2016-05-31

Slony-I 2.0: `cleanupEvent' causes deadlock

Slony-I 2.0.6 + 同期復旧 patch を使うようになって以降、割と平穏な日々を過ごしてきた。

しかし実はまだ 1 つ、既知の問題が残っている。Slony-I 2.0 系は、deadlock を起こすことがある。

いつか直らないかと気に掛けていたものの、一向に直る気配もなく今に至る。そうこうしているうちに何年かぶりに再発したため、今更ながら調べることにした。

面倒なのでソースコード引用は省略。発生条件は、slon が 10 分毎に実行する clenaupEvent 処理と、slonik の実行が衝突すること。slonik を使わない、または slonik 実行時に slon が停止していれば発生することはない。(たぶん)

deadlock の原因は、当たり前だが、それぞれの処理でロックの取得順が異なることに因る。それぞれのロック取得順は次のようになる。

  • slonik コマンド: sl_config_lock → sl_event (一部の slonik コマンドを除く)
  • slon cleanupEvent: sl_event → sl_config_lock

分かってしまえば解決は難しくない。それぞれのロック取得順を合わせてやれば良い。今回の場合、cleanupEvent 処理の最初で sl_config_lock のロックを取得するのが簡単だろう。

--- slony1-2.0.6/src/backend/slony1_funcs.sql.orig	2010-12-08 01:44:09.000000000 +0900
+++ slony1-2.0.6/src/backend/slony1_funcs.sql	2016-05-31 17:35:22.000000000 +0900
@@ -4478,6 +4478,11 @@
 	v_rc            int8;
 begin
 	-- ----
+	-- Grab the central configuration lock
+	-- ----
+	lock table @NAMESPACE@.sl_config_lock;
+
+	-- ----
 	-- First remove all confirmations where origin/receiver no longer exist
 	-- ----
 	delete from @NAMESPACE@.sl_confirm

とは言っても、元々 deadlock が発生すること自体が稀なため、本当に直ったのか確認することは難しい。正直、「直ったらラッキー」程度に考えている。

ちなみに Slony-I 2.1 以降はロック機構がガラリと変わっており、以上のことは当てはまらない。(deadlock が起こらないかは知らない)