Innodb锁系统 Insert/Delete 锁处理及死锁示例分析

本文详细分析了InnoDB存储引擎中Insert和Delete操作的锁处理,包括插入记录时的锁检查、锁继承、死锁示例及删除操作的锁机制。在插入操作中,InnoDB会进行锁判断,处理插入意向锁和冲突,并在死锁发生时进行处理。删除操作则是通过标记删除,由Purge线程完成实际删除,涉及锁的转移和检查。
摘要由CSDN通过智能技术生成

Innodb锁系统 Insert/Delete 锁处理及死锁示例分析

A.INSERT

插入操作在函数btr_cur_optimistic_insert->btr_cur_ins_lock_and_undo->lock_rec_insert_check_and_lock这里进行锁的判断,我们简单的看看这个函数的流程:

1.首先先看看欲插入记录之后的数据上有没有锁,

   next_rec = page_rec_get_next_const(rec);

   next_rec_heap_no = page_rec_get_heap_no(next_rec);

   lock = lock_rec_get_first(block, next_rec_heap_no);

如果lock为空的话,对于非聚集索引,还需要更新page上的最大事务ID。

实际上这里是比较松散的检查,大并发插入的时候,可以大大的降低创建锁开销。

那么其他事务如何发现这些新插入的记录呢(重复插入同一条记录显然应该被阻塞),这里会有个判断,其他事务去看看

新插入记录的事务是否还是活跃的,如果还是活跃的,那么就为这个事务主动增加一个锁记录(所谓的隐式锁就是么有锁。。。。),这个判断是在检查是否存在冲突键的时候进行的(row_ins_duplicate_error_in_clust->row_ins_set_shared_rec_lock->lock_clust_rec_read_check_and_lock->lock_rec_convert_impl_to_expl

row_ins_set_shared_rec_lock的目的是为了向记录上加一个LOCK_REC_NOT_GAP的LOCK_S锁,也就是非GAP的记录S锁,如果发现记录上有X锁(隐式锁转换为LOCK_REC | LOCK_X | LOCK_REC_NOT_GAP),显然是需要等待的(返回DB_LOCK_WAIT)

 

 

这里设置inherit为FALSE,然后返回DB_SUCCESS;

至于inherit的作用,稍后再议!

 

2.如果lock不为空,这意味着插入记录的下一个记录上存在锁,设置inherit为TRUE.

检查下一个记录上的锁是否和LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION相互冲突

    if (lock_rec_other_has_conflicting(

            LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,

            block, next_rec_heap_no, trx)) {

 

        /* Note that we may get DB_SUCCESS also here! */

        err = lock_rec_enqueue_waiting(LOCK_X | LOCK_GAP

                           | LOCK_INSERT_INTENTION,

                           block, next_rec_heap_no,

                           index, the);

 

如果有别的事务在下一个记录上存在显式的锁请求,并且和锁模式( LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION) 冲突,那么

这时候当前事务就需要等待。

 

如果别的事务持有一个GAP类型的锁以等待插入,我们认为这个锁和当前插入不冲突。

如何判定锁之间是否冲突,在上一篇博客(http://mysqllover.com/?p=425)已经介绍过,不再赘述.

 

当检查到存在冲突的事务,我们就将一个锁模式为LOCK_X | LOCK_GAP|LOCK_X | LOCK_GAP 加入到请求队列中(调用函数lock_rec_enqueue_waiting),这里也会负责去检查死锁。

 

注意在加入等待队列的时候可能会返回DB_SUCCESS,例如死锁发生,但选择另外一个事务为牺牲者。

 

我们上面提到变量inherit,在存在下一个记录锁时会设置为TRUE,在上层函数btr_cur_optimistic_insert,会据此进行判断:

    if (!(flags & BTR_NO_LOCKING_FLAG) && inherit) {

        lock_update_insert(block, *rec);

    }  

注意当我们执行到这部分逻辑时err为DB_SUCCESS,表示锁检查已经通过了。

BTR_NO_LOCKING_FLAG表示不做记录锁检查

对于optimistic_insert, flags值为0

对于pessimistic_insert,flags值为BTR_NO_UNDO_LOG_FLAG | BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值