Thomas Bruederli
2013-09-12 0ee22c2145482571014d843ffa899ef579317eb7
Retry queries on deadlock errors from InnoDB row-level locking (MySQL)
2 files modified
47 ■■■■■ changed files
program/lib/Roundcube/rcube_db.php 22 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_db_mysql.php 25 ●●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_db.php
@@ -386,6 +386,23 @@
        $result = $this->dbh->query($query);
        if ($result === false) {
            $result = $this->handle_error($query);
        }
        $this->last_result = $result;
        return $result;
    }
    /**
     * Helper method to handle DB errors.
     * This by default logs the error but could be overriden by a driver implementation
     *
     * @param string Query that triggered the error
     * @return mixed Result to be stored and returned
     */
    protected function handle_error($query)
    {
            $error = $this->dbh->errorInfo();
            if (empty($this->options['ignore_key_errors']) || $error[0] != '23000') {
@@ -397,11 +414,8 @@
                    'message' => $this->db_error_msg . " (SQL Query: $query)"
                    ), true, false);
            }
        }
        $this->last_result = $result;
        return $result;
        return false;
    }
    /**
program/lib/Roundcube/rcube_db_mysql.php
@@ -179,4 +179,29 @@
        return isset($this->variables[$varname]) ? $this->variables[$varname] : $default;
    }
    /**
     * Handle DB errors, re-issue the query on deadlock errors from InnoDB row-level locking
     *
     * @param string Query that triggered the error
     * @return mixed Result to be stored and returned
     */
    protected function handle_error($query)
    {
        $error = $this->dbh->errorInfo();
        // retry after "Deadlock found when trying to get lock" errors
        $retries = 2;
        while ($error[1] == 1213 && $retries >= 0) {
            usleep(50000);  // wait 50 ms
            $result = $this->dbh->query($query);
            if ($result !== false) {
                return $result;
            }
            $error = $this->dbh->errorInfo();
            $retries--;
        }
        return parent::handle_error($query);
    }
}