2016-04-08 18 views
0

Ich habe gekämpft, um ein Deadlock-Problem zu bekommen, die wir haben, wenn wir einige Spalten materialisieren, wenn etwas anderswo in der Datenbank geändert hat.MySQL Deadlock bei der Aktualisierung der gesamten Tabelle

Im Wesentlichen setzt die Materialisierungsroutine die relevanten Spalten auf NULL zurück und fügt bei Bedarf Werte hinzu (wie bei den meisten Elementen bleiben die Spalten NULL).

Hier ein paar Beispielabfragen:

UPDATE `component_instances` SET `view_user_ids` = NULL, `edit_user_ids` = NULL ORDER BY component_instances.ancestry, position 

UPDATE `component_instances` SET `edit_user_ids` = '9,6' WHERE (((`component_instances`.`id` = 3 OR `component_instances`.`ancestry` LIKE '1/3/%') OR `component_instances`.`ancestry` = '1/3')) ORDER BY component_instances.ancestry, position 

ich nur das Problem in der Produktion gesehen habe (es schwieriger zu beheben machen), und es kommt viel öfter, als ich die Materialisierung als Teil der do Anfrage, die die anderen verwandten Daten geändert hat, als es tut, wenn ich es als delayed_job Warteschlange kurz nachdem die Anfrage beendet wurde.

Meine einzigen Ideen sind die Reihenfolge zu entfernen, die in diesen Fällen keine Rolle spielt. Und möglicherweise auf Indizes schauen?

Ich habe eine Ahnung, dass es passiert, wenn mehrere Anfragen diese Materialisierungen ungefähr zur gleichen Zeit auslösen und sie sich gegenseitig auf die Füße treten?

Bitte lassen Sie mich wissen, welche anderen Informationen nützlich sein werden zu wissen.

UPDATE

Hier ist der Ausgang (oder der Beginn davon) von SHOW ENGINE INNODB STATUS:

LATEST DETECTED DEADLOCK 
------------------------ 
160406 23:03:05 
*** (1) TRANSACTION: 
TRANSACTION 3A787847, ACTIVE 0 sec starting index read 
mysql tables in use 1, locked 1 
LOCK WAIT 5 lock struct(s), heap size 1248, 4 row lock(s) 
MySQL thread id 437042, OS thread handle 0x7f488b80c700, query id 13820202 localhost xxxxxxxxxxxx init 
UPDATE `component_instances` SET `edit_user_ids` = '3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,26,29,30,35,37,38,39,40' WHERE (((`component_instances`.`id` = 125 OR `component_instances`.`ancestry` LIKE '1/14/22/125/%') OR `component_instances`.`ancestry` = '1/14/22/125')) ORDER BY component_instances.ancestry, position 
*** (1) WAITING FOR THIS LOCK TO BE GRANTED: 
RECORD LOCKS space id 0 page no 124313 n bits 152 index `PRIMARY` of table `450273b5d362920c`.`component_instances` trx id 3A787847 lock_mode X locks rec but not gap waiting 
Record lock, heap no 19 PHYSICAL RECORD: n_fields 19; compact format; info bits 0 
0: len 4; hex 8000007d; asc };; 
1: len 6; hex 00003a787842; asc :xxB;; 
2: len 7; hex 54000217c52716; asc T ' ;; 
3: len 1; hex 81; asc ;; 
4: len 4; hex 80000021; asc !;; 
5: SQL NULL; 
6: len 4; hex 50616765; asc Page;; 
7: len 4; hex 80000003; asc  ;; 
8: SQL NULL; 
9: SQL NULL; 
10: SQL NULL; 
11: len 4; hex 80000001; asc  ;; 
12: len 7; hex 312f31342f3232; asc 1/14/22;; 
13: len 4; hex 80000003; asc  ;; 
14: len 30; hex 4c6974657261637920617420546175706f205072696d617279205363686f; asc Literacy at XXXXXXXXXXX Scho; (total 32 bytes); 
15: SQL NULL; 
16: len 6; hex 332c342c3135; asc 3,4,15;; 
17: len 1; hex 81; asc ;; 
18: SQL NULL; 

*** (2) TRANSACTION: 
TRANSACTION 3A787846, ACTIVE 0 sec fetching rows 
mysql tables in use 1, locked 1 
180 lock struct(s), heap size 31160, 12416 row lock(s) 
MySQL thread id 437041, OS thread handle 0x7f488b6e6700, query id 13820201 localhost xxxxxxxxxxxxxxx init 
UPDATE `component_instances` SET `view_user_ids` = NULL, `edit_user_ids` = NULL ORDER BY component_instances.ancestry, position 
*** (2) HOLDS THE LOCK(S): 
RECORD LOCKS space id 0 page no 124313 n bits 152 index `PRIMARY` of table `450273b5d362920c`.`component_instances` trx id 3A787846 lock_mode X 
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0 
0: len 8; hex 73757072656d756d; asc supremum;; 

UPDATE 2

Es gibt derzeit ein Index für die ancestry Spalte und das ist es (abgesehen von ID).

Es liegen noch keine Transaktionen um dieses Updates:

UPDATE `component_instances` SET `view_user_ids` = NULL, `edit_user_ids` = NULL ORDER BY component_instances.ancestry, position 
    Permission Exists (0.4ms) SELECT 1 AS one FROM `permissions` LIMIT 1 
    ComponentInstance Load (17.0ms) SELECT component_instances.*, GROUP_CONCAT(DISTINCT view_groups_users.user_id) AS calculated_view_user_ids, GROUP_CONCAT(DISTINCT edit_groups_users.user_id) AS calculated_edit_user_ids FROM `component_instances` LEFT OUTER JOIN permissions ON permissions.component_instance_id = component_instances.id LEFT OUTER JOIN groups view_groups ON view_groups.id = permissions.group_id AND permissions.view = 1 LEFT OUTER JOIN groups edit_groups ON edit_groups.id = permissions.group_id AND permissions.edit = 1 LEFT OUTER JOIN groups_users view_groups_users ON view_groups_users.group_id = view_groups.id LEFT OUTER JOIN groups_users edit_groups_users ON edit_groups_users.group_id = edit_groups.id GROUP BY component_instances.id ORDER BY component_instances.ancestry 
    SQL (4.5ms) UPDATE `component_instances` SET `edit_user_ids` = '6' WHERE (((`component_instances`.`id` = 2 OR `component_instances`.`ancestry` LIKE '1/2/%') OR `component_instances`.`ancestry` = '1/2')) ORDER BY component_instances.ancestry, position 
    SQL (6.9ms) UPDATE `component_instances` SET `edit_user_ids` = '9,6' WHERE (((`component_instances`.`id` = 3 OR `component_instances`.`ancestry` LIKE '1/3/%') OR `component_instances`.`ancestry` = '1/3')) ORDER BY component_instances.ancestry, position 
    SQL (0.9ms) UPDATE `component_instances` SET `edit_user_ids` = '9' WHERE (((`component_instances`.`id` = 6 OR `component_instances`.`ancestry` LIKE '1/3/6/%') OR `component_instances`.`ancestry` = '1/3/6')) ORDER BY component_instances.ancestry, position 
    SQL (0.7ms) UPDATE `component_instances` SET `view_user_ids` = '6' WHERE (((`component_instances`.`id` = 9 OR `component_instances`.`ancestry` LIKE '1/3/9/%') OR `component_instances`.`ancestry` = '1/3/9')) ORDER BY component_instances.ancestry, position 
    SQL (1.4ms) UPDATE `component_instances` SET `view_user_ids` = '9' WHERE (((`component_instances`.`id` = 118 OR `component_instances`.`ancestry` LIKE '1/118/%') OR `component_instances`.`ancestry` = '1/118')) ORDER BY component_instances.ancestry, position 
    SQL (1.5ms) UPDATE `component_instances` SET `view_user_ids` = '9,6' WHERE (((`component_instances`.`id` = 120 OR `component_instances`.`ancestry` LIKE '1/120/%') OR `component_instances`.`ancestry` = '1/120')) ORDER BY component_instances.ancestry, position 
    SQL (2.3ms) UPDATE `component_instances` SET `edit_user_ids` = '9' WHERE (((`component_instances`.`id` = 120 OR `component_instances`.`ancestry` LIKE '1/120/%') OR `component_instances`.`ancestry` = '1/120')) ORDER BY component_instances.ancestry, position 
    SQL (1.0ms) UPDATE `component_instances` SET `view_user_ids` = '9' WHERE (((`component_instances`.`id` = 119 OR `component_instances`.`ancestry` LIKE '1/120/119/%') OR `component_instances`.`ancestry` = '1/120/119')) ORDER BY component_instances.ancestry, position 
    SQL (0.7ms) UPDATE `component_instances` SET `edit_user_ids` = '9' WHERE (((`component_instances`.`id` = 119 OR `component_instances`.`ancestry` LIKE '1/120/119/%') OR `component_instances`.`ancestry` = '1/120/119')) ORDER BY component_instances.ancestry, position 
    SQL (0.7ms) UPDATE `component_instances` SET `view_user_ids` = '6' WHERE (((`component_instances`.`id` = 121 OR `component_instances`.`ancestry` LIKE '1/120/121/%') OR `component_instances`.`ancestry` = '1/120/121')) ORDER BY component_instances.ancestry, position 
    SQL (0.8ms) UPDATE `component_instances` SET `edit_user_ids` = '6' WHERE (((`component_instances`.`id` = 121 OR `component_instances`.`ancestry` LIKE '1/120/121/%') OR `component_instances`.`ancestry` = '1/120/121')) ORDER BY component_instances.ancestry, position 
    SQL (3.9ms) UPDATE `component_instances` SET `recursively_visible` = 1 ORDER BY component_instances.ancestry, position 
    ComponentInstance Load (0.6ms) SELECT `component_instances`.* FROM `component_instances` WHERE `component_instances`.`visible` = 0 ORDER BY component_instances.ancestry, position 

UPDATE 3

Mein Verdacht ist, dass die große Abfrage über unterschiedlich vom Rest der Abfragen wird die Bestellung. Ich habe dies in meinem Produktionscode behoben, um zu sehen, ob dies das Problem behebt.

+0

Welche Speicher-Engine verwenden Sie? – SpacePhoenix

+1

Können Sie uns zeigen, welche Abfragen den Deadlock verursachen? Sie finden den "SHOW ENGINE INNODB STATUS" unter [hier] (http://dba.stackexchange.com/a/1740/89670) für Details (vorausgesetzt, Sie verwenden die INNODB-Engine). Von diesem können Sie herausfinden, ob es wirklich zwei Anforderungen gleichzeitig sind, die die Deadlocks verursachen (am wahrscheinlichsten, IMO) oder etwas anderes. – BoraMa

+0

@SpacePhoenix: Innodb. –

Antwort

0

In diesem speziellen Szenario war das Problem ein Unterschied in der ORDER BY Klausel von ein paar verschiedenen Bits von SQL, die zur gleichen Zeit ausgeführt werden. Ich habe die falsche Reihenfolge übertrieben und alles ist seitdem gut.