-
Notifications
You must be signed in to change notification settings - Fork 112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CRM-21489 fix DatabaseObject code to retry when deadlock is met. #197
Conversation
c1a1973
to
c934761
Compare
(CiviCRM Review Template DEL-1.0)
It's probably also a good idea to throw a better described exception than re-throwing 'DB Error: Unknown Error' |
DB/DataObject.php
Outdated
if (!stristr($e->getCause()->getUserInfo(), 'nativecode=1205') || ($tries + 1) === $maxTries) { | ||
throw $e; | ||
} | ||
CRM_Core_Error::debug_log_message('Retrying after deadlock hit on attempt ' . $tries + 1 . ' at query : ' . $string); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This didn't work properly for me with PHP 7 - .
and +
seem to have the same precendence, so the output was always 1 at query: ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah - the wrong thing in the log - so it should be like the line above?
d12daec
to
f1225ee
Compare
@agileware-fj I have pushed fixes to address the issues that are in this repo (the settings file is in civicrm-core). Note to self. Never call a branch 'dead'. issuing the following command is disconcerting: git push -f eileen dead |
& here is the other PR I don't really know the convention for the template - editing it to 'pass' once the things in it have been addressed loses history, but otherwise it looks like the review is incomplete ... @totten @seanmadsen |
1c02211
to
57cf229
Compare
DB/DataObject.php
Outdated
throw $e; | ||
} | ||
if (($tries + 1) === $maxTries) { | ||
$message = (stristr($dbErrorMessage, 'nativecode=1213') ? 'Database deadlock encountered' : 'Database lock encountered'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bgm - I'm never sure if we are supposed to ts() exception messages. In this case it's not one we would hope the user saw except very rarely
57cf229
to
4c7af3b
Compare
This is restoring previous functionality broken when we meddled with deadlocks.
4c7af3b
to
9fdcc07
Compare
(CiviCRM Review Template DEL-1.0)
|
I think that's how I've seen it done elsewhere. |
We've been testing this pretty heavily on our staging too & it's had some internal review (hence minor changes). I tested it by running a query that took several minutes CREATE TABLE hurt_my_server SELECT * FROM civicrm_email and then in another session running a batch merge job. The latter hit the big query and had a couple of retries, then the big query ended and the batch merge finished. |
We're running this on production and it seems fine. I modified it to post in a slack channel for every retry, so I can see them happening in real-time. I've seen it loop multiple times when needed. |
I should also note we have had this in production since it was submitted. |
AUG has been running this in our production for the last few weeks and have had good experience with this. i am a +1 for merging |
This is restoring previous functionality broken when we meddled with deadlocks.
The Database class has handling in it for deadlocks but some time ago, likely around 4.2, we introduced changes that cause it to be bypassed. When
$result = $DB->query($string)
is called & there is a deadlock, it used to return a PEAR_Error object. If the $result was a PEAR_Error then 3 retries were attempted.
However, we made changes to exception handling a while back (around 4.2 I think) that meant that an exception was thrown, by-passing the retry code.
Since this is an unmaintained (& previously hacked) package I think we just patch our version & I propose that we also add a Constant to allow sites to specify the number of retries. This is pretty low-level developer stuff so I don't propose a setting, although some helper text can go in civicrm.settings.php on new installs.
Note re doing retries - from mysql docs
https://dev.mysql.com/doc/refman/5.7/en/innodb-deadlocks-handling.html
"Deadlocks are a classic problem in transactional databases, but they are not dangerous unless they are so frequent that you cannot run certain transactions at all. Normally, you must write your applications so that they are always prepared to re-issue a transaction if it gets rolled back because of a deadlock."
Replication
Note I simulated a deadlock by hacking website_get api with this
function civicrm_api3_website_get($params) {
CRM_Core_DAO::executeQuery('START TRANSACTION');
CRM_Core_DAO::executeQuery('SELECT * FROM civicrm_email WHERE id = 24220 LOCK IN SHARE MODE');
sleep(2000);
and calling it from another browser