您好,欢迎访问代理记账网站
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

【MySQL45讲】insert语句锁的优化

MySQL对自增主键锁做了优化,尽量在申请到自增id以后,就释放自增锁

insert语句是一个很轻量的操作,不过,这个结论对于"普通的insert语句"才有效,也就是说,还有些insert语句是属于特殊情况的,在执行过程中需要给其他资源加锁,或者无法在申请到自增id以后就立马释放自增锁

接下来聊聊这个话题

一、insert … select语句

表t和t2的表结构和初始化数据语句如下:

表结构语句:

CREATE TABLE `t` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `c` int(11) DEFAULT NULL,
 `d` int(11) DEFAULT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `c` (`c`)
) ENGINE=InnoDB;

初始化数据语句:

insert into t values(null, 1,1);
insert into t values(null, 2,2);
insert into t values(null, 3,3);
insert into t values(null, 4,4);
create table t2 like t

现在看看在可重复读隔离级别下,binlog_format=statement时执行:

insert into t2(c,d) select c,d from t;

为什么执行这个语句时,需要对表t的所有行和间隙加锁呢?

其实,这个问题需要考虑的还是日志和数据的一致性,看看并发insert场景时的执行序列:

在这里插入图片描述
实际的执行效果是,如果session B先执行,由于这个语句对表t主键索引加了(-∞,1]这个next-key lock,会在语句执行完成后,才允许session A的insert语句执行

但如果没有锁的话,就可能出现session B的insert语句先执行,但是后写入binlog的情况
于是,在binlog_format=statement的情况下,binlog里面就记录了这样的语句序列:

insert into t values(-1,-1,-1);
insert into t2(c,d) select c,d from t;

这个语句到了备库执行,就会把id=-1这一行也写到表t2中,出现主备不一致


分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进