2012-04-27 5 views
2

これは単純な解決策があるとはかなり確信していますが、これまでこれを見つけることはできませんでした。 SERIALIZABLEに設定分離レベルでのInnoDBのMySQLデータベースを提供し、次の操作与えられた:トランザクション中に、トランザクションが完了するまで、影響を受ける行への読み取りはどのように防止できますか?

BEGIN WORK; 
SELECT * FROM users WHERE userID=1; 
UPDATE users SET credits=100 WHERE userID=1; 
COMMIT; 

は、私は、すぐにトランザクション内の選択が発行されるように、行はユーザーIDに対応していることを確認したいと思いますし= 1はトランザクションが完了するまでがロックされ、と読み込まれます。今のように、この行のUPDATEは、トランザクションが処理中であれば終了するのを待っていますが、SELECTは単に前の値を読み込みます。私はこれがこの場合の予想される動作だと理解していますが、SELECTがトランザクションが値を返すために終了するまで待つような方法で行をロックする方法があるのだろうか?

私が探している理由は、ある時点で十分な同時ユーザーがいるため、以前のトランザクションが処理中に他のユーザーが他のユーザーが計算するために「クレジット」を読み取ることがあります。理想的には、他の誰かが実行するコードは、トランザクションが新しい値を使用するのを待つ必要があります。そうしないと、不可逆的な非同期の問題が発生する可能性があります。

テーブル全体を特定の行だけロックする必要はありません。

また、テーブルにブール値の「ロックされた」フィールドを追加して、トランザクションを開始するたびに1に設定することもできますが、絶対にそうでない限り、これをmysqlを通して直接処理する他の方法はありません。

+0

テーブルのスナップショットを一時テーブルに入れることができます: 'CREATE TEMPORARY TABLE t_users SELECT * FROM users;'。 – eggyal

+0

それはしないだろう、私はトランザクションが進行中に特定の行への読み込みが拒否されていることを確認したい、私はメインテーブルから行を削除し、私が終わった後、それはあまりにも多くのDBへの旅行のように聞こえる。 – Mahn

+0

私の悪い、私はあなたの質問に誤解していた。 – eggyal

答えて

2

私は具体的には、回避策を見つけた:

SELECTを...共有モードでLOCKは、行 読み取りに共有モードロックを設定します。共用モード・ロックにより、他のセッションは行を読み取ることができますが、 はそれらを変更しません。 読み取られた行が最新のものであるため、 がまだコミットされていない別のトランザクションに属している場合は、そのトランザクションが終了するまで の読み取りがブロックされます。

Source

1つだけのトランザクションデータに依存している重要なSELECT文で共有モードでLOCKを含むことができ、彼らが実際に/行を取得する前に終了し、現在のトランザクションを待つことになるようですs。これが機能するためには、トランザクションはFOR UPDATEを明示的に使用しなければなりません(私が与えた元の例とは対照的に)。例えば。、次の与えられた:どこでも、他のコードで

BEGIN WORK; 
SELECT * FROM users WHERE userID=1 FOR UPDATE; 
UPDATE users SET credits=100 WHERE userID=1; 
COMMIT; 

私が使用できます。この文は、トランザクションでラップされていない

SELECT * FROM users WHERE userID=1 LOCK IN SHARE MODE; 

ので、ロックは、このように、その後には影響を与えていない、すぐに解放されますしかし、トランザクション内で更新するためにuserID = 1を含む行が選択されている場合、この文はトランザクションが完了するまで待つでしょう。これはまさに私が探していたものです。

2

SELECT ... FOR UPDATEロックを読み取ることができます。

SELECT ... FOR UPDATEは、使用可能な最新のデータを読み取り、読み込んだ各行で排他ロックを設定します。したがって、検索されたSQL UPDATEが行に対して設定するのと同じロックを設定します。

次のサイトを経由してください:http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html

+0

すでに試してみましたが、書き込みは行をロックするだけで、読み取りはできません。また、分離レベルがすでにSERIALIZEに設定されている場合は、違いはないと私は信じています。 – Mahn

+0

(私は何らかの理由で前のコメントを編集できませんが、明らかにSERIALIZABLEを意味していました) – Mahn

+0

回避策を見つけるのに役立ちましたので元通りになりました – Mahn

関連する問題