2011-01-12 13 views
1

私はSELECTと可能なINSERTのトランザクションを持っています。並行性の理由から、私はSELECTFOR UPDATEを追加しました。ファントム行を防ぐために、私はSERIALIZABLEトランザクション分離レベルを使用しています。これはテーブル内に行がある場合はすべて正常に動作しますが、の場合はではありません。テーブルが空の場合、SELECT FOR UPDATEは(排他的な)ロックを行わず、同時のスレッド/プロセスはロックされずに同じSELECT FOR UPDATEを発行することができます。innodbとシリアライズ可能なトランザクションを使用したMysqlは、(常に)行をロックしません。

CREATE TABLE t (
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    display_order INT 
) ENGINE = InnoDB; 

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
START TRANSACTION; 
SELECT COALESCE(MAX(display_order), 0) + 1 from t FOR UPDATE; 

.. 

このコンセプトは、SQL Serverでは期待どおり動作しますが、MySQLでは期待されません。私が間違っていることに関するアイデアは?

EDIT

display_orderにインデックスを追加すると、動作を変更しません。

答えて

0

あなたはこの文書を見ていました: http://dev.mysql.com/doc/refman/5.1/en/innodb-locking-reads.html

あなたは私に言わせれば、mysqlのは、そのように使用されるように構築されていなかった... マイrecomendationがある: あなたはそれをaffortことができれば - >テーブル全体をロックします。

+0

優れた外観を5.1ドキュメントでは、分離レベルの管理が今では全く異なっています – regilero

+0

Mysqlのドキュメントでは、わかっているので、これらのケースに対してFOR UPDATEを使用することが明示的に推奨されています。セマンティクスが空のテーブルと異なるように見えるだけです。 –

0

これはおそらくバグではありません。

異なるデータベースが特定のトランザクション分離レベルを実装する方法は、100%一貫性がありません。また、どのような動作が異なるかを考慮する必要があります。 InnoDBはオラクルをエミュレートすることを意図されていましたが、そこでさえ、違うところで動作するケースがあると私は信じています。

アプリケーションは、それがおそらく壊れている、特定のトランザクション分離モードでは非常に微妙なロック動作に依存していた場合:

  • でも今それを「作品」場合は、誰かがデータベーススキーマ
  • を変更した場合、それはないかもしれません
  • B、それは
+0

これは必ずしもバグではないことに同意します。私はそれが私がそれを見たいと思うようにうまくいかない理由が不思議です。私はこの問題に関する何かをMySQLのドキュメントで見つけることができませんでした。 –

1

をロックの機微に依存している場合、これと楽しい何かがありますあなたのコードを維持するエンジニアが、それはデータベースを使っているかを理解することはほとんどありません実際のロックを取得する準備ができています。トランザクションの1つが挿入を実行しようとするとすぐに、ロックがそこにあります。両方のトランザクションがそれを試すと、デッドロックが発生し、ロールバックされます。そのうちの1人だけが試してみると、のロック待機タイムアウトが得られます。

ロック待機タイムアウトを検出した場合、ロールバックすることができます。これにより、次のトランザクションが挿入を実行できるようになります。

デッドロック例外やタイムアウト例外が発生する可能性が非常に高いと思います。は状況を保存する必要があります。しかし、完璧な 'シリアライズ可能な'状況について言えば、これは事実上空のテーブルの悪い副作用です。すべてのケースでエンジンが完璧になるわけではありません。少なくとも二重トランザクション挿入はできません。

私はそれが面白いです。この例を確認し、potsgreSQlのドキュメントに、エンジンseriability対昨日真seriabilityの興味深いケースを送ってきました:http://www.postgresql.org/docs/8.4/static/transaction-iso.html#MVCC-SERIALIZABILITY

更新: その他の興味深い資源:でDoes MySQL/InnoDB implement true serializable isolation?

+0

デッドロックやタイムアウトの可能性も気づいた。デッドロック/タイムアウトの処理とトランザクションの再試行は可能ですが、デッドロックのないきれいなソリューションを好むでしょう。 –

+0

シリアライザブルトランザクションを処理する場合は、トランザクション処理(リトライループを使用)で例外をすでに処理している必要があります。デッドロックの中断は、処理するもう一つの例外です。アプリケーションと同じアルゴリズムです。シリアライズ可能なトランザクションは非常に 'unzerializable例外'を取得する可能性が高い、私はちょうど同じ方法で例外を検出例外を考慮する。 – regilero

+0

もちろん、これらの例外を処理します(また、デッドロック/タイムアウト例外が発生したときにトランザクションを再試行します)が、なぜ排他ロックが取られないのか不思議です。 –

関連する問題