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语句无法通过索引进行Locking read,UPDATE,DELETE,那MySQL将扫描整个表,表中的每一行都将被锁定(在RC级别,通过semi-consistent read,能够提前释放不符合条件的记录;在RR级别,需设置innodb_locks_unsafe_for_binlog=1,才能打开semi-consistent read)。在某些场景下,锁也不会立即被释放。如union查询,生成一...
最后经过分析,我们项目里发现是for update的sql语句,和另外一个update非select数据的sql语句导致的死锁。 比如有60条数据,select .. for update查询第31-60条数据,update在更新1-10条数据,按照innodb存储引擎的行锁原理,应该不会导致不同行的锁导致的互相等待。开始以为是行锁在数据量较大情况下,会锁数据块。导致...
时间前后相差 1s,但最终执行结果是,这两个事务相互死锁,均失败。 事务定义非常简单,伪代码描述如下: start transaction // 1、查询数据 data = select for update(tenantId, storeId, skuId); if (data == null) { // 插入数据 insert(tenantId, storeId, skuId); ...
SELECT ... FOR UPDATE:加排他(X)锁 INSERT / UPDATE / DELETE:加排他(X)锁 当前读在 RR 和 RC 两种隔离级别下的实现也是不一样的:RC 只加记录锁,RR 除了加记录锁,还会加间隙锁,用于解决幻读问题。 不同SQL 语句对加锁的影响 不同的 SQL 语句当然会加不同的锁,总结起来主要分为五种情况: ...
2.select … in share mode,会给记录加S锁,但是根据隔离级别的不同,加锁的行为有所不同: RC隔离级别:是在记录上加S锁。 RR/Serializable隔离级别: 如果查询条件为唯一索引且是唯一等值查询时:是在该条记录上加S锁; 非唯一条件查询(查询会扫描到多条记录时):记录本身+记录的间隙(需要具体分析间隙的范围),加...
在RC级别中,数据的读取都是不加锁的,但是数据的写入、修改和删除是需要加锁的。这种隔离级别也支持所谓的不可重复读(Nonrepeatable Read)。 Repeatable Read(可重读) 这是MySQL中InnoDB默认的隔离级别。我们姑且分“读”和“写”两个模块来讲解。 读(快照读) ...