[pgsql-jp: 37334] Re: popoolとシーケンスキー

Tatsuo Ishii ishii @ sraoss.co.jp
2006年 7月 4日 (火) 22:51:36 JST


石井です.

> 島田@Storgateです。
> 
>  pgpool の中身を、正確には理解できてない(石井さん。すみ 
> ません)
> ので恐縮ですが、向学のため。。。誤解や誤りがありましたら、ご教授
> 戴ければ幸いです。
> 
> On 2006/07/04, at 10:11, Tatsuo Ishii wrote:
> > READMEは同時セッションが2つ以上の場合を問題にしています
> 
> On 2006/07/04, at 17:13, koyama wrote:
> > pgpoolに、INSERT文が来た場合の、DB1及び、DB2 
> > への、それぞれの
> > 実行順番が同じであれば、DB1、とDB2のテーブル内の 
> > データは、
> > 一致していると考えてますが、間違っておりますでしょうか?
> 
> 「実行順序が同じ」であればDB間の不整合は起らないでしょう。。
> ただし、ここがミソです。実行順序とは何かの定義をお考えください。
> 
> 今、2つのアプリのプロセス p1, p2 が pgpool経由で 
> DB接続したと
> します。その結果以下のような接続状態(cxxはコネクション) 
> になる
> はずです。
> APL.server                             postgres backend process
>  p1---c1---| pgpool |---c11---| db1---pg.11
>              |        |===c21===|    ===pg.21
>    p2===c2===|        |
>              |        |---c12---| db2---pg.12
>              |        |===c22===|    ===pg.22
> 
> ここで、カラムのDEFAULT句に "nextval('seq')" をもつ 
> テーブルに
> p1, p2 からそれぞれ INSERT を行なった場合、db1, db2  
> で不整合が
> 生じない条件は、先にもあるように、「実行順序が同じ」、すなわち、
>  db1 での postgres backend process、pg11,  
> pg12 と
>  db2 での postgres backend process、pg21,  
> pg22 において
> insert文の処理時の nextval() が「同じ順序で実行されるこ 
> と」を
> 保証する事です。
> 
> 一見、db1, db2 に同じ順番で  INSERT文を送信すれば、 
> その条件を
> 満たしそうですが、各 backend process の内での実際の処理進 
> 行が
> 各バックエンドプロセスにおける SQLの受信順序になることは、
> postgresバックエンドが複数の個別プロセスであるために保証され
> ないかと。。
> (独立なプロセスは kernel によって勝手にスケジュールされま 
> す)
> 
> 従って、pgpool の説明にもあるように、明示的にテーブルを LOCK
> する様な、何らかの仕込みが必要になるのでは。
> ただし、3つ以上のコネクションが同時にinsert を行なっ 
> た時は、
> 今度は各コネクション毎での、LOCK の順番も保証しないと。。
> 
> また、"replication_strict"は勉強不足で良く理解出来ていない
> のですが、どこかで、何とかして、複数DB間にまたがっての更新に
> 関する "Serializable" な状態をつくってあげる必要があると思 
> います。

島田さんの図はちょっとよくわからないのですが,こういうことが起きるとい
う問題だと理解しています.

今,"master","secondary"という2つのDBにpgpoolが接続し,pgpoolには2つ
のセッション"session0"と"session1"が接続しています.pgpoolでは,pgpool
へのセッションはそのままpgpoolからPostgreSQLへのセッションになります.

pgpoolの"strict_mode"では各セッションにおいて,masterでのSQLの実行が完
了し,応答が返ってきてからsecondaryに同じSQLを投げることを保証します.
セッションが1個しかなないのであれば,これでmasterとsecondaryで常に同じ
順序でSQLを実行することが保証できます.

しかし,セッションが2つあると,以下のような状況が発生します(この図では
上から下に時間が流れるものとします.).


	    master		       secondary
   session 0	session 1	session 0   session 1
   ------------------------------------------------------
   nextval	
                nextval
                                             nextval
                                nextval
   ------------------------------------------------------

各セッション内ではmasterでのnextvalの実行後にsecondaryでnextvalが実行
されるということが保たれています.しかし,全体で見ると,masterでは
session0->session1の順でnextvalが実行されるのに対し,secondaryでは
session1->session0の順でnextvalが実行されてしまってます.これがまずい
わけですね.

masterでもsecondaryでも必ずsession0->session1の順でnextvalを実行させる
ための一つの方法がテーブルロックです.テーブルロックを併用すると以下の
様になります(nextvalの後のcommitは省略してあります).

	    master		       secondary
   session 0	session 1	session 0   session 1
   ------------------------------------------------------
   lock
                                lock
   nextval	
                                nextval
                lock
                                             lock
                nextval
                                             nextval
   ------------------------------------------------------

この状態であれば,シーケンスが狂うことはありません.この例ではセッショ
ンが2つですが,セッションが3つ以上でも同じことが言えます.

もちろんテーブルロックを使うことによってトランザクションの同時実行性が
損なわれてしまうのは好ましいことではありませんが,現状ではシーケンス値
を保証しようとするとテーブルロックを使うなどしてSQLの実行順序を保証し
なければなりません.

島田さんのおっしゃる,

> どこかで、何とかして、複数DB間にまたがっての更新に
> 関する "Serializable" な状態をつくってあげる必要があると思 
> います。

ということですね.

ただ,どんな更新処理でもテーブルロックが必要かというと,そんなことはな
くて,シーケンスを使っていなければ普通は物理的な行の挿入順は問題ならな
いと思うので,そういう場合はロックは不要にできると思います.
--
Tatsuo Ishii
SRA OSS, Inc. Japan



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