我有一个包含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)在锁定时陷入僵局;与另一个进程通信缓冲资源并被选为死锁牺牲品。重新运行该交易。
答案 0 :(得分:0)
它可能是死锁的问题,当你试图更新记录时,有些人也在阅读这些记录。
您的更新语句是一个完整的声明,我认为它没有在事务中运行。看来,您希望获得更多优先级来完成更新的语句而不是读取语句(使用select)。
对于上述场景,您可以在阅读时使用NoLock允许幻像读取(每次用户使用时执行选择查询获得不同的输出)。在您的场景中,它不会是脏读,因为您将只读取提交的记录。
SELECT count(1) FROM notifications (NOLOCK) WHERE user_id=123 AND unseen=1
答案 1 :(得分: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提示,可以避免死锁。
答案 2 :(得分:-1)
在“更新”中,您应该使用记录的Primery键之类的内容标记您所看到的记录。
UPDATE notifications SET unseen=0 WHERE user_id=123 AND unseen=1 and PKID='some thing'