1

列 id、type、user_id、および unseen を含む通知テーブルがあります。

新しい通知数を取得するには、次を使用します。

SELECT count(1) 
FROM notifications 
WHERE user_id=123 AND unseen=1

新しい通知のみを表示済みとしてマークするには、次を使用します。

UPDATE notifications 
SET unseen=0 
WHERE user_id=123 AND unseen=1

ただし、この更新クエリではエラーが発生することがあります。知りたいのですが、これを行う正しい方法は何ですか?

編集:

ERROR DESC
トランザクション (プロセス ID 68) がロック時にデッドロックされました。バッファ リソースを別のプロセスと通信しており、デッドロックの犠牲者として選択されています。トランザクションを再実行します。

4

3 に答える 3

0

次のステートメントは、ロックされたレコードとコミットされていないレコードを無視します。

SELECT count(1) 
FROM notifications WITH(READPAST)  
WHERE user_id=123 AND unseen=1

次のステートメントは、更新が必要なレコードをロックしますが、テーブル全体はロックしません。

UPDATE notifications  with (ROWLOCK) 
SET unseen=0 
WHERE user_id=123 AND unseen=1

したがって、READPAST および ROWLOCK ヒントを使用すると、デッドロックを回避できます。

READPASTとNOLOCKについて知るために彼女から読んでください

于 2012-05-04T11:56:19.863 に答える
0

デッドロックの問題である可能性があります。レコードを更新しようとしているときに、それらのレコードを読み取っている人もいます。

あなたの更新ステートメントは完全なステートメントです。トランザクションで実行されていないと思います。読み取りステートメント (選択を使用) ではなく、更新されたステートメントを完了することを優先したいようです。

上記のシナリオでは、読み取り中に NoLock を使用して、ファントム読み取りを許可できます (ユーザーが選択クエリを実行するたびに、異なる出力が得られます)。あなたのシナリオでは、コミットされたレコードのみを読み取るため、ダーティ リードにはなりません。

SELECT count(1) FROM notifications (NOLOCK) WHERE user_id=123 AND unseen=1
于 2012-05-03T13:55:29.353 に答える
-1

「更新」では、レコードの Primery キーのようなもので見たレコードをマークする必要があります。

UPDATE notifications SET unseen=0 WHERE user_id=123 AND unseen=1 and PKID='some thing'
于 2012-05-03T06:41:53.480 に答える