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

Monks,

I have inherited some SQL and would like some input.

I am processing some cable modem stats. Client machine is Windows Server 2008 R2, ActivePerl 5.8, using the ODBC Data Source Administrator control panel.

Script runs fine, but occasionally it exits with the following:

DBD::ODBC::st execute failed: [MySQL][ODBC 5.1 Driver][mysqld-5.1.45-community-log]Lost connection to MySQL server during query (SQL-08S01) at load_modem.wpl line 255.

Please note: I respect the Monastery's preference for actual code, but in interest of inappropriate disclosure, I have modified the following slightly. The logic has not been altered.

use strict; use warnings; use DBI; my $dbh = DBI->connect("dbi:ODBC:MySQL_for_modem"); $dbh->{LongReadLen} = 512 * 1024; $dbh->{LongTruncOk} = 1; my $sql_region_id = "select distinct region_id from config.object "; my $sql_statement = "select info from database"; unless ( $region_cursor = $dbh->prepare( "$sql_region_id" )){ exit 1; } unless ( $region_cursor->execute ) { exit 2; } $region_cursor->bind_columns(\($region_id)); while( $region_cursor->fetch() ){ unless ( $cursor = $dbh->prepare( "$sql_statement" )) { exit 1; } unless ( $cursor->execute($region_id) ) { # <-- line 255 in the sc +ript exit 2; } $cursor->bind_columns(\( $modem_ip, etc... )); while( $cursor->fetch() ) { process the stats... } }

Given that I have no control over the server that I am querying, what is the best way to have the script carry on? ie: instead of the exits (or dies if I replace them), what is a clean way to reconnect and and continue?

As always, thanks for any help and references...

Scott...

Replies are listed 'Best First'.
Re: Lost connection to MySQL server
by onelesd (Pilgrim) on Aug 30, 2011 at 05:49 UTC

    You can disable DBI from raising exceptions on errors. The error message might be helpful (if there is one).

    $dbh->{RaiseError} = 0 ; # don't raise exception on error $dbh->{PrintError} = 1 ; # print errors to console $cursor->execute($region_id) or warn $DBI::errstr, "\n" ;
      Thanks - I will incorporate that...
Re: Lost connection to MySQL server
by Neighbour (Friar) on Aug 30, 2011 at 06:50 UTC
    You can't execute a second query while still fetching the results of an earlier query. (At least, this was the case a year ago when I last tried that). You might want to use $dbh->selectall_arrayref or $dbh->selectall_hashref to fetch the data of your first query.
    Also, You are passing a parameter ($region_id) to the second query when executing it, but no placeholders are defined in the second query ($sql_statement).

      Thank you - that's an excellent lead. I'll give the $dbh->selectall_arrayref a shot.

      Re: the placeholder - thanks for the catch, but I had been too sloppy in editing the original code. There is indeed a placeholder:

      my $sql_region_id = "select distinct k.id from config.object o join config.location l on l.id=o.location join config.location k on k.id=l.region order by k.id desc"; my $sql_statement = "select x.ip, m.modemmacaddress, m.date_time, m.cmtsrxsnr, m.cmtsrxpower, m.modemrxsnr, m.modemrxpower, m.modemtxpower, m.microreflections, m.corrected, m.uncorrectable, a.node, a.addr, a.street, a.city, a.state, a.zip5, k.name, i.ifDescr from config.object o join config.location l on l.id = o.location join config.location k on k.id = l.region and k.id = ? join nemos.arp x on o.id = x.object join modem_hist.mh_day_0 m on m.cmtsid = x.object and m.modemmacaddre +ss = x.mac join cust.equipment e on e.mac = x.mac join cust.addr a on a.acct = e.acct join config.ifdrum i on i.object=o.id and i.ifdrum = x.ifdrum where o.community is not null and i.ifindex > 0 and (m.modemtxpower < -15 or m.modemtxpower > 55) or (m.modemrxsnr < 28) or (m.modemrxpower < -12 or m.modemrxpower > 12) or (m.cmtsrxsnr < 25) or (m.microreflections > 40) "; unless ( $region_cursor = $dbh->prepare( "$sql_region_id" )){ exit 1; } unless ( $region_cursor->execute ) { exit 2; } $region_cursor->bind_columns(\($region_id)); while( $region_cursor->fetch() ){ unless ( $cursor = $dbh->prepare( "$sql_statement" )) { exit 1; } unless ( $cursor->execute($region_id) ) { exit 2; } while( $cursor->fetch() ) { do stuff... } }

      I do not find it to be the case, i.e. categorically, that “you can’t execute another query while you are fetching the results of an earlier one.”   (In fact, I just did it.)   As long as you are careful to use two separate statement-handles, it is perfectly okay to, for example, loop through one query and select each of the records in turn that are mentioned in that query.

      I am therefore quite sure that I misunderstood the subtle point you were trying to make – which, I am entirely certain, must indeed have been correct or of course you wouldn’t have said it.   Therefore, could you please clarify your point?   An example of the specific “gotcha” that you are elucidating?   Thanks.

        Perhaps Neighbour mixed up MySQL and MS-SQL? MS SQL Server's protocol is limited to one active statement handle per connection. (Recent versions add some dirty tricks to overcome this limit, but they require non-portable, specially crafted code.) DBI has no such limits, neither has DBD::ODBC; and I can't find a hint in the documentation of DBD::mysql that it is limited to a single active statement.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: Lost connection to MySQL server
by locked_user sundialsvc4 (Abbot) on Aug 29, 2011 at 22:04 UTC

    Since “lost connection” is a highly unusual occurrence, yet one which seems to happen to you regularly-enough to mention, I suggest that you need to get to the bottom of this.   Perhaps, for instance, you are trying to send too much BLOB-data at one time and you are overflowing some buffer and in response MySQL is cutting you off.   Like I said, you need to dig deep enough to find out why this is happening to you and to your program, before you start to try to develop an appropriate solution.   Oh, you might manage to find “a Band-Aid® That Seems To Work,” but it is a faux quest.   Forsooth, if you have not unearthed the root cause, your headaches and heartburn will not end.

      I agree. No BLOB data, though. This is all cable modem data initially acquired via SNMP. I'm hoping that Neighbour's note that you can't execute a second query while still fetching the results of an earlier query is at the root.

Re: Lost connection to MySQL server
by Neighbour (Friar) on Aug 31, 2011 at 06:59 UTC
    By the way, is there a specific reason you're accessing MySQL using ODBC instead of DBD::MySQL?
    Also, how much time passes between executing the query and getting the disconnection errormessage? Is this a timeout present in the ODBC-layer (since the server would normally not disconnect connections that are waiting for a query result)?