[pgcluster: 891] Re: pgbench で固まってしまいます

Yoshiyuki Asaba y-asaba @ sraoss.co.jp
2006年 7月 13日 (木) 23:30:00 JST


こんばんは、浅羽です。

From: a.mitani @ sra-europe.com
Subject: [pgcluster: 888] Re: pgbench で固まってしまいます
Date: Thu, 13 Jul 2006 12:18:58 +0200 (CEST)

> > pgbenchでコネクション数を増やすとレプリケーションの処理が固まってしまうので
> > す。
> > だいたい10ぐらいになるとそのままフリーズしてしまいます。
> これは判っている問題なのですが,今のところ解決方法がありません.
> 
> pgbenchはシングルプロセスのベンチマークツールで,デフォルトでは1トランザクショ
> ン内で3つのUPDATEと1つのINSERT,1つのSELECTを発行しています.
> デフォルトの設定では,3つのUPDATEのうち1つが同一レコードに更新をかけるため
> ロックが発生します.レプリケーションをしない状態では上手くロック待ちができる
> ようなのですが,レプリケーションを絡めるとロックが発生します.
> pgbenchがシングルプロセスのため,1つでもロックが発生すると,次のクエリーが
> 送られないため,固まります.

1.5.x のソースコードを見たことがないので検討違いのことを書いているかも
しれませんが、これは pgbench がシングルプロセスだからデッドロックが発
生する、という問題ではありません。pgbench は非同期問い合わせを行うので、
本来であれば、ロック待ちが発生しても、デッドロック状態にはならないはず
です。

では、なぜ PGCluster でデッドロックが発生するかというと、PostgreSQL の
行ロック獲得アルゴリズムが原因になります。PostgreSQL では、行ロックを
すでに獲得しているトランザクションがあると、他のトランザクションは待た
されます。これは普通の挙動ですね。で、行ロックを持っているトランザクショ
ンが終了すると、一斉に複数のクライアントが行ロックを奪いにいきます。こ
こにレースコンディションが存在し、次にどのクライアントがロックを獲得す
るかわからない状況になります。

1 つの DB サーバであれば、そんなに問題がないのですが、複数台が常に同期
をとらないとなると、これは非常にまずいのです。何故かというと、各サーバ
上で異なるクライアントがロックを取る可能性があり、ロック獲得状況に不整
合が生じるためです。そのため、デッドロックが発生しています。

このデッドロックが発生する条件は調べた限りでは、

  - トランザクション隔離レベルが read committed
  - 同じ行に対して 3 クライアント以上がロックを獲得しに行く

です。pgbench で -c 2 の場合は、デッドロックしないのを確認できるかと思
います。

この問題はテーブルロック(SHARE ROW EXCLUSIVE)を先に獲得することで回避
することができます。ちなみに、1.0.x では行ロックを獲得するようなクエリ
は自動的にテーブルロックを獲得するオプションがあります。


> pgbenchをマルチプロセスにしたpgcbenchというものはPGClusterでは用意しています
> ので,こちらを使ってもらえれば,ベンチマークを計ることは可能です.
> お試しください.

pgcbench がなぜ動くかについても以前調べてみましたが、pgbench が発行す
るクエリと微妙に異なり、複数のクライアントが同時に UPDATE するようなク
エリが無くなっていました。

--
Yoshiyuki Asaba
y-asaba @ sraoss.co.jp



pgcluster メーリングリストの案内