在 SQL Server 中选择更新期间选择正确的提示

问题描述 投票:0回答:1

我们有一个 Spring 应用程序,它使用 ** SQL Server** 作为具有 Hibernate 方言的数据库:

org.hibernate.dialect.SQLServer2012Dialect
延伸
org.hibernate.dialect.SQLServer2005Dialect

我们决定并随后对具有默认隔离的事务中中央 JPA 实体的所有更新仅实现一种类型的锁定 (悲观读取) - READ_COMMITTED。 实现本身由事务服务方法组成,这些方法检索并更新调用带有注释的存储库方法的实体: @Lock(LockModeType.PESSIMISTIC_READ) 我们这样做是为了防止静默丢失更新。这是正确的选择吗?

过了一会儿,我们注意到抛出了很多 org.hibernate.exception.LockAcquisitionException / org.springframework.dao.CannotAcquireLockException 。 根据 SQLServer2005Dialect,使用提示 (holdlock, rowlock) 检索实体以进行更新,并且在检索多个实体进行更新的每个事务期间,整个表都被锁定以进行更新。 我们想知道是否实现我们自己的 Hibernate 方言,扩展 SQLServer2012Dialect 并在检索实体进行更新时用另一个提示覆盖。 我们走在正确的道路上吗?

如果没有进一步的配置,提示的组合(updlock、rowlock)不能满足我们的要求,因为经过测试,我们注意到检索一行进行更新会阻止检索另一行进行更新。 在查询中提供哪些提示以及是否需要额外的配置?

这是期望的行为:

  • 所有记录应该能够随时读取(而不是更新)而不会阻塞。
  • 应该可以随时插入新记录而不会阻塞。
  • 并发检索更新相同的行应该是不可能的。
  • 并发检索不同行的更新应该可以不阻塞。
sql-server spring locking hint
1个回答
0
投票

您对于在 RDBMS 中使用锁定的方式完全错误。使用提示是最糟糕的事情,因为您静态地施加锁,而 SQL Server 以最合适的方式自动选择它,此外还动态地选择它(它可以在事务期间更改锁的粒度,因为它有能力这样做:“锁定升级”)。

所以让他自然地做出最好的选择。 SQL Server 配备了关系 DBMS 领域最好的优化器之一。

根据您的请求,使用以下命令启用乐观锁定模式:

ALTER DATABASE CURRENT SET READ_COMMITTED_SNAPSHOT ON WITH NO_WAIT;

并使用更新的可串行化隔离级别强制悲观锁定

© www.soinside.com 2019 - 2024. All rights reserved.