前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >使用 SQL NOWAIT 的最佳方式

使用 SQL NOWAIT 的最佳方式

作者头像
姚远OracleACE
发布2023-04-06 18:45:17
发布2023-04-06 18:45:17
1K00
代码可运行
举报
文章被收录于专栏:oracleaceoracleace
运行总次数:0
代码可运行

摘要:SQL NOWAIT使我们能够在获取行级锁时避免阻塞,本文中我们将学会使用这个功能最佳方法。

原文网址:https://vladmihalcea.com/sql-no-wait/?spm=wolai.workspace.0.0.7d3133509qYp1k

作者:Vlad Mihalcea,Java Champion,著有《High-Performance Java Persistence》,这本书是Amazon上最畅销的Java书之一。他目前正在开发Hypersistence Optimizer,他还利用业余时间开发各种开源项目,例如Hibernate Types和FlexyPool,并在StackOverflow网址上回答问题。

由于所有的主要数据库都支持此功能,Hibernate提供了一个NOWAIT选项,可以在不同数据库上调用这个功能,而且不影响代码的数据库可移植性。

01

事务获取锁时被阻塞

关系数据库就像状态机一样运行,数据库事务将数据库从一个一致状态更改为另一个一致状态。如果出现数据一致性问题,数据库系统必须能够成功回滚所有未提交的更改,并将所有已经修改的记录还原到其之前的一致状态。即使大多数关系数据库系统使用 MVCC(多版本并发控制)机制来协调读写操作,每当执行 UPDATE 或 DELETE 操作时,仍会采用悲观锁定。每当我们对给定的表记录执行 UPDATE 或 DELETE 语句时,关系数据库系统都会获取并持有该记录的独占锁,直到当前事务以提交或回滚结束,如下图所示。

Alice的UPDATE锁定了表记录,因此当 Bob 想要使用FOR UPDATE子句获取锁时,他的锁获取请求将阻塞,直到 Alice 的交易结束或锁获取超时。使用 SELECT 查询的FOR UPDATE子句可以模拟相同的行为,如下图所示:

通过获取并保持独占锁直到事务结束,关系数据库系统避免了脏写,从而保证了事务的原子性。

02

SQL NOWAIT

为了避免SQL 语句在获取锁时被阻塞 ,我们可以使用 NOWAIT 子句,如下图所示:

现在,在获取锁时,该语句将立即抛出锁获取失败而不是阻塞,因此您可以捕获异常并继续执行其他操作,过段时间后再重新尝试获取锁。

不同的数据库系统的NOWAIT 子句并不相同,见下表:

数据库

独占锁的NOWAIT子句

Oracle

FOR UPDATE NOWAIT

SQL Server

WITH (UPDLOCK,HOLDLOCK,ROWLOCK,NOWAIT)

PostgreSQL

FOR NO KEY UPDATE NOWAIT

MySQL

FOR UPDATE NOWAIT

幸运的是,在使用 JPA 和 Hibernate 时,开发人员无需编写针对特定数据库的SQL语句即可获取正确的NOWAIT 子句,因为框架会根据底层的数据库生成正确的SQL 语法。因此,开发人员只需在获取行级锁时使用LockOptions.NO_WAIT选项即可,如以下示例所示:

代码语言:javascript
代码运行次数:0
运行
复制
Post post = entityManager.find(
    Post.class,
    postId,
    LockModeType.PESSIMISTIC_WRITE,
    Map.of(
        SpecHints.HINT_SPEC_LOCK_TIMEOUT,
        LockOptions.NO_WAIT
    )
);

就是这么简单!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-03-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 oracleace 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 事务获取锁时被阻塞
  • SQL NOWAIT
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档