专栏首页DDD死锁分析延续

死锁分析延续

根据上一篇【死锁分析】,又重新梳理了一下,画图表示更形象一些

【使用电脑阅读更佳】

事务 1

事务 2

-

begin

begin

delete id=1;(1)id加锁、(2)A加锁

delete id=2;(3)id加锁、(4)A加锁

-

  • | update ? where userid=? and tenantid=? and no=?;
  • | 如果先走no索引,已经持有B锁,再去持D锁时等待 update ? where userid=? and tenantid=? and no=?; | - 先走no索引,持B锁时等待;deadlock |-

update ? where userid=? and tenantid=? and no=?;如果先走(tenantid,userid) 则是日志一

先走no,则是日志二

索引交叉,则是日志三


最近借着死锁事项,又温习了部分数据库的理论知识,后面有时间再整理。现在的程序员真难,得上知天文,下知地理;这应该是DBA的专长,作为开发也得去深究,真难

在追查死锁的过程中,对照理论有一些实践,总结一下:

查看事务自动提交选项

show session variables like 'autocommit';show global variables like 'autocommit’;
set session autocommit=0;set global autocommit=0;

查看事务隔离级别

select @@tx_isolation

查看锁信息,想查看一条sql使用了什么锁,需要打开锁监听

show session variables like '%output%';
#开启InnoDB锁监控set global innodb_status_output_locks=on;
set global innodb_status_output=on;#上面的语句可定期写入到标准错误输出(stderr,即error log,大概每15s写一次),你也可以使用 SHOW ENGINE INNODB STATUS 语句直接在客户端获取innodb信息
show session variables like '%output%';

要启用InnoDB锁定监视器的 SHOW ENGINE INNODB STATUS输出,只需启用innodbstatusoutput_locks

打开监控开关后,在mysql日志文件中会出现

=====================================2020-06-30 15:44:46 7fdc8a76e700 INNODB MONITOR OUTPUT=====================================
----------------------------END OF INNODB MONITOR OUTPUT============================

打开锁监控,可以确定一下常用语句的锁信息

执行完一条SQL,使用SHOW ENGINE INNODB STATUS打印出锁信息

delete from invoice_collection_info where id=1275244823997059072
TABLE LOCK table `assist`.`invoice_collection_info` trx id 1636893 lock mode IXRECORD LOCKS space id 18491 page no 211 n bits 104 index `PRIMARY` of table `assist`.`invoice_collection_info` trx id 1636893 lock_mode X locks rec but not gap

delete语句,根据主键删除操作;可以明显看出上了表锁IX model,还有一个主键索引锁

其实如果有二级索引,还会有二级索引锁,但那是隐式锁,所以没有显示出来,后面会有试验让隐式锁显示化


使用二级索引删除操作

delete FROM invoice_item WHERE ( collection_id = 1275244823997059072 );
TABLE LOCK table `assist`.`invoice_item` trx id 1636964 lock mode IXRECORD LOCKS space id 18493 page no 4 n bits 784 index `idx_collection_id` of table `assist`.`invoice_item` trx id 1636964 lock_mode X locks rec but not gapRecord lock, heap no 563 PHYSICAL RECORD: n_fields 2; compact format; info bits 0 0: len 8; hex 91b2946930001000; asc    i0   ;; 1: len 8; hex 91b2ae5d61401000; asc    ]a@  ;;
RECORD LOCKS space id 18493 page no 12 n bits 96 index `PRIMARY` of table `assist`.`invoice_item` trx id 1636964 lock_mode X locks rec but not gapRecord lock, heap no 28 PHYSICAL RECORD: n_fields 23; compact format; info bits 0

先在二级索引上加锁,再在对应的主键索引上加锁


使用二级索引查询

select * from invoice_collection_info where invoice_uiq_flag = '031001900104-62079412' for update
TABLE LOCK table `assist`.`invoice_collection_info` trx id 1636947 lock mode IXRECORD LOCKS space id 18491 page no 642 n bits 344 index `idx_uniflag` of table `assist`.`invoice_collection_info` trx id 1636947 lock_mode X locks rec but not gap
RECORD LOCKS space id 18491 page no 496 n bits 96 index `PRIMARY` of table `assist`.`invoice_collection_info` trx id 1636947 lock_mode X locks rec but not gap

从日志中看出,先在invoice_uiq_flg二级索引上加锁,再在主键索引加锁


使用主键更新操作

update invoice_collection_info set invoice_uiq_flag = '031200190010-62079412' WHERE (  id = 1275244823997059072 ); TABLE LOCK table `assist`.`invoice_collection_info` trx id 1636958 lock mode IXRECORD LOCKS space id 18491 page no 741 n bits 88 index `PRIMARY` of table `assist`.`invoice_collection_info` trx id 1636958 lock_mode X locks rec but not gap

其实不仅会在主键加X,还会在二级索引上也加X,但没有显示出来;这儿跟delete一样,其实也是个隐式锁


模拟测试了一下,两条sql,一条根据二级索引删除操作、另一条使用主键更新记录模拟并发死锁,把update中的二级索引锁显示出来了


上面的操作都是在RC级别下进行的,对于select操作,快照读都不会加锁,实验结果也与理论一致

本文分享自微信公众号 - 码农戏码(coder-game),作者:朱先生

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-07-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 死锁分析

    日志二和日志三sql完全一样,其实是两次调用(同一时刻并发调用),调用条件不同,但在程序处理时这条SQL的where条件一样而已

    码农戏码
  • MySQL死锁分析

    当业务并发比较高时,如果数据库访问设计得不合理,可能时不时就爆出一个死锁错误。业务上表现为一个偶现的失败。这种情况,有时候非常让人抓狂,感觉无从入手。这里就介绍...

    海伯利安
  • 【MySQL】mysql死锁以及死锁日志分析

    死锁:死锁一般是事务相互等待对方资源,最后形成环路造成的。 对于死锁,数据库处理方法:牺牲一个连接,保证另外一个连接成功执行。 发生死锁会返回ERR...

    用户5522200
  • PostgreSQL 死锁与分析

    任何数据库都有死锁,MYSQL的死锁有相关的工具,或者去日志查找,postgresql的死锁又怎么搞,今天的来说说。

    AustinDatabases
  • 两次死锁的分析

    以上过程,因为S锁升级为X锁的时间间隔很短,所以不是很好复现,一般在高并发的时候出现。不过可以用3个事务来复现:

    十毛
  • 一个AB锁死锁问题分析

    1,查看dmesg日志可以看到node在重启前确实出现频繁的cgroup oom:

    chudihuang
  • 一个死锁分析过程

    第一步的目标是找到锁被谁持有了,这只需要找到死锁的位置,然后查看pthread_mutex_t.__owner值是什么。接下来使用GDB的“info thr...

    一见
  • MySQL锁等待与死锁问题分析

    在 MySQL 运维过程中,锁等待和死锁问题是令各位 DBA 及开发同学非常头痛的事。出现此类问题会造成业务回滚、卡顿等故障,特别是业务繁忙的系统,出现死锁问题...

    MySQL技术
  • mysql insert duplicate key update 死锁分析

    数据入库这块有离线和实时两套入库系统,写同一个db的同一批mysql表,两边用的都是insert into table on duplicate key upd...

    YG
  • 一次线上Mysql死锁分析

    这个表用来保存用户的收货地址,下单时需要选择相应的收货地址;通过查看日志平台日志,出问题的主要发生在添加地址的场景。

    心平气和
  • 一个Linux死锁信息分析

    这个事情很奇怪,我不觉得它提出来的Possible unsafe locking scenario真的会死锁啊。

    猿哥
  • 数据库死锁怎么分析?

    我们为hero表的id列创建了聚簇索引,为name列创建了一个二级索引。这个hero表主要是为了存储三国时的一些英雄,我们向表中插入一些记录:

    Bug开发工程师
  • Java - 死锁 Dead Lock 定位分析

    JVM-11虚拟机性能监控与故障处理工具之【JDK的可视化工具-JConsole】

    小小工匠
  • 死锁(Deadlock)简析

    比如A进程占有资源R1,需要资源R2,而B进程占有资源R2并需要资源R1,A、B进程互相等待对方完成任务并释放资源,形成了死锁。

    gojam
  • MySQL死锁系列-常见加锁场景分析

    在上一篇文章《锁的类型以及加锁原理》主要总结了 MySQL 锁的类型和模式以及基本的加锁原理,今天我们就从原理走向实战,分析常见 SQL 语句的加锁场景。了解了...

    程序员历小冰
  • 【死磕Java并发】----- 死磕 Java 并发精品合集

    【死磕 Java 并发】系列是 LZ 在 2017 年写的第一个死磕系列,一直没有做一个合集,这篇博客则是将整个系列做一个概览。

    用户1655470
  • 浅析一个postgresql的死锁问题

    之前写过一篇文章(浅析一个sql server数据库事务死锁问题),简单分析了一个sql server数据库的死锁问题及索引对执行计划的影响;这里继续分享一个p...

    Bruce Li
  • 一个MySQL死锁的问题分析

    两个事务相互等待时,当一个等待时间超过设置的某一阀值时,对其中一个事务进行回滚,另一个事务就能继续执行。一般不需要人为介入,这种方法简单有效,在innodb中,...

    MySQL轻松学
  • 这样分析一个死锁问题

    之前也列举了几期的MySQL死锁问题,光有操作演练,还缺少一些自己的分析,所以我就打算补充一下。 首先对于死锁问题,我们分析的背景是基于MySQL事...

    jeanron100

扫码关注云+社区

领取腾讯云代金券