Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

DBI keep alive

by Anonymous Monk
on Aug 09, 2024 at 17:00 UTC ( [id://11160963]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Sup Monks! I have some question about DBI module, but first lets see what we have

minimally reproducible example:

#!/usr/bin/perl use strict; use warnings; use DBI; # Database connection details my $dsn = 'DBI:mysql:database=testdb;host=mysql-test.local.priv;mysql_ +write_timeout=2;mysql_read_timeout=2;mysql_connect_timeout=2'; my $username = 'test_user'; my $password = '12345'; # Connect to the MySQL database my $dbh = DBI->connect($dsn, $username, $password, { mysql_enable_utf8 => 1, }); $dbh->{mysql_auto_reconnect} = 1; # Check if the connection was successful if (!$dbh) { die "Could not connect to database: $DBI::errstr"; } # Sleep for 40 minutes print "Sleeping for 40 minutes...\n"; sleep(40 * 60); # 40 minutes # Execute the query my $sth = $dbh->prepare('SELECT 1 FROM dual'); $sth->execute(); # Fetch and print the result while (my @row = $sth->fetchrow_array) { print "Result: @row\n"; } # Clean up $sth->finish(); $dbh->disconnect(); print "Done.\n";

Environments:

1. Debian 12.6 Perl : 5.036000 (x86_64-linux-gnu-thread-multi) OS : linux (4.19.0) DBI : 1.643 DBD::mysql : 4.050 2. CentOS Linux release 7.9.2009 Perl : 5.016003 (x86_64-linux-thread-multi) OS : linux (3.10.0-957.1.3.el7.x86_64) DBI : 1.627 DBD::mysql : 4.023 3. Mysql Maxscale router
So-o-o-o, all my live i used centos 7 and there, when i try to execute this script, after 30 minutes of idle, maxscale kills the session cuz it should, BUT the script actually doesn't see it, i don't know how to explain, i just didn't get an error, it reconnects automatically and just work like a charm. Let me show you output of strace:
strace: Process 204408 attached + + restart_syscall(<... resuming interrupted read ...>) = 0 + + poll([{fd=3, events=POLLIN|POLLPRI}], 1, 0) = 1 ([{fd=3, revents=POLLI +N}]) + read(3, "=\0\0\0\377\207\7#08S01Connection killed b"..., 8192) = 65 + + poll([{fd=3, events=POLLIN|POLLPRI}], 1, 0) = 1 ([{fd=3, revents=POLLI +N}]) + read(3, "", 8192) = 0 + + shutdown(3, SHUT_RDWR) = 0 + + close(3) = 0 + + socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3 + + fcntl(3, F_SETFL, O_RDONLY) = 0 + + fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) + + fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) + + fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 + + connect(3, {sa_family=AF_INET, sin_port=htons(3306), sin_addr=inet_add +r("192.168.1.1")}, 16) = -1 EINPROGRESS (Operation now in progress) + fcntl(3, F_SETFL, O_RDWR) = 0 + + poll([{fd=3, events=POLLIN|POLLPRI}], 1, 2000) = 1 ([{fd=3, revents=PO +LLIN}]) + getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 + + setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, "\2003\341\1\0\0\0\0\0\0\0\0\0\ +0\0\0", 16) = 0 + setsockopt(3, SOL_SOCKET, SO_SNDTIMEO, "\2003\341\1\0\0\0\0\0\0\0\0\0\ +0\0\0", 16) = 0 + setsockopt(3, SOL_IP, IP_TOS, [8], 4) = 0 + + setsockopt(3, SOL_TCP, TCP_NODELAY, [1], 4) = 0 + + setsockopt(3, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0 + + setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, "\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0 +\0", 16) = 0 + setsockopt(3, SOL_SOCKET, SO_SNDTIMEO, "\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0 +\0", 16) = 0 + poll([{fd=3, events=POLLIN}], 1, 2000) = 1 ([{fd=3, revents=POLLIN}]) + + read(3, "S\0\0\0\n5.6.38-83.0-log\0\33P\273\31U\37#KDU?"..., 16384) = +87 + write(3, "a\0\0\1\217\242\16\0\0\0\0@!\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 +\0\0\0"..., 101) = 101 + read(3, "\7\0\0\2\0\0\0\2\0\0\0", 16384) = 11 + + poll([{fd=3, events=POLLIN|POLLPRI}], 1, 0) = 0 (Timeout) + + write(3, "\23\0\0\0\3SELECT 1 FROM dual", 23) = 23 + + read(3, "\1\0\0\1\1\27\0\0\2\3def\0\0\0\0011\0\f?\0\1\0\0\0\10\201\0\0 +\0\0"..., 16384) = 56 + write(1, "Result: 1\n", 10) = 10 + + write(3, "\1\0\0\0\1", 5) = 5 + + shutdown(3, SHUT_RDWR) = 0 + + close(3) = 0 + + write(1, "Done.\n", 6) = 6 ...
as you can see here, we get an error "Connection killed by MaxScale: Timed out by MaxScale", and then it tries to reconnect and repeat the query. BUT in debian it doesn't. So my question is: Why? Why it returns me an error "Connection killed by MaxScale: Timed out by MaxScale" and didn't even try to reconnect how it is on Centos? How can i keep alive connections?

Replies are listed 'Best First'.
Re: DBI keep alive
by Corion (Patriarch) on Aug 09, 2024 at 20:44 UTC

    The module versions are all different between your machines. As a first step, I would try to make all module (and other library) versions similar to each other by installing the appropriate modules.

Re: DBI keep alive
by talexb (Chancellor) on Aug 09, 2024 at 20:30 UTC

    It looks like you're a) connecting to the database, b) sleeping for 40 minutes, and then c) trying to run a query, which fails under some circumstances.

    It feels like you're trying to reproduce something that you haven't told us about. Why would you connect to a database and then sleep for 40 minutes?

    How about a) connecting, then b) loop 40 times, doing a ping on the database handle after sleeping for a minute, and finally c) running the query. I'm guessing that would have a better chance of working, but have no idea what's behind the curtain.

    Alex / talexb / Toronto

    Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.

Re: DBI keep alive
by NERDVANA (Curate) on Aug 10, 2024 at 23:59 UTC
    MySQL dropping connections is a frequent problem, so much so that the DBD::mysql driver has that feature built-in to reconnect. It looks like you fund that feature and have it enabled and working in the example.

    You gave an example of it working, so that doesn't give us much to figure out the one that doesn't work. One thing that prevents the auto-reconnect is if you left a transaction open. DBD::mysql can only retry one query after auto-reconnect, so it can't get a new transaction back to the state it was in before the disconnect, so it doesn't try.

    For web apps, if DBD::mysql isn't reconnecting automatically, you could call eval { $conn->ping } at the start of the request, and you could even call ->connect again if that fails.

    As it happens, just about 3 weeks ago I was trying to *disable* the mysql auto-reconnect because I wanted to know when there was a new connection ID, to have the ability to log and kill long-running queries associated with a user account. Setting {mysql_auto_reconnect}= 0 had no effect. I didn't get around to reporting that bug yet. Maybe that bug is related to the problem you're having on Debian.

Re: DBI keep alive
by Anonymous Monk on Aug 12, 2024 at 18:37 UTC
    Sup Monks! Thanks to everyone for the advice and especially NERDVANA. Yes, indeed, i have tried to disable AutoCommit and mysql_auto_reconnect on Centos and after that it didn't try to reconnect, BUT in Debian it just doesn't work, no matter if you enable it or disable it. So it seems to me, that we have a bug here.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11160963]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (4)
As of 2024-09-07 23:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.