使用 HSQLDB 的悲观行锁定

Posted

技术标签:

【中文标题】使用 HSQLDB 的悲观行锁定【英文标题】:Pessimistic row locking with HSQLDB 【发布时间】:2014-02-24 01:53:49 【问题描述】:

我需要为连接显式锁定表中的一行,其中:

读入数据; (中间会运行一些逻辑) 更新数据库中的对应行;

当其他连接无法读取数据时,禁用脏读(因此 ISOLATION 级别是没有问题的)。

阅读documentation,但不要完全理解它。我目前的理解是否正确:

将并发控制模型设置为 MVCC; 将事务隔离级别设置为 READ COMMITTED(实际上已经默认); 将手头的 Connection 对象的自动提交值设置为 false; 创建语句/PreparedStatement; 对语句或 PreparedStatement 对象运行“SELECT /--/ FOR UPDATE”查询并接收 ResultSet; -执行一些逻辑- 使用 ResultSet updateX() 方法或新的 UPDATE sql (executeUpdate()) 更新行。 提交更改。

任何步骤是多余的、遗漏的还是我完全误解了整个概念?

【问题讨论】:

【参考方案1】:

执行此操作的正确方法是在开头和结尾更新行。创建语句的步骤如下。

创建语句 使用其现有值(或更改的值,如果此时已知)更新该行 执行其他操作 使用更改的值更新行(如果之前未完成) 提交

如果您不按上述方式进行操作,则另一个事务可能会在此事务更改行之前更改行。

【讨论】:

为什么“SELECT /-/ FOR UPDATE”不为其他事务锁定行?您的第二步真的是锁定它的方法吗(即使用现有或更改的值进行更新)? PS,如果并发模型没有设置为MVCC,那么整个表都会被锁定,而不是单行,对吧? 它没有。第二步是锁定行。如果模型不是 MVCC,则整个表被锁定。如果不使用 MVCC,您可以显式锁定表以进行写入,而不是第一次更新。 我不明白这是如何实现悲观锁定的。因此,如果流程是: 1. 开始事务 2. SELECT 3. UPDATE(使用当前值) 4.(一些应用程序代码) 5. UPDATE(使用更新值) 6. Commit 如果 2 个线程同时执行此操作,则线程2 将在第 3 步阻塞。然而,当第一个线程提交时,线程 2 将继续执行步骤 #3 的更新,覆盖保存在线程 1 中的值。 -> 丢失更新。所以我不认为这个策略真的有效吗?我需要能够执行 SELECT ... FOR UPDATE 。欢迎任何提示, MVCC 没有悲观锁定。使用 LOCKS 模式进行悲观锁定。

以上是关于使用 HSQLDB 的悲观行锁定的主要内容,如果未能解决你的问题,请参考以下文章

Mysql:行锁 表锁 乐观锁 悲观锁 读锁 写锁

使用 EntityManager 在实体上设置悲观锁定

使用 NOLOCK 消除具有悲观锁定的应用程序的死锁

确保更新发生在 Hibernate/HSQLDB 中的并发锁定?

使用 Hibernate 和 HSQLDB 在数据库级别锁定实体

Lockmodetype.Pessimistic_Read 正在锁定锁定行以外的行