mysql> SELECT * FROM child WHERE id > 100 FOR UPDATE; 该事务在id>100的范围上加了gap lock mysql> START TRANSACTION; mysql> INSERT INTO child (id) VALUES (101); 另一个事务插入id=101的记录 哪些sql使用当前锁 sql insert into table value * update table set xxx where * delete table where ...
→ for update:InnoDB默认是行级别的锁,当有明确指定的主键时,使用的是行锁;否则使用的是表锁。使用情况详细如下: 明确指定主键,并且由此记录,行级锁。例:select name,age from tb_user where id = '1' 明确指定主键/索引,若查无记录,无锁。例:select name,age from tb_user where id = '1' 无主键/...
同样的sql语句查询条件和结果顺序都一致,按理不会导致一个锁了主键索引,等待锁非主键索引,另外一个锁了非主键索引,等待主键索引导致的死锁。 最后经过分析,我们项目里发现是for update的sql语句,和另外一个update非select数据的sql语句导致的死锁。 比如有60条数据,select .. for update查询第31-60条数据,update在...
在MySQL中select称为快照读,不需要锁,而insert、update、delete与select for update则称为当前读,需要给数据加锁,幻读中的“读”即是针对当前读。 本文针对MySQL InnoDB中在Repeatable Read的隔离级别下使用select for update可能引发的死锁问题进行分析。 1. 业务案例 业务中需要对各种类型的实体进行编号,例如对于x...
最后经过分析,我们项目里发现是for update的sql语句,和另外一个update非select数据的sql语句导致的死锁。 比如有60条数据,select .. for update查询第31-60条数据,update在更新1-10条数据,按照innodb存储引擎的行锁原理,应该不会导致不同行的锁导致的互相等待。开始以为是行锁在数据量较大情况下,会锁数据块。导致...
SELECT ... FOR UPDATE:加排他(X)锁 INSERT / UPDATE / DELETE:加排他(X)锁 当前读在 RR 和 RC 两种隔离级别下的实现也是不一样的:RC 只加记录锁,RR 除了加记录锁,还会加间隙锁,用于解决幻读问题。 不同SQL 语句对加锁的影响 不同的 SQL 语句当然会加不同的锁,总结起来主要分为五种情况: ...
InnoDB是基于索引来完成行锁,select * from tab_with_index where id = 1 for update;,for update可根据条件来完成行锁锁定,要求id是有索引键的列。如果 id 不是索引键那么InnoDB将完成表锁,并发将无从谈起。 InnoDB存储引擎的锁的算法有三种 Record lock:单个行记录上的锁 ...
时间前后相差 1s,但最终执行结果是,这两个事务相互死锁,均失败。 事务定义非常简单,伪代码描述如下: start transaction // 1、查询数据 data = select for update(tenantId, storeId, skuId); if (data == null) { // 插入数据 insert(tenantId, storeId, skuId); ...
2.select … in share mode,会给记录加S锁,但是根据隔离级别的不同,加锁的行为有所不同: RC隔离级别:是在记录上加S锁。 RR/Serializable隔离级别: 如果查询条件为唯一索引且是唯一等值查询时:是在该条记录上加S锁; 非唯一条件查询(查询会扫描到多条记录时):记录本身+记录的间隙(需要具体分析间隙的范围),加...