2016-05-31

Slony-I 2.0: `cleanupEvent' causes deadlock

Slony-I 2.0.6 + patch を使うようになって以降、割かし平穏な日々を過ごしてきたが、

実は一つだけ問題がある。Slony-I 2.0 系は、deadlock を起こすことがある。

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

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

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

  • slonik コマンド: sl_config_lock -> sl_event (一部のコマンドを除く)
  • 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

本当にこの修正で良いのか不安もあるが、そもそも発生することが稀なため、確認するのも容易でない。正直、「直ったらラッキー」程度に考えている。

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