- PR -

PostgreSQLのJDBCのcommitのタイミングについて

投稿者投稿内容
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2007-09-18 23:55
PostgreSQLを疑うには根拠が乏しいのではないでしょうか。

synchronizedしているオブジェクトは適切ですか?
メソッドをsynchronized修飾するだけではスレッドセーフ
とは言い切れません。状況次第で問題になる事も多いです。

#まさか複数のJVMから負荷をかけたなんてオチはないですよね?

とりあえず、づかさんが示された状況での正しい方針は、
1. 親レコードもしくはテーブルを排他ロックする
2. INSERTに失敗したらトランザクションをリトライする
のどちらかだと思います。

トランザクションはリトライを前提にしている部分もあるので、
厳密に言えば両者を組み合わせるのが最良な方針だと思います。

特に、PostgreSQLのように隔離性をマルチバージョンで実現した
DBMSのSERIALIZABLE隔離レベルでは、トランザクションを直列化
できない場合にエラーとなるだけなので、リトライは必須です。

#InnoDBもマルチバージョン型ですが、事情がちょっと異なります。
づか
会議室デビュー日: 2007/06/26
投稿数: 15
お住まい・勤務地: Tokyo, Japan
投稿日時: 2007-09-19 00:36
あしゅさん

すみません・・・・

synchronized修飾子を付けたクラスがSingletonではありませんでした。
そうですよね。メソッドにsynchronized修飾子を付けたら synchronized(this)と同じことになるんですよね。

ああああ、しまったああーーーーーー。やってもうたーーと言う感じです。
本当にありがとうございました。もう一度、きちんと調べ直してみます。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-09-19 02:34
念のためPostgreSQLのJDBCドライバのソースを呼んだ限りでは、
"COMMIT"というコマンド送信を行っていますが、
コマンド送信結果のメッセージを受け取ってから処理が継続するように見えました。

流石に深くまでは追っていませんが・・・
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2007-09-19 09:16
引用:

づかさんの書き込み (2007-09-18 21:36) より:
どのようなときに、その問題が発生したかというと、

BEGIN;

DELETE FROM TABLE1 WHERE id = 'aaaa';
INSERT INTO TABLE1(id, data) VALUES('aaaa', 'data');

COMMIT;

(idカラムは主キー)
というような処理を、クライアントサイドでは同時に実行しないよう排他処理を行う処理を書きました。
(BEGINからCOMMITまでの処理をJavaでいうsynchronized修飾子のついたメソッドで実行しました)


これは擬似コードなのでしょうか?それとも BEGIN; や COMMIT; までも含んだ文字列をひとつの SQL 文として、送信したのでしょうか?もしそうだとしたら、(ちょっと自分では自信がありませんが)ミドルウェアが予期していない可能性がありトランザクションの管理がうまくいかなくなるかもしれません。

--
unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86}
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 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/06/26
投稿数: 15
お住まい・勤務地: Tokyo, Japan
投稿日時: 2007-09-19 22:11
みなさん(かつのりさん、unibonさん、あしゅさん)

すみません、完全なる僕の誤解だったようです。
クライアントコードの方で、ロックのアルゴリズムを変えたらちゃんとしたエラーのない動きをしました。

PostgreSQLを疑って、ほんとすみませんでした。
逆に言ってしまえば、PostgreSQLはそういうところもちゃんとしたDBです。僕はPostgreSQLが大好きと言いますか、DBはPostgreSQLから入ったので、今後とも、PostgreSQLの機能を重視してソフトウェアを作っていこうと思います。今後とも、よろしくお願いします。

スキルアップ/キャリアアップ(JOB@IT)