我有一个3层应用程序并在客户端缓存数据,所以我需要知道服务器上的数据何时更改以保持此缓存同步。
所以我添加了一个" lastmodification"表中的字段,并在数据更改时更新此字段。但是一些父母的父母'如果修改子行(使用FK),则必须更新lastmodification行 从主表中获取MAX(lastmodification),从相关表中获取MAX,然后从这几个值中获取MAX,但是有点慢。 我的意思是:
MAX(MAX(MAIN_TABLE), MAX(CHILD1_TABLE), MAX(CHILD2_TABLE))
所以我切换并在此表中添加了一个触发器,以便更新TBL_METADATA表中的字段:
CREATE TABLE [TABLE_METADATA](
[TABLE_NAME] [nvarchar](250) NOT NULL,
[TABLE_LAST_MODIFICATION] [datetime] NOT NULL
现在相关的表格可以更新“主要内容”。通过更新元数据表中的最后一个修改来表最后修改时间。 现在快速获取lastmodification
但是......现在我有与更新此表相关的随机死锁。
这是由于2个事务在不同步骤修改TABLE_METADATA,然后相互锁定。
我的问题:你是否看到了一种方法来保持这种最后修改更新而不锁定行? 就我而言,我真的不在乎:
事实上,我真的不需要将这些更新放在交易中,但是当它们被触发器执行时,它会在当前交易中自动执行。
感谢您的帮助
答案 0 :(得分:1)
据我所知,你无法阻止U型锁。但是,您可以尝试使用with (rowlock)
将锁的数量减少到最少。
这将告诉查询优化器在更新行时逐个锁定行,而不是使用页面或表锁。
您还可以对连接到正在更新的表的表使用with (nolock)
。另一种方法是使用set transaction isolation level read uncommitted
。
但是请小心使用此方法,因为您可能会创建损坏的数据。
例如:
update mt with (rowlock)
set SomeColumn = Something
from MyTable mt
inner join AnotherTable at with (nolock)
on mt.mtId = at.atId
您还可以将with (rowlock)
和with (nolock)
/ set transaction isolation level read uncommitted
添加到经常读写相同表的其他数据库对象,以进一步降低发生死锁的可能性。
如果仍然发生死锁,您可以通过自联接减少目标表上的读锁定,如下所示:
update mt with (rowlock)
set SomeColumn = Something
from MyTable mt
where mt.Id in (select Id from MyTable mt2 where Column = Condition)
可以找到有关表提示的更多文档here.