designateでdeadlockが発生する原因と解決手段
English follow is here =>
Designate got the DBDeadLock – Hirose Takahito – Medium
designateを使っていてたまにdeadlockがおきていることに気がついたので、その原因を探っていきました。
原因は登録/更新/削除のフローで起きる構造になっていたのでそれについてまとめました。
これは簡単にまとめたdesignateの登録フローです。 今回deadlockのポイントになったのが、2と3の最初のMySQLへの登録(更新)プロセスと、8と9のstatus更新プロセスの部分です。
for i in {1..100} ; do openstack recordset create --records 192.168.0.1 --type A 26b12550-6d64-49eb-a69d-0427472b7da2 z$i ; done
今回はシンプルなシェルスクリプトで確認しました。すると、
------------------------ LATEST DETECTED DEADLOCK ------------------------ 190320 15:32:32 *** (1) TRANSACTION: TRANSACTION 27B30A, ACTIVE 0 sec starting index read mysql tables in use 1, locked 1 LOCK WAIT 5 lock struct(s), heap size 1248, 3 row lock(s), undo log entries 2 MySQL thread id 243, OS thread handle 0x7f2ac428d700, query id 65726 10.127.163.56 designate Updating UPDATE zones SET version=(zones.version + 1), updated_at=‘2019-03-20 06:32:32.527418’, status=‘ACTIVE’, action=‘NONE’ WHERE zones.id = ‘26b125506d6449eba69d0427472b7da2’ AND zones.deleted = ‘0’ *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 653 page no 3 n bits 72 index `PRIMARY` of table `designate`.`zones` trx id 27B30A lock_mode X locks rec but not gap waiting *** (2) TRANSACTION: TRANSACTION 27B306, ACTIVE 0 sec starting index read mysql tables in use 1, locked 1 6 lock struct(s), heap size 1248, 3 row lock(s), undo log entries 2 MySQL thread id 274, OS thread handle 0x7f2a70d71700, query id 65731 10.127.163.56 designate Updating UPDATE records SET version=(records.version + 1), updated_at=‘2019-03-20 06:32:32.545283’, data=‘ns1.example.com. domain.example.com. 1553063552 3562 600 86400 3600’, hash=‘a4718b30220d6ff2d4b4cc3602654509’, serial=1553063552 WHERE records.id = ‘78b667000767489a8fc821275d5fff0b’ *** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 653 page no 3 n bits 72 index `PRIMARY` of table `designate`.`zones` trx id 27B306 lock_mode X locks rec but not gap *** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 649 page no 12 n bits 112 index `PRIMARY` of table `designate`.`records` trx id 27B306 lock_mode X locks rec but not gap waiting *** WE ROLL BACK TRANSACTION (1)
のようにやはり、タイミングがかさなるとDeadLockが発生していました。
なので、今回は以下のように修正してpatchを投げました。順番を修正してあげれば大丈夫です。
$ git diff diff --git a/designate/central/service.py b/designate/central/service.py index ffd12c6..f6f734d 100644 --- a/designate/central/service.py +++ b/designate/central/service.py @@ -2317,8 +2317,8 @@ class Service(service.RPCService, service.Service): “”" # TODO(kiall): If the status is SUCCESS and the zone is already ACTIVE, # we likely don’t need to do anything. - self._update_record_status(context, zone_id, status, serial) zone = self._update_zone_status(context, zone_id, status, serial) + self._update_record_status(context, zone_id, status, serial) return zone def _update_zone_status(self, context, zone_id, status, serial): zone = self._update_zone_status(context, zone_id, status, serial) + self._update_record_status(context, zone_id, status, serial) return zone def _update_zone_status(self, context, zone_id, status, serial):
patchは以下のURLです。 Gerrit Code Review