2012-05-09 8 views
0

複数のエージェントがテーブルから顧客を1つずつロードするC#でコールセンタープログラムを作成しています。複数のエージェントが同じ顧客をロードするのを防ぐために、テーブルに新しいフィールドを追加して、その行がロックされていることを示しました。行を選択すると、その行が更新され、その行を選択したエージェントのIDにロックフィールドが設定されます。しかし問題は、私が行を選択してロックしている間に、別のエージェントがまだロックされていないので同じ行を選択することができます!このような状況に対応できる方法はありますか?データベースは、MySQL 5/InnoDBの更新が行われる前に他のセッションが行を選択しないようにする方法

+0

あなたは「テーブルから1つずつ」 - どの基準に基づいて書きますか?一番長い間テーブルの中にいたのは? – MiMo

答えて

1

はあなたが唯一のエージェントにつき1つのプロファイルをロックすることができますと仮定している:私は、アップデートを実行する前に、私はIDを選択する必要が

--Check for no lock 
UPDATE T SET LockField = 'abc' WHERE ProfileId = 1 AND LockField IS NULL; 

--Check to see if we updated anything. 
--If not, we can't show this row because someone else has it locked 
SELECT ROW_COUNT(); 

...

1つのステートメントでUPDATEを実行すると、そうではありません。私はMySQLの構文について私の知るところを少し過ぎていますが、次のようなものです:

--Check for no lock 
UPDATE T SET LockField = 'abc' WHERE ProfileId = (
    SELECT ProfileId FROM T WHERE LockField IS NULL LIMIT 1 
); 

--Check to see what we updated 
SELECT * FROM T WHERE LockField = 'abc'; 

かなり簡単に動作します。

あなたはもう少し複雑に取得したい場合(またはMySQLのサブクエリをサポートしていません)、あなたは、SELECT ... FOR UPDATEで更新ロックを使用することができます。

START TRANSACTION; 

--Put an update lock on the row till the xaction ends 
--any other SELECT wanting an update lock will block until we're out of the xaction 
SELECT @id = ID FROM T WHERE LockField IS NULL LIMIT 1 FOR UPDATE; 

UPDATE T SET LockField = 'abc' WHERE ID = @id; 

COMMIT TRANSACTION; 
関連する問題