[pgsql-jp: 33986] Re: pgpool でデッドロック?

Mana Takebe takebemana @ yahoo.co.jp
2004年 9月 15日 (水) 11:08:16 JST


武部です。申し訳ありません、基本的な情報を記述していませ
んでした。
PostgreSQLのバージョンは7.4.5
pgpoolのバージョンは2.0.9
pgpoolの設定ファイルの中身
→最後に添付します。

さて、実行していうSQLですが、PostgreのLOGベースで
以下にご説明します。
(すべてそのままを公開することはできないので、加工してい
ます)

まず、前提としてINSERT対象のテーブルには以下の特徴があり
ます。
・INSERT対象のTABLE_AにはINSERT,UPDATEのトリガーがついて
います。内容は行のあるフィールドをインクリメントするもの
です。
・TABLE_Aのother_table_idフィールドには外部参照キーが
張られており、other_tableのpk_other_tableを参照していま
す。
トランザクションがうまくいった場合は以下のような流れで
SQLが実行されます。実際アプリで発行しているSQLは(1)と(4)で
(2)以下4行はトリガーの実行(3)は、外部参照によるother_table
へのセレクト(FOR UPDATE)が内部的に発生しているのだと思
います。

(1) LOG:  statement: INSERT INTO TABLE_A
(id,other_table_id,data,create_date) VALUES
(123,5,'aaaaaaaaaaaaaaaaaaaaa','2004-09-14 17:46:43.735');
(2)  LOG:  statement: SELECT   $1  = 'INSERT'
CONTEXT:  PL/pgSQL function "table_a_func" line 3 at if
  LOG:  statement: SELECT  0
CONTEXT:  PL/pgSQL function "table_a_func" line 4 at
assignment
(3)  LOG:  statement: SELECT 1 FROM ONLY
"public"."other_table" x WHERE "pk_other_table" = $1 FOR
UPDATE OF x
  LOG:  duration: 56.185 ms
(4) LOG:  statement: SELECT * FROM TABLE_A WHERE id=123
  LOG:  duration: 3.156 ms
  LOG:  statement: commit;begin;
  LOG:  duration: 7.497 ms
  LOG:  statement: rollback; begin;

ロックが発生しているプロセスでは(1)の行までしか実行ログが
図れません。idleしているプロセスでは(1)の後に「LOG: 
duration: 3.156 ms
」が出力されます。

外部参照のロックのあたりでなにか問題が発生しているような
気がします。

再現性は、こちらの環境ではアプリのほうの同時接続数が5を
越えると100%です。

以下にpgpoolの設定ファイルの内容を添付します。
# pgpool configuration file sample
# $Header:
/home/t-ishii/repository/pgpool/pgpool.conf.sample,v 1.10
2004/07/09 05:51:13 t-ishii Exp $

# if 1, connection using INET domain socket is allowed
allow_inet_domain_socket = true

# port number for pgpool
port = 5432

# Unix domain socket path. Debian package default to
/var/run/postgresql!
socket_dir = '/tmp'

# host name where PostgreSQL server is running on. ''
means localhost using UNIX
# domain socket
#backend_host_name = ''
backend_host_name = '192.168.1.108'

# port number PostgreSQL server is running on.
backend_port = 5433

# Unix domain socket path for the backend. Debian package
default to /var/run/postgresql!
backend_socket_dir = '/tmp'

# host name where secondary PostgreSQL server is running
on. '' means localhost using UNIX
# domain socket
secondary_backend_host_name = '192.168.1.109'

# port number secondary PostgreSQL server is running on.
# 0 means no secondrary PostgreSQL
secondary_backend_port = 5432

# number of pre-forked child process
#num_init_children = 32
num_init_children = 4

# numer of connection pool allowed for a child process.
#max_pool = 4
max_pool = 1

# if idle for this seconds, child exits. 0 means no
timeout. this
# featue is not implemented yet.
child_life_time = 0

# if idle for this seconds, connection to PostgreSQL
closes. 0 means
# no timeout
connection_life_time = 0

# logging directory
logdir = '/tmp'

# replication mode
replication_mode = true

# set this to true if you want to avoid deadlock situation
when
# replication enabled.
# there will be noticable performance degration, however.
# a work around is set this to false and insert /*STRICT*/
comment
# at the beginning of the SQL command.
replication_strict = true

# when replication_strict is set to true, there will be a
chance for
# deadlocks. set this to non 0 (in milli seconds) to
detect this
# situation and resolve the deadlock aborting current
session.
#replication_timeout = 5000
replication_timeout = 10000

# load balancing mode. i.e. all SELECT except in a
transaction block
# are load balanced. This is useless if replication_mode
is false.
load_balance_mode = false

# if there's a data mismatch between master and secondary
# start degenration to stop replication mode
replication_stop_on_mismatch = false

================================
takebemana @ yahoo.co.jp


--- Tatsuo Ishii <t-ishii @ sra.co.jp> からのメッセージ:
> 石井です.
> 
>   実行したSQL文
>   PostgreSQLのバージョン
>   pgpoolのバージョン
>   pgpoolの設定ファイルの中身
> 
> がわかって,かつ再現性があれば何か分かるかも知れません
.
> 
> こちらでpgbenchでテストした程度では再現しないようなの
で...
> --
> Tatsuo Ishii
> 
> > 武部と申します。
> > 
> >
> Tomcat+PostgreSQLでアプリケーションを構築しており、
> >
> 主にレプリケートの目的で、pgpoolを利用しようと考えてい
ま
> > すが、
> > アプリケーションの負荷試験を行ったところ、
> >
> pgpoolでレプリケートしていると、デッドロックのような
> > 現象が発生し、更新処理が止まってしまいます。
> > (replication_strictはtrueに設定しています。)
> > 
> > ロック状態を確認したところ以下のようになっており、
> > slave側ではp2の方がSQLの実行としては後
> > (postgreのlog_statement
> > の出力から)
> > なのですがトランザクションID
> 5417630ロックを先に取得して
> > しまって
> > いるように見えます。
> >
> (p1,p2というのは同じSQLを実行するmasterとslaveのペアに
同
> > じ名前をつけています。)
> > 
> > master側---------------------------------
> > p1(psで見るとidle in tranzaction状態)
> >                     |          |     5417667 |
> 25384 |
> > ExclusiveLock    | t
> >  other_table        | db1      |             |
> 25384 |
> > AccessShareLock  | t
> >  other_table        | db1      |             |
> 25384 |
> > RowShareLock     | t
> >  TABLE_A            | db1      |             |
> 25384 |
> > AccessShareLock  | t
> >  TABLE_A            | db1      |             |
> 25384 |
> > RowExclusiveLock | t
> > 
> > 
> > p2 (psで見るとINSERT waiting状態)
> >  pk_other_table     | db1      |             |
> 25382 |
> > AccessShareLock  | t
> >  TABLE_A            | db1      |             |
> 25382 |
> > AccessShareLock  | t
> >  TABLE_A            | db1      |             |
> 25382 |
> > RowExclusiveLock | t
> >                     |          |     5417667 |
> 25382 |
> > ShareLock        | f
> >                     |          |     5417693 |
> 25382 |
> > ExclusiveLock    | t
> >  other_table        | db1      |             |
> 25382 |
> > AccessShareLock  | t
> >  other_table        | db1      |             |
> 25382 |
> > RowShareLock     | t
> > 
> > 
> > slave側---------------------------------
> > p1 (psで見るとINSERT waiting 状態)
> >  pk_other_table     | db1      |             |
> 3389 |
> > AccessShareLock  | t
> >  other_table        | db1      |             |
> 3389 |
> > AccessShareLock  | t
> >  other_table        | db1      |             |
> 3389 |
> > RowShareLock     | t
> >                     |          |     5417630 |
> 3389 |
> > ShareLock        | f
> >  TABLE_A            | db1      |             |
> 3389 |
> > AccessShareLock  | t
> >  TABLE_A            | db1      |             |
> 3389 |
> > RowExclusiveLock | t
> >                     |          |     5417605 |
> 3389 |
> > ExclusiveLock    | t
> > 
> > p2 idle (psで見るとidle in tranzaciton状態)
> >  other_table        | db1      |             |
> 3387 |
> > AccessShareLock  | t
> >  other_table        | db1      |             |
> 3387 |
> > RowShareLock     | t
> >  TABLE_A            | db1      |             |
> 3387 |
> > AccessShareLock  | t
> >  TABLE_A            | db1      |             |
> 3387 |
> > RowExclusiveLock | t
> >                     |          |     5417630 |
> 3387 |
> > ExclusiveLock    | t
> > 
> > 
> > 現状、replication_strictがtrueですが、
> > master側のSQLがロック待ちになっている状態でも
> >
> salve側にSQLが実行されているという状況に見えるのですが
、
> > これは正しい状態なのでしょうか?
> > 設定がうまくいっていないのでしょうか?
> > 
> > なにかアドバイスをいただければ幸いです。


__________________________________
Do You Yahoo!?
http://bb.yahoo.co.jp/




pgsql-jp メーリングリストの案内