INSERT ... FOR UPDATE这把锁你用过没?

简介: INSERT ... FOR UPDATE这把锁你用过没?

引言

了不起最近处理了一个生产问题,具体情况是这样的:

就是两个sql语句在同一个代码块中,第一个sql语句是对设备状态根据设备ID批量删除,第二个sql语句是批量插入,插入的设备ID和删除的设备ID是同一个。

本地和测试环境当时都好好的,可是上了生产环境,报错了

错误是存在重复的唯一索引,代码逻辑很简单

可以看到就是一个批量删除,再批量插入,测试环境当时没有用多个实例进行测试,上产是有多个实例的,错误的发生情况当天下班后一直分析到晚上12点,终于分析出来了,如下图:

可以看到是同时来了两个请求,分别落到了2台机器,这段代码在2个机器上执行就不能保证顺序性了,这个要加锁的话也是分布式锁。

不过还可以通过数据库的行锁来实现,接下来我们就一起来看看INSERT ...  FOR UPDATE语句。

MySQL的 INSERT ... FOR UPDATE语句可以用于在插入新行的同时对这些行进行加锁,从而防止其他事务对这些行进行修改。下面简要介绍 INSERT ... FOR UPDATE语句的原理和应用场景,并举例说明其具体用法。

一、INSERT ... FOR UPDATE语句的原理

INSERT ... FOR UPDATE语句会在执行插入操作时,对插入的新行进行排他锁(Exclusive Lock)的加锁操作,从而避免其他事务对这些新行进行修改。

这种锁定机制同样是基于MySQL的事务隔离级别实现的,只有在可重复读(REPEATABLE READ)和串行化(SERIALIZABLE)隔离级别下,INSERT ... FOR UPDATE语句才能生效。

二、INSERT ... FOR UPDATE语句的应用场景

  1. 防止重复插入

在某些业务场景下,可能需要对某些数据进行唯一性约束,避免重复插入相同的数据。使用 INSERT ... FOR UPDATE语句可以避免并发的情况下,多个事务同时插入相同的数据。

  1. 实现悲观锁

在某些业务场景下,需要对某些数据进行严格的控制,确保数据不会被其他事务修改。使用 INSERT ... FOR UPDATE语句可以实现悲观锁,确保数据的安全性。

  1. 实现乐观锁

使用 INSERT ... FOR UPDATE语句可以实现乐观锁机制,即在插入数据的同时,记录数据的版本号或时间戳等信息,如果在插入时发现版本号或时间戳已经存在,则说明其他事务已经插入了相同的数据,需要进行相应的处理。

三、INSERT ... FOR UPDATE语句的应用举例

下面举例说明 INSERT ... FOR UPDATE语句的具体用法。

假设有一个用户表user,其中包含用户ID和用户名两个字段,现在需要往用户表中插入新用户,假设插入流程如下:

  1. 根据用户ID查询用户是否已经存在
  2. 如果用户不存在,则插入新用户

在这个过程中,需要对用户ID进行唯一性约束,避免重复插入相同的用户。

可以使用如下的SQL语句来实现插入操作:

START TRANSACTION;
SELECT * FROM user WHERE user_id = '123' FOR UPDATE;
INSERT INTO user(user_id, username) VALUES ('123', 'John');
COMMIT;

在这个SQL语句中,SELECT ... FOR UPDATE语句用于对选定的行进行加锁,防止其他事务对这些行进行修改,从而避免重复插入相同的用户。如果查询结果为空,则可以插入。

四、生产问题的解决

了不起这边处理的方式就很简单了,直接将批量插入sql的语句末尾加上了 FOR UPDATE。语法参考:

insert into tablename values() on duplicate key update columnName = valueName;

由于具体涉及公司隐私就不贴sql语句了,原理就是当执行插入的时候,如果已经有这条数据存在,那么就更新它,就不会存在说已经插入了的数据在插入一条会报重复Key这个情况。

简单的INSERT ... FOR UPDATE你掌握了吧,后面我们继续学习。

相关文章
|
11天前
|
SQL 数据库
UPDATE
【11月更文挑战第04天】
20 1
|
6月前
|
关系型数据库 MySQL 数据库
INSERT IGNORE与INSERT INTO的区别
INSERT IGNORE与INSERT INTO的区别
124 0
|
6月前
|
关系型数据库 索引
select for update有什么含义,会锁表还是锁行还是其他。
select for update有什么含义,会锁表还是锁行还是其他。
|
6月前
|
SQL
DML(insert与delete)
DML(insert与delete)
41 0
insert和insertselective的区别
insert和insertselective的区别
188 0
|
6月前
|
SQL 关系型数据库 MySQL
MySQL insert 遇到delete 唯一键未提交导致死锁
一 前言死锁,其实是一个很有意思也很有挑战的技术问题,大概每个DBA和部分开发同学都会在工作过程中遇见 。关于死锁我会持续写一个系列的案例分析,希望能够对想了解死锁的朋友有所帮助二案例分析2.1 业务场景用户录入商品,应用程序会提前检查是否存在相同记录,如果有则先删除再插入;如果没有则直接插入。2....
292 0
|
SQL Java 数据库连接
INSERT操作
INSERT操作
87 0
|
关系型数据库 PostgreSQL
PostgreSQL merge insert(upsert/insert into on conflict) 如何区分数据是INSERT还是UPDATE
标签 PostgreSQL , merge insert , upsert , insert into on conflict , 区分 insert update , xmin , xmax 背景 使用insert into on conflict update语法,可以支持UPSERT的功能,但是到底这条SQL是插入的还是更新的呢?如何判断 通过xmax字段的值是否不为0,可以判断,如果是UPDATE,XMAX里面会填充更新事务号。
2148 0
|
Web App开发 异构计算