- - PR -
PostgreSQLのJDBCのcommitのタイミングについて
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2007-09-18 23:55
PostgreSQLを疑うには根拠が乏しいのではないでしょうか。
synchronizedしているオブジェクトは適切ですか? メソッドをsynchronized修飾するだけではスレッドセーフ とは言い切れません。状況次第で問題になる事も多いです。 #まさか複数のJVMから負荷をかけたなんてオチはないですよね? とりあえず、づかさんが示された状況での正しい方針は、 1. 親レコードもしくはテーブルを排他ロックする 2. INSERTに失敗したらトランザクションをリトライする のどちらかだと思います。 トランザクションはリトライを前提にしている部分もあるので、 厳密に言えば両者を組み合わせるのが最良な方針だと思います。 特に、PostgreSQLのように隔離性をマルチバージョンで実現した DBMSのSERIALIZABLE隔離レベルでは、トランザクションを直列化 できない場合にエラーとなるだけなので、リトライは必須です。 #InnoDBもマルチバージョン型ですが、事情がちょっと異なります。 | ||||
|
投稿日時: 2007-09-19 00:36
あしゅさん
すみません・・・・ synchronized修飾子を付けたクラスがSingletonではありませんでした。 そうですよね。メソッドにsynchronized修飾子を付けたら synchronized(this)と同じことになるんですよね。 ああああ、しまったああーーーーーー。やってもうたーーと言う感じです。 本当にありがとうございました。もう一度、きちんと調べ直してみます。 | ||||
|
投稿日時: 2007-09-19 02:34
念のためPostgreSQLのJDBCドライバのソースを呼んだ限りでは、
"COMMIT"というコマンド送信を行っていますが、 コマンド送信結果のメッセージを受け取ってから処理が継続するように見えました。 流石に深くまでは追っていませんが・・・ | ||||
|
投稿日時: 2007-09-19 09:16
これは擬似コードなのでしょうか?それとも BEGIN; や COMMIT; までも含んだ文字列をひとつの SQL 文として、送信したのでしょうか?もしそうだとしたら、(ちょっと自分では自信がありませんが)ミドルウェアが予期していない可能性がありトランザクションの管理がうまくいかなくなるかもしれません。 -- unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86} | ||||
|
投稿日時: 2007-09-19 21:41
synchronizedが間違っている時点で現象を説明出来ますよ。
対象行が存在していない状態で、 TX1: DELETE ⇒ 対象行が存在しないので何もしない TX2: DELETE ⇒ 対象行が存在しないので何もしない TX1: INSERT ⇒ 排他行ロックを行ってINSERT成功 TX2: INSERT ⇒ 排他行ロックを行えないので待機 TX1: COMMIT ⇒ コミット成功 TX2: INSERTから目覚めて「duplicate key」が発生 という動きです。 他のDBで起きないのは隔離レベルがSERIALIZABLEなので DELETE時のインデックス等の共有ロックのせいでは? READ_COMMITTEDなら結果が変わるかもしれません。 | ||||
|
投稿日時: 2007-09-19 22:11
みなさん(かつのりさん、unibonさん、あしゅさん)
すみません、完全なる僕の誤解だったようです。 クライアントコードの方で、ロックのアルゴリズムを変えたらちゃんとしたエラーのない動きをしました。 PostgreSQLを疑って、ほんとすみませんでした。 逆に言ってしまえば、PostgreSQLはそういうところもちゃんとしたDBです。僕はPostgreSQLが大好きと言いますか、DBはPostgreSQLから入ったので、今後とも、PostgreSQLの機能を重視してソフトウェアを作っていこうと思います。今後とも、よろしくお願いします。 |