-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Short description of the issue
When a request takes too long, the MySQL server goes away thus making the next query fail. The execute
function's comment states that it "will retry queries if they failed due to a lost connection", however it seems it just retries the query, which is still linked to the connection that has gone away.
Expected behavior
Even though we could play with the MySQL wait_timeout
setting, it is not necessarily possible in some cases (e.g. shared hosting), making the retry aspect of Processwire's PDO highly valuable. But it doesn't work here.
From my understanding, once it detects a fail / retries, it should first re-create the connection and then re-construct the query based on this new connection.
Suggestion for a possible fix
What I tried to do, and seemed to work at first, was adding this code before the line 583:
if ($tryAgain > 0) {
$newQuery = $this->wire('database')->prepare($query->queryString);
foreach ($query->getParams() as $value) {
$newQuery->bindValue($value["parameter"], $value["value"], $value["data_type"]);
}
$query = $newQuery;
}
Two things to note: I had to make every PDOStatement a WireDatabasePDOStatement, and in the WireDatabasePDOStatement file I created a params
var populated with the values binded in the bindValue
function:
$this->params[] = [
"parameter" => $parameter,
"value" => $value,
"data_type" => $data_type,
];
And accessible with the getParams
function mentionned above.
However, even if it worked for my code below (in the "Step to reproduce the issue"), I still had the 2006 MySQL error afterwards at this line.
Side note: this second error led me to the DatabaseQuery file which seems to provide the abstraction for what I'm describing above...? So maybe it could be there that we should retry the query ? I don't know at this point if every query in PW is a DatabaseQuery or not.
Step to reproduce the issue
Here is a code sample that triggers this error:
$page->of(false);
$title = $page->title;
$page->title = "Error";
$page->save();
sleep(60); // adjust according to your server's wait_timeout setting
$page->title = $title;
$page->save();
Setup/Environment
Server Details
Software | Version |
---|---|
ProcessWire | 3.0.165 |
PHP | 7.3.25 |
Webserver | Apache |
MySQL Server | 5.7.30-log |
MySQL Client | mysqlnd 5.0.12-dev - 20150407 - |
Server Settings
Parameter | Value |
---|---|
allow_url_fopen | |
max_execution_time | 60 (changeable) |
max_input_nesting_level | 64 |
max_input_time | 0 |
max_input_vars | 3000 |
memory_limit | 640M |
post_max_size | 300M |
upload_max_filesize | 300M |
xdebug | |
xdebug.max_nesting_level | |
mod_rewrite | |
mod_security | |
EXIF Support | 1 |
FreeType | 1 |
GD Settings
Parameter | Value |
---|---|
Version | bundled (2.1.0 compatible) |
GIF | 1 |
JPG | 1 |
PNG | 1 |
WebP | 1 |
iMagick Settings
Parameter | Value |
---|---|
Version | 6.8.9 |
GIF | 1 |
JPG | 1 |
PNG | 1 |
SVG | 1 |
1 | |
WebP |
Module Details
Module ClassName | Version |
---|---|
AdminThemeUikitModified | 0.3.1 |
ImageCreateVariations | 1.0.0 |
ProcessTracyAdminer | 1.0.7 |
TracyDebugger | 4.21.23 |