Last active
August 29, 2015 14:01
-
-
Save zerolab/8b2531599bff611942ae to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/includes/database.mysqli.inc b/includes/database.mysqli.inc | |
index e208a66..e4eb6a5 100644 | |
--- a/includes/database.mysqli.inc | |
+++ b/includes/database.mysqli.inc | |
@@ -133,34 +133,72 @@ function _db_query($query, $debug = 0, $slave = FALSE) { | |
$query = '/* '. $name .' : '. $bt[2]['function'] .' */ '. $query; | |
} | |
- $sent_to_slave = FALSE; | |
- if (isset($active_slave_db) && $slave) { | |
- $result = mysqli_query($active_slave_db, $query); | |
- $sent_to_slave = TRUE; | |
- } | |
- else { | |
- $result = mysqli_query($active_db, $query); | |
- } | |
+ $retry = 0; | |
+ do { | |
+ $sent_to_slave = FALSE; | |
+ if (isset($active_slave_db) && $slave) { | |
+ $result = mysqli_query($active_slave_db, $query); | |
+ $errno = mysqli_errno($active_slave_db); | |
+ $sent_to_slave = TRUE; | |
+ } | |
+ else { | |
+ $result = mysqli_query($active_db, $query); | |
+ $errno = mysqli_errno($active_db); | |
+ } | |
- if (variable_get('dev_query', 0)) { | |
- $query = $bt[2]['function'] ."\n". $query; | |
- list($usec, $sec) = explode(' ', microtime()); | |
- $stop = (float)$usec + (float)$sec; | |
- $diff = $stop - $timer; | |
- $queries[] = array($query, $diff, $sent_to_slave); | |
- } | |
+ if (variable_get('dev_query', 0)) { | |
+ $query = $bt[2]['function'] ."\n". $query; | |
+ list($usec, $sec) = explode(' ', microtime()); | |
+ $stop = (float)$usec + (float)$sec; | |
+ $diff = $stop - $timer; | |
+ $queries[] = array($query, $diff, $sent_to_slave); | |
+ } | |
+ | |
+ // Handle transient errors. | |
+ // If we can handle this error, then increment the counter, so we run again. Otherwise | |
+ // use the default case to exit the while loop and return an error as per normal. | |
+ switch($errno) { | |
+ case 1153: // Got a packet bigger than "max_allowed_packet" bytes | |
+ // If the MySQL Server rejected the query because it's too big, | |
+ // writing the query to database watchdog will fail as well | |
+ // Truncate the query ... | |
+ $retry = 2; | |
+ $query = substr($query, 0, 100); | |
+ break; | |
+ | |
+ case 1205: // Lock wait timeout exceeded; try restarting transaction | |
+ case 1213: // Deadlock found when trying to get lock; try restarting transaction | |
+ $retry++; // Increment counter. | |
+ break; | |
+ | |
+ case 1614: // Transaction branch was rolled back: deadlock was detected | |
+ case 2013: // Lost connection to MySQL server during query | |
+ $retry++; // Increment counter. | |
+ if ($sent_to_slave) { | |
+ $slave = FALSE; // Retry on master. | |
+ } | |
+ break; | |
+ | |
+ // If not an error we can handle (or not an error!) exit the loop. | |
+ // We cal deal with fall-out later, as errno is set. | |
+ default: | |
+ $retry = 2; | |
+ break; | |
+ } | |
+ | |
+ if (!$sent_to_slave) { | |
+ $active_last_db = $active_db; | |
+ } else { | |
+ $active_last_db = $active_slave_db; | |
+ } | |
+ } while ($retry < 2); | |
- if (!$sent_to_slave) { | |
- $active_last_db = $active_db; | |
- } else { | |
- $active_last_db = $active_slave_db; | |
- } | |
if ($debug) { | |
print '<p>query: '. $query .'<br />error:'. mysqli_error($active_db) .'</p>'; | |
} | |
- if (!mysqli_errno($active_last_db)) { | |
+ if (!$errno) { | |
return $result; | |
} | |
else { | |
diff --git a/includes/database.mysql.inc b/includes/database.mysql.inc | |
index acad975..f53daa5 100644 | |
--- a/includes/database.mysql.inc | |
+++ b/includes/database.mysql.inc | |
@@ -134,34 +134,71 @@ function _db_query($query, $debug = 0, $slave = FALSE) { | |
$query = '/* '. $name .' : '. $bt[2]['function'] .' */ '. $query; | |
} | |
- $sent_to_slave = FALSE; | |
- if (isset($active_slave_db) && $slave) { | |
- $result = mysql_query($query, $active_slave_db); | |
- $sent_to_slave = TRUE; | |
- } | |
- else { | |
- $result = mysql_query($query, $active_db); | |
- } | |
+ $retry = 0; | |
+ do { | |
+ $sent_to_slave = FALSE; | |
+ if (isset($active_slave_db) && $slave) { | |
+ $result = mysql_query($query, $active_slave_db); | |
+ $errno = mysql_errno($active_slave_db); | |
+ $sent_to_slave = TRUE; | |
+ } | |
+ else { | |
+ $result = mysql_query($query, $active_db); | |
+ $errno = mysql_errno($active_db); | |
+ } | |
- if (variable_get('dev_query', 0)) { | |
- $query = $bt[2]['function'] ."\n". $query; | |
- list($usec, $sec) = explode(' ', microtime()); | |
- $stop = (float)$usec + (float)$sec; | |
- $diff = $stop - $timer; | |
- $queries[] = array($query, $diff, $sent_to_slave); | |
- } | |
+ if (variable_get('dev_query', 0)) { | |
+ $query = $bt[2]['function'] ."\n". $query; | |
+ list($usec, $sec) = explode(' ', microtime()); | |
+ $stop = (float)$usec + (float)$sec; | |
+ $diff = $stop - $timer; | |
+ $queries[] = array($query, $diff, $sent_to_slave); | |
+ } | |
- if (!$sent_to_slave) { | |
- $active_last_db = $active_db; | |
- } else { | |
- $active_last_db = $active_slave_db; | |
- } | |
+ // Handle transient errors. | |
+ // If we can handle this error, then increment the counter, so we run again. Otherwise | |
+ // use the default case to exit the while loop and return an error as per normal. | |
+ switch($errno) { | |
+ case 1153: // Got a packet bigger than "max_allowed_packet" bytes | |
+ // If the MySQL Server rejected the query because it's too big, | |
+ // writing the query to database watchdog will fail as well | |
+ // Truncate the query ... | |
+ $retry = 2; | |
+ $query = substr($query, 0, 100); | |
+ break; | |
+ | |
+ case 1205: // Lock wait timeout exceeded; try restarting transaction | |
+ case 1213: // Deadlock found when trying to get lock; try restarting transaction | |
+ $retry++; // Increment counter. | |
+ break; | |
+ | |
+ case 1614: // Transaction branch was rolled back: deadlock was detected | |
+ case 2013: // Lost connection to MySQL server during query | |
+ $retry++; // Increment counter. | |
+ if ($sent_to_slave) { | |
+ $slave = FALSE; // Retry on master. | |
+ } | |
+ break; | |
+ | |
+ // If not an error we can handle (or not an error!) exit the loop. | |
+ // We cal deal with fall-out later, as errno is set. | |
+ default: | |
+ $retry = 2; | |
+ break; | |
+ } | |
+ | |
+ if (!$sent_to_slave) { | |
+ $active_last_db = $active_db; | |
+ } else { | |
+ $active_last_db = $active_slave_db; | |
+ } | |
+ } while ($retry < 2); | |
if ($debug) { | |
print '<p>query: '. $query .'<br />error:'. mysql_error($active_db) .'</p>'; | |
} | |
- if (!mysql_errno($active_last_db)) { | |
+ if (!$errno) { | |
return $result; | |
} | |
else { |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment