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在...
同样的sql语句查询条件和结果顺序都一致,按理不会导致一个锁了主键索引,等待锁非主键索引,另外一个锁了非主键索引,等待主键索引导致的死锁。 最后经过分析,我们项目里发现是for update的sql语句,和另外一个update非select数据的sql语句导致的死锁。 比如有60条数据,select .. for update查询第31-60条数据,update在...
SELECT ... FOR UPDATE:加排他(X)锁 INSERT / UPDATE / DELETE:加排他(X)锁 当前读在 RR 和 RC 两种隔离级别下的实现也是不一样的:RC 只加记录锁,RR 除了加记录锁,还会加间隙锁,用于解决幻读问题。 不同SQL 语句对加锁的影响 不同的 SQL 语句当然会加不同的锁,总结起来主要分为五种情况: ...
本文针对MySQL InnoDB中在Repeatable Read的隔离级别下使用select for update可能引发的死锁问题进行分析。 1. 业务案例 业务中需要对各种类型的实体进行编号,例如对于x类实体的编号可能是x201712120001,x201712120002,x201712120003类似于这样。可以观察到这类编号有两个部分组成:x+日期作为前缀,以及流水号(这里是四位的流...
时间前后相差 1s,但最终执行结果是,这两个事务相互死锁,均失败。 事务定义非常简单,伪代码描述如下: start transaction // 1、查询数据 data = select for update(tenantId, storeId, skuId); if (data == null) { // 插入数据 insert(tenantId, storeId, skuId); ...
对于前者, 在RC下只需要锁住满足条件的记录,就可以避免被其它事务修改,也就是 select for update, select in share mode; RR隔离下使用MVCC实现可重复读; 对于后者, 要锁住满足条件的记录及所有这些记录之间的gap,也就是需要 间隙锁 gap lock、临键锁 next-key lock。
2.select … in share mode,会给记录加S锁,但是根据隔离级别的不同,加锁的行为有所不同: RC隔离级别:是在记录上加S锁。 RR/Serializable隔离级别: 如果查询条件为唯一索引且是唯一等值查询时:是在该条记录上加S锁; 非唯一条件查询(查询会扫描到多条记录时):记录本身+记录的间隙(需要具体分析间隙的范围),加...