From 867b1ffbac476a02d05cc85d485c3bef35f4b3f1 Mon Sep 17 00:00:00 2001 From: Office <11071985+kkmuffme@users.noreply.github.com> Date: Wed, 8 Jan 2025 23:01:21 +0100 Subject: [PATCH 1/3] Fix unnecessary pings * queries slower than heartbeat recheck_timeout would trigger unnecessary heartbeat pings * unnecessary heartbeat pings after we just pinged if less servers than retries * fix if ping (e.g. due to network congestion or physical distance) would exceed recheck_timeout --- ludicrousdb/includes/class-ludicrousdb.php | 55 +++++++++++++++++----- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/ludicrousdb/includes/class-ludicrousdb.php b/ludicrousdb/includes/class-ludicrousdb.php index c125dcd..a178601 100644 --- a/ludicrousdb/includes/class-ludicrousdb.php +++ b/ludicrousdb/includes/class-ludicrousdb.php @@ -1340,6 +1340,8 @@ protected function single_db_connect( $dbhname, $host, $user, $password ) { return false; } + + $this->update_heartbeat( $dbhname ); } /** @@ -1401,7 +1403,9 @@ public function set_sql_mode( $modes = array(), $dbh_or_table = false ) { $modes_str = implode( ',', $modes ); - mysqli_query( $dbh, "SET SESSION sql_mode='{$modes_str}'" ); + if ( mysqli_query( $dbh, "SET SESSION sql_mode='{$modes_str}'" ) ) { + $this->update_heartbeat( $dbh ); + } } /** @@ -1427,6 +1431,10 @@ public function select( $db, $dbh_or_table = false ) { $success = mysqli_select_db( $dbh, $db ); + if ( $success ) { + $this->update_heartbeat( $dbh ); + } + return $success; } @@ -1608,6 +1616,7 @@ public function check_connection( $die_on_disconnect = true, $dbh_or_table = fal && mysqli_ping( $dbh ) ) { + $this->update_heartbeat( $dbh ); return true; } @@ -1931,17 +1940,7 @@ protected function _do_query( $query, $dbh_or_table = false ) { // phpcs:ignore } } - // Maybe log last used to heartbeats - if ( ! empty( $this->check_dbh_heartbeats ) ) { - - // Lookup name - $name = $this->lookup_dbhs_name( $dbh ); - - // Set last used for this dbh - if ( ! empty( $name ) ) { - $this->dbhname_heartbeats[ $name ]['last_used'] = microtime( true ); - } - } + $this->update_heartbeat( $dbh ); return $result; } @@ -2146,6 +2145,8 @@ public function db_server_info( $dbh_or_table = false ) { $server_info = mysqli_get_server_info( $dbh ); + $this->update_heartbeat( $dbh ); + return $server_info; } @@ -2789,6 +2790,36 @@ protected function tcp_cache_delete( $key = '' ) { return true; } + /** + * Update the heartbeat + * + * @param string|object $dbhname_or_dbh To update the heartbeat for + * + * @return void + */ + protected function update_heartbeat( $dbhname_or_dbh ) { + if ( ! $this->check_dbh_heartbeats ) { + return; + } + + if ( is_string( $dbhname_or_dbh ) ) { + $dbhname = $dbhname_or_dbh; + } else { + $dbhname = $this->lookup_dbhs_name( $dbhname_or_dbh ); + } + + // Set last used for this dbh + if ( empty( $dbhname ) ) { + return; + } + + if ( ! isset( $this->dbhname_heartbeats[ $dbhname ] ) ) { + $this->dbhname_heartbeats[ $dbhname ] = array(); + } + + $this->dbhname_heartbeats[ $dbhname ]['last_used'] = microtime( true ); + } + /** * Find a dbh name value for a given $dbh object. * From a13d6a07fc1a32b3349909e47150efbaf42d5936 Mon Sep 17 00:00:00 2001 From: Office <11071985+kkmuffme@users.noreply.github.com> Date: Wed, 8 Jan 2025 23:45:08 +0100 Subject: [PATCH 2/3] retry/ping if server went away but heartbeats are disabled to ensure the server will not be reused and disconnected --- ludicrousdb/includes/class-ludicrousdb.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ludicrousdb/includes/class-ludicrousdb.php b/ludicrousdb/includes/class-ludicrousdb.php index a178601..046154d 100644 --- a/ludicrousdb/includes/class-ludicrousdb.php +++ b/ludicrousdb/includes/class-ludicrousdb.php @@ -2366,13 +2366,19 @@ public function run_query_log_callbacks( $query = '', $retval = null ) { * @return bool True if we should try to ping the MySQL host, false otherwise. */ public function should_mysql_ping( $dbhname = '' ) { + if ( empty( $dbhname ) ) { + return false; + } - // Return false if empty handle or checks are disabled if ( - empty( $dbhname ) - || empty( $this->check_dbh_heartbeats ) + && + in_array( mysqli_errno( $this->dbhs[ $dbhname ] ), array( 2006, 4031 ), true ) ) { + return true; + } + + if ( empty( $this->check_dbh_heartbeats ) ) { return false; } From 11597544f2817d37d6f16e9bda8cd8e30dc98bc1 Mon Sep 17 00:00:00 2001 From: Office <11071985+kkmuffme@users.noreply.github.com> Date: Wed, 8 Jan 2025 23:47:04 +0100 Subject: [PATCH 3/3] retry the query --- ludicrousdb/includes/class-ludicrousdb.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ludicrousdb/includes/class-ludicrousdb.php b/ludicrousdb/includes/class-ludicrousdb.php index 046154d..2b5c8b5 100644 --- a/ludicrousdb/includes/class-ludicrousdb.php +++ b/ludicrousdb/includes/class-ludicrousdb.php @@ -1812,6 +1812,20 @@ public function query( $query ) { ++$this->num_queries; + $mysql_errno = mysqli_errno( $this->dbh ); + if ( $mysql_errno && ! empty( $this->check_dbh_heartbeats ) ) { + $dbhname = $this->lookup_dbhs_name( $this->dbh ); + + if ( ! empty( $dbhname ) ) { + $this->dbhname_heartbeats[ $dbhname ]['last_errno'] = $mysql_errno; + } + } + + // retry the server and all other servers if the connection went away + if ( in_array( $mysql_errno, array( 2006, 4031 ), true ) ) { + return $this->query( $query ); + } + if ( preg_match( '/^\s*SELECT\s+([A-Z_]+\s+)*SQL_CALC_FOUND_ROWS\s/i', $query ) ) { if ( false === strpos( $query, 'NO_SELECT_FOUND_ROWS' ) ) { $this->timer_start();