谈谈MySQL死锁之二 死锁检测和处理源码分析

这一篇主要是通过一个实验来进行描述,过程是比较枯燥的.

实验准备

create table test_lock(id int auto_increment primary key ,stock int) engine=innodb;

insert into test_lock(id,stock) value(1,50);

这里我把堆栈信息尽可能的简化,25个主要函数的名称和入参

后面为了突出主题,我对事务相关的函数加上这个开头死锁检测函数列表,一共10个函数

 

死锁检测函数列表A row_search_for_mysql(搜索行)

死锁检测函数列表B sel_set_rec_lock(判断是二级索引还是主键,然后对行加锁)

死锁检测函数列表C lock_clust_rec_read_check_and_lock(检查有锁堵塞)

死锁检测函数列表D lock_rec_lock 处理逻辑(检测锁的兼容性)

死锁检测函数列表E lock_rec_lock_slow处理逻辑(确认申请不到锁)

死锁检测函数列表F lock_rec_enqueue_waiting

死锁检测函数列表G lock_deadlock_check_and_resolve处理逻辑

死锁检测函数列表H lock_deadlock_search函数代码处理逻辑

死锁检测函数列表I lock_get_first_lock处理逻辑(第一个锁比较)

死锁检测函数列表J lock_get_next_lock函数代码处理逻辑(获取锁继续比较)

我们一个个来看这些函数的主要作用

死锁检测函数列表A row_search_for_mysql处理逻辑

作用:对数据库进行行的寻找

传入的参数是:

1.buf 缓存区,用于获取MySQl格式的行

2.mode 搜索的方式

3.prebuilt 预构表结构的相关信息

4.搜索的方向

返回结果:

@return DB_SUCCESS, DB_RECORD_NOT_FOUND, DB_END_OF_INDEX, DB_DEADLOCK,

DB_LOCK_TABLE_FULL, DB_CORRUPTION, or DB_TOO_BIG_RECORD */

在row_search_for_mysql搜索到行后,会对行进行加锁处理,也就是调用函数列表B sel_set_rec_lock处理逻辑

死锁检测函数列表B sel_set_rec_lock处理逻辑

作用:对一条记录进行加锁,返回结果为(DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code)

参数列表和备注

1.btr_pcur_get_block(pcur),记录对应的page的指针地址

2.rec:rec = btr_pcur_get_rec(pcur)对于的行的指针地址

3.index:prebuilt->index,表的索引

4.offsets:offsets是一个数组,默认100个元素,offsets = rec_get_offsets(next_rec, index, offsets,ULINT_UNDEFINED, &heap);

5.prebuilt->select_lock_type 表锁的类型(LOCK_NONE,LOCK_S, or LOCK_X)

6.lock_type:这里指的是行级锁(LOCK_REC_NOT_GAP,LOCK_GAP,LOCK_ORDINARY(Next-Key Lock))

7.thr:查询图查询线程节点 赋值thr = que_fork_get_first_thr(prebuilt->sel_graph);

死锁检测函数列表C lock_clust_rec_read_check_and_lock处理逻辑

作用:

检查其他事务的锁是否阻止立即读取或传递通过读取游标读取聚簇索引记录.

这个函数的作用主要是检查其他事务的锁是否堵塞了当前读,或者通过传递一个读取游标来读取主键索引记录。

如果他们这样做,首先测试

如果查询线程应该由于某种原因暂停;

如果没有,那么将事务和查询线程置于锁等待状态,并插入一个等待对锁队列的记录锁请求。

设置请求的模式锁定在记录上

死锁检测函数列表D 函数 lock_rec_lock 处理逻辑

作用:

尝试去对指定的行进行加锁,如果不能进行加锁,则进入lock_rec_lock_slow函数里面的处理逻辑

死锁检测函数列表E函数 lock_rec_lock_slow处理逻辑

作用:事务所请求的锁和别的事务有冲突(别人已经持有),进入lock_rec_enqueue_waiting进行处理

死锁检测函数列表F 函数 lock_rec_enqueue_waiting处理逻辑

作用:进入死锁检测函数lock_deadlock_check_and_resolve

死锁检测函数列表G 函数 lock_deadlock_check_and_resolve处理逻辑

作用:构造锁竞争的信息,然后把锁竞争的信息带入到lock_deadlock_search函数

死锁检测函数列表H函数 lock_deadlock_search函数代码处理逻辑

作用:通过锁竞争信息,对比两个事务对于的记录的heap_no,看两个事务所持有的锁是否为对方所需要的,进入到lock_get_first_lock来进行遍历

死锁检测函数列表I 函数lock_get_first_lock处理逻辑

作用:把参与锁竞争的事务的第一个锁来和另外一个事务等待的锁进行比较,如果检测到等值的锁则返回锁信息。

返回值:返回第一个锁或者NULL

死锁检测函数列表J lock_get_next_lock函数代码处理逻辑

作用:返回值,返回事务锁持有的下一个锁或者NULL

时间: 2024-10-09 20:01:43

谈谈MySQL死锁之二 死锁检测和处理源码分析的相关文章

(二)最简单的模块源码分析

一.常用的模块操作命令(1)lsmod(list module,将模块列表显示),功能是打印出当前内核中已经安装的模块列表 (2)insmod(install module,安装模块),功能是向当前内核中去安装一个模块,用法是insmod xxx.ko(3)modinfo(module information,模块信息),功能是打印出一个内核模块的自带信息.,用法是modinfo xxx.ko(4)rmmod(remove module,卸载模块),功能是从当前内核中卸载一个已经安装了的模块,用

equals和==方法比较(二)--Long中equals源码分析

equals方法是Object类中的方法,java中所有的对象均继承自Object类,也就继承了equals方法,下面是Object类中equals方法的实现, public boolean equals(Object obj) { return (this == obj); } 可以看到,equals方法使用的就是==的比较方式,那么如果是两个引用类型,比较的当然是两个引用地址. java又规定所有继承自Object的类都可以重写equals方法,即实现自己的比较逻辑,但Long这个包装类(其

Solr4.8.0源码分析(19)之缓存机制(二)

Solr4.8.0源码分析(19)之缓存机制(二) 前文<Solr4.8.0源码分析(18)之缓存机制(一)>介绍了Solr缓存的生命周期,重点介绍了Solr缓存的warn过程.本节将更深入的来介绍下Solr的四种缓存类型,以及两种SolrCache接口实现类. 1.SolrCache接口实现类 前文已经提到SolrCache有两种接口实现类:solr.search.LRUCache 和 solr.search.LRUCache. 那么两者具体有啥区别呢? 1.1 solr.search.LR

谈谈MySQL死锁 一

数据越来越和我们的生活离不开,数据在生命周期的各个阶段有着不同的痛点和需求以及特殊场景. CURD是数据的四大基本需求:写入,更新,读取,删除. 今天,来谈一谈死锁问题 死锁是高并发下MySQL不可回避的一个问题. 这句话可以引申四个问题: 1.什么是死锁? 2.MySQL什么时候会检测死锁? 3.数据库系统如何处理死锁? 4.有哪些典型的高并发死锁场景? 1.我们先来看看什么是死锁. 在<数据库系统实现>第八章第二节这样定义死锁 并发执行的事务由于竞争资源而到达一个存在死锁的状态:若干事务的

MySQL Innodb表导致死锁日志情况分析与归纳

发现当备份表格的sql语句与删除该表部分数据的sql语句同时运行时,mysql会检测出死锁,并打印出日志 案例描述在定时脚本运行过程中,发现当备份表格的sql语句与删除该表部分数据的sql语句同时运行时,mysql会检测出死锁,并打印出日志.两个sql语句如下:(1)insert into backup_table select * from source_table(2)DELETE FROM source_table WHERE Id>5 AND titleWeight<32768 AND

Atitit.线程 死锁 跑飞 的检测与自动解除 与手动解除死锁 java c# .net php javascript.

Atitit.线程 死锁 跑飞 的检测与自动解除 与手动解除死锁 java c# .net php javascript. 1. 现象::主程序卡住无反应,多行任务不往下执行 1 2. 原因::使用jv jprofile查看线程,原来俩个线程死锁了.. 1 3. Java的缺点,默认不能自动解除死锁 1 4. 自动检测与解除死锁::使用看门狗watchdog 2 4.1. 死锁检测算法(太麻烦,不推荐) 2 4.2. 硬件看门狗 2 4.3. 软件看门狗的实现--TIMER 2 4.4. LIN

死锁的产生与检测

产生死锁 在操作系统中,我们可能接触过两个进程争抢资源,互不相让,然后产生了死锁,这时候,我们可以用银行家算法来分配资源.下面,我们先模拟产生死锁: #region 试图产生死锁的代码 // static void T1(Program p) //{ // //主线程占有了mainRes并试图访问workerRes; // lock (p.mainRes) // { // Thread.Sleep(10);// // lock (p.workerRes) //死锁 // { // Console

阻塞与死锁(二)——各种操作对锁的申请

原文:阻塞与死锁(二)--各种操作对锁的申请 如何监视锁的申请.持有和释放: 在着手分析.处理阻塞.死锁之前,首先要进行"监控"和"信息收集" 1.检查一个连接当前所持有的锁: 可以使用sp_lock来查看所有连接持有的锁的内容. 在2005以后引入的DMV,还能用过sys.dm_tran_locks来查看: SELECT request_session_id, resource_type , resource_associated_entity_id , requ

死锁案例二

1.环境说明 MySQL5.6.33,隔离级别是RR.表结构及数据: Create table t1(id int not null primary key auto_increment,c1 int,c2 int,c3 int, unique key(c1),unique key(c2)); insert into t1(c1,c2,c3) values(1,3,4),(6,6,10),(9,9,14); 2.测试用例 session1 session2 session3 begin; beg