繁体   English   中英

并发,锁定SQL Server数据库

[英]Concurrency, Locking in SQL Server Database

我需要保存/更新15个表中的数据。 我必须确保在更新时应保持并发性和锁定,以免发生脏读。 我正在使用存储过程更新数据。 我可以在oredr中执行哪些操作来实现锁定和并发?

其他答案假设您已经在使用事务。 我不会忽略这一点,因为您可能会错过它。

您应该使用事务来确保所有15个表中的记录都没有插入或更新。 事务确保您操作中的原子性。 如果在存储过程中某些操作失败,并且您不使用事务,则将执行某些保存/更新操作,而不会进行某些操作(来自产生错误的查询的操作)。

如果将BEGIN TRAN和COMMIT用于成功的操作,或者在失败的情况下使用ROLLBACK,则将全部完成,否则将一事无成。 您应在每次查询执行后检查错误,如果有查询,则调用ROLLBACK TRANSACTION,或在存储过程的末尾调用COMMIT。

这个Stackoverflow问题的公认答案中有一个很好的示例,说明如何在存储过程中处理事务。

完成交易后,第二部分就是如何避免脏读 您可以将数据库的隔离级别设置为READ COMMITED,这将默认情况下防止对数据进行脏读。 但是用户仍然可以通过在查询中指定WITH(NOLOCK)或READUNCOMMITED来选择进行脏读取。 您无法阻止。

此外,还有快照隔离级别(快照和已提交读快照)可以防止锁定(并不总是很好),同时避免脏读。

互联网上有很多有关此主题的文献。 如果您对快照隔离级别感兴趣,建议您阅读Brent Ozar的Kendra Little撰写的这篇很棒的文章

您无法防止不会发生脏读。 做脏读的是读者 ,而不是你(作家)。 您所要做的就是确保您的写入是原子的 ,这是通过将所有写入包装在单个事务中来完成的。 这样,不会发出脏读的读者将看不到您的所有更新,也看不到(原子的)更新。

如果读者选择发表脏读, 那么您将无能为力

请注意, 更改隔离级别对读者的隔离级别任何作用。

您需要做的所有事情,以确保正确设置了sql server隔离级别 要消除脏读,它必须处于Read Committed或更高的状态(而不是Read Uncommitted )。 读取已提交是开箱即用的默认设置。

但是,值得回顾一下上面的链接,看看较高的设置可以带来什么好处(和后果)。

您可以将事务隔离级别设置为SERIALIZABLE。 通过使用以下语句

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 

在开始交易但发出警告之前,它可能会使其他尝试查看更新或将数据插入表中的用户的速度变慢,您还可以使用SNAP_SHOT隔离级别,该级别仅向您显示最后的提交/保存的数据,但是大量使用Temp DB也会影响性能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM