使用 SQL NOWAIT 的最佳方式

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

由于所有的主要数据库都支持此功能,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选项即可,如以下示例所示:




Post post = entityManager.find(    Post.class,    postId,    LockModeType.PESSIMISTIC_WRITE,    Map.of(        SpecHints.HINT_SPEC_LOCK_TIMEOUT,        LockOptions.NO_WAIT    ));

就是这么简单!

相关实践学习
体验RDS通用云盘核心能力
本次实验任务是创建一个云数据库RDS MySQL(通用云盘),并通过云服务器ECS对RDS MySQL实例进行压测,体验IO加速和IO突发带来的性能提升;并通过DMS执行DDL,将数据归档到OSS,再结合云盘缩容,体验数据归档带来的成本优势。
相关文章
|
5月前
|
SQL 缓存 数据处理
SQL执行方式
【7月更文挑战第22天】SQL执行方式
37 2
|
7月前
|
SQL 数据库
SQL-修改数据
SQL-修改数据
|
7月前
|
SQL 数据库
三、SQL的基础查询
三、SQL的基础查询
58 0
|
SQL 关系型数据库 MySQL
SQL 解析详解
SQL 解析详解
SQL 解析详解
|
SQL 存储 关系型数据库
SQL必会的基础哈
《基础系列》
161 0
|
SQL 存储 关系型数据库
SQL,何必在忆之一(基础篇)
很久之前就学了SQL,然而又忘记,今天正式系统的性的回顾一下,温故而知新。可以为师矣
117 0
SQL,何必在忆之一(基础篇)
8个实用SQL操作小技巧
SQL在使用过程中,经常会遇到一些奇奇怪怪的小问题,今天给大家总结一下常见的几个问题该如何处理。
8个实用SQL操作小技巧
|
SQL XML 数据库
一行SQL代码能做什么?(下)
最近在知乎上看到一个问题:一行代码可以做什么?答题者数万计,都是一些非常“高端”的操作,就在想一行SQL代码能做什么呢?
一行SQL代码能做什么?(下)
一行SQL代码能做什么?(上)
最近在知乎上看到一个问题:一行代码可以做什么?答题者数万计,都是一些非常“高端”的操作,就在想一行SQL代码能做什么呢?
一行SQL代码能做什么?(上)
一行SQL代码能做什么?(上)
最近在知乎上看到一个问题:一行代码可以做什么?答题者数万计,都是一些非常“高端”的操作,就在想一行SQL代码能做什么呢? SQL一行代码其实有很多很多,一些常见的比如: SELECT * FROM TableName INSERT INTO TableName VALUES(...) TRUNCATE TABLE TableName ..... 这些就没什么意思了,我们来给大家看一些比较“高级”的。
一行SQL代码能做什么?(上)