首页 > 解决方案 > 隔离级别和选择更新

问题描述

关系数据库的隔离级别和隔离级别之间有什么关系select for update

如果我使用与 SQL Server 的普通 JDBC 连接并将隔离级别设置为 READ_REPEATABLE 并使用简单的select,我是否会看到可重复读取的不一致?或者我应该使用select for updatealways 来避免事务中不一致的可重复读取?如果是这样,隔离级别的处理是什么,它们将如何发挥作用?

标签: sqlsql-servertransactionsrdbms

解决方案


SQL Server 没有select ... for update语法。SQL Server 中的等价物是使用 UPDLOCK 表提示。

当读取一行并立即更新原子事务中的同一行时使用此提示。例如

declare @balance = (select balance from account where accountId = @id)
update account set balance = @balance + @amount where accountId = @id

在 READ COMMITTED 或任何没有多语句事务的隔离级别,多个会话可以运行第一个查询,并且在更新余额时丢失了更新。

使用 REPEATABLE READ 或 SERIALIZABLE 隔离级别将防止这种更新异常,但如果有任何并发​​事务已读取该行,并且如果其他事务之一尝试更新该行,它们会阻止第一个写入程序,从而导致僵局。

大多数情况下,这种行为不值得付出性能成本和处理死锁的烦恼。因此,您在读取时使用“select for update”(即 UPDLOCK)在行上放置 U 锁,并阻止后续读取器获取冲突锁。

例如

declare @balance = (select balance from account with (updlock) where accountId = @id)
update account set balance = @balance + @amount where accountId = @id

推荐阅读