MySQL实战45讲Day39----insert语句的锁

一、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的所有行和间隙加锁的原因:
  对于这个执行序列:

  实际的执行效果是,如果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中,出现主备不一致

注意

  • 主要考虑的是日志和数据的一致性。
  • 对目标表不是锁全表,而是只锁住需要访问的资源

二、insert 循环写入:

1、对于语句:insert into t2(c,d) (select c+1, d from t force index(c) order by c desc limit 1);//往表t2中插入一行数据,这一行的c值是表t中c值的最大值加1。:

  这个语句的加锁范围,就是表t索引c上的(4,supremum]这个next-key lock和主键索引上id=4这一行。
  该语句的执行流程是:从表t中按照索引c倒序,扫描第一行,拿到结果写入到表t2中。

  该语句执行的慢查询日志(slow log)为:
  因此整条语句的扫描行数是1。(Rows_examined :1)

2、对于语句:insert into t(c,d) (select c+1, d from t force index(c) order by c desc limit 1);:

  该语句执行的慢查询日志(slow log)为:

  因此整条语句的扫描行数是5。(Rows_examined :5)

  该语句的explain结果为:

  该语句的执行过程为:

  • 创建临时表,表里有两个字段c和d。

  • 按照索引c扫描表t,依次取c=4、3、2、1,然后回表,读到c和d的值写入临时表。这时,Rows_examined=4。

  • 由于语义里面有limit 1,所以只取了临时表的第一行,再插入到表t中。这时,Rows_examined的值加1,变成了5。

注意

  • 这个语句会导致在表t上做全表扫描,并且会给索引c上的所有间隙都加上共享的next-key lock。所以,这个语句执行期间,其他事务不能在这个表上插入数据。
  • 执行需要临时表的原因:这类一边遍历数据,一边更新数据的情况,如果读出来的数据直接写回原表,就可能在遍历过程中,读到刚刚插入的记录,新插入的记录如果参与计算逻辑,就跟语义不符。
  • 由于实现上这个语句没有在子查询中就直接使用limit 1,从而导致了这个语句的执行需要遍历整个表t。它的优化方法也比较简单,就是先insert into到临时表temp_t,这样就只需要扫描一行;然后再从表temp_t里面取出这行数据插入表t1。

三、insert 唯一键冲突:

1、
唯一键冲突加锁

  在可重复读(repeatable read)隔离级别下执行。可以看到,session B要执行的insert语句进入了锁等待状态。session A执行的insert语句,发生主键冲突的时候,并不只是简单地报错返回,还在冲突的索引上加了锁。而由于一个next-key lock就是由它右边界的值定义的。这时候,session A持有索引c上的(5,10]共享next-key lock(读锁)。
  加这个读锁,从作用上来看,这样做可以避免这一行被别的事务删掉。

2、
唯一键冲突--死锁

  现象:在session A执行rollback语句回滚的时候,session C几乎同时发现死锁并返回。

  死锁产生的逻辑:

  • 在T1时刻,启动session A,并执行insert语句,此时在索引c的c=5上加了记录锁。注意,这个索引是唯一索引,因此退化为记录锁。
  • 在T2时刻,session B要执行相同的insert语句,发现了唯一键冲突,加上读锁;同样地,session C也在索引c上,c=5这一个记录上,加了读锁。
  • T3时刻,session A回滚。这时候,session B和session C都试图继续执行插入操作,都要加上写锁。两个session都要等待对方的行锁,所以就出现了死锁。

      流程的状态变化图:

四、insert into … on duplicate key update:

  对于语句:insert into t values(11,10,10) on duplicate key update d=100;,

  1. 会给索引c上(5,10] 加一个排他的next-key lock(写锁)。
  2. insert into … on duplicate key update;这个语义的逻辑是插入一行数据,如果碰到唯一键约束,就执行后面的更新语句。
  3. 如果有多个列违反了唯一性约束,就会按照索引的顺序,修改跟第一个索引冲突的行。
  4. 假设现在表t里面已经有了(1,1,1)和(2,2,2)这两行,下面这个语句执行的效果:


    两个唯一键同时冲突

    可以看到:

  • 主键id是先判断的,MySQL认为这个语句跟id=2这一行冲突,所以修改的是id=2的行。
  • 需要注意的是,执行这条语句的affected rows返回的是2,很容易造成误解。实际上,真正更新的只有一行,只是在代码实现上,insert和update都认为自己成功了,update计数加了1, insert计数也加了1。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容