表锁 

表锁相关结构:

table->locks:数据字典table保存这个表上的所有表锁信息

trx->lock.table_locks:每个事务trx保存该事务所加的所有表锁信息

trx->lock.trx_locks:每个事务trx保存该事务所有的锁信息(包括行锁)

表锁类型:

IS IX S X AI

AI:Auto-Increment Lock 也是表级的,语句结束后释放而不事事务结束后释放

http://dev.mysql.com/doc/refman/5.5/en/innodb-auto-increment-handling.html

lock_table 加锁流程

1 先从 trx->lock.table_locks 查找该事务是否已加对该表加锁,如果所加的锁比要加的锁strong,则返回成功。其它情况进入2

2  从 table->locks中查找该表是否被其他事务加锁。如果没有加锁进入3,如果已加锁进入4

3 新建表锁,返回加锁成功

4 此时需判断欲加的锁是否与已加的锁兼容。如果兼容进入5,否则进入6

5 新建表锁,返回加锁成功

6 新建表锁,加入等待队列,其中会穿插死锁检测流程。

新建表锁会将新建的锁放入table->locks,trx->lock.table_locks,trx->lock.trx_locks中。

附锁兼容矩阵和锁

/* LOCK COMPATIBILITY MATRIX
* IS IX S X AI
* IS + + + - +
* IX + + - - +
* S + - + - -
* X - - - - -
* AI + + - - -

锁强度比较矩阵

/* STRONGER-OR-EQUAL RELATION (mode1=row, mode2=column)

* IS IX S X AI
* IS + - - - -
* IX + + - - -
* S + - + - -
* X + + + + +
* AI - - - - +
* See lock_mode_stronger_or_eq().
*/

记录锁

记录锁的存储单位为页,一个事务在一个页上的所有同类型锁存储为一个lock,lock中通过bitmap来表示那些记录已加锁

行锁类型:行锁类型由基本类型和精确类型组成

行锁基本类型:

LOCK_S,LOCK_X

行锁精确类型:

LOCK_ORDINARY(NK):next-key lock 既锁记录也锁记录前的gap

LOCK_GAP(GAP):不锁记录,只锁记录前的gap

LOCK_REC_NOT_GAP(NG):只锁记录,不锁记录前的gap

LOCK_INSERT_INTENTION(I):insert时,若insert位置已有gap锁,则需加LOCK_INSERT_INTENTION锁

相关结构:

trx->lock.trx_locks:每个事务trx保存该事务所有的锁信息(表锁和行锁)

lock_sys->rec_hash:保存所有事务的行锁信息

给记录加S锁之前必会给表加IS锁

给记录加X锁之前必会给表加IX锁

lock_rec_lock流程

分为两个阶段快加锁和慢加锁阶段,设记录所在的页为p

1 快加锁阶段:

1.1 在 lock_sys->rec_hash中查找P的所有锁,如果没有锁,则新建锁返回成功;否则进入1.2

1.2 如果查找到只有一个锁,且该所在的事务是当前事务,锁类型也相同,则进入1.3,否则,进入第二阶段快加锁阶段

1.3 如将该记录已加锁,则返回加锁成功。否则进入1.4

1.4  将该记录在lock的bitmap的位置为已加锁。返回成功。

2 慢加锁阶段

2.1  在lock_sys->rec_hash中遍历查找当前事务对此记录所加的锁,如果已有锁比欲加的锁strong(见lock_rec_has_expl),则进入2.2,否则进入2.3。

2.2. 如果已有锁状态为wait,则当前事务进入等待。否则直接返回加锁成功。

2.3  在lock_sys->rec_hash中遍历查找对此记录所加的锁 ,如果所在的事务是其他事务且锁不兼容则进入等待,否则进入2.4

2.4 如是隐式加锁,则返回成功,否则进入2.5

2.5 如果当前记录已有锁等待(?),或当前事务没有同类型的锁设置bitmap位,则新建锁返回成功(见lock_rec_add_to_queue) ,否则进入2.6

2.6  在当前事务同类型的锁上设置bitmap位,返回成功

可见慢加锁阶段可能会两次遍历lock_sys->rec_hash的哈希桶。

行锁的兼容和锁比较没有表锁那么简单,是由于引入行锁精确类型导致的。

兼容性有以下原则

1 Gap type locks without LOCK_INSERT_INTENTION flag do not need to wait for anything. This is because different users can have conflicting lock types on gaps

2 Record lock (LOCK_ORDINARY or LOCK_REC_NOT_GAP does not need to wait for a gap type lock

3 Lock on gap does not need to wait for a LOCK_REC_NOT_GAP type lock

4 No lock request needs to wait for an insertintention lock to be removed.

可以推出以下锁兼容矩阵

GAP    I    NG   NK

GAP      +       +     +     +

I                     +

NG      +       +

NK      +       +

对于锁强度比较可以参考lock_rec_has_expl,对于SUPREMUM记录的处理比较特殊。

锁强度矩阵(strong or equ)

GAP    I    NG   NK

GAP                -     -

I                 -

NG       -        -

NK                -

而对于SUPREMUM记录NG和G是+。

关于 lock的bitmap,当记录发生移动和page发生分裂和合并时都需要维护bitmap信息,参见lock_rec_move lock_update_merge_right

死锁检测

死锁检测发生在锁等待时,参见lock_deadlock_check_and_resolve。表锁和记录锁的检测逻辑是一样的。

采用等待图法,事务是图的节点,事务与该事务所等待的锁所在的事务的连线构成线,如果发现图中存在回路,则表示系统中出现了死锁。innodb采用图的深度优先的非递归算法实现的。非递归采用栈来记录节点的访问轨迹。lock->trx->lock.deadlock_mark和 ctx->mark_start来判断节点是否已访问过。

死锁检测有三种结果:

1 检查过程中搜索节点过深(>200)或访问的节点数过多(>1000000),或栈节点数超过srv_max_n_threads(?),则停止搜索,实际上就是认为产生了死锁。而不是采用超时的方法。此时将欲加的锁的事务做为牺牲者。

2 检测到死锁,这是需要选择牺牲者。在当前事务和等待的锁事务中选择,原则是牺牲undo和持有锁较少的事务。(trx_weight_ge)

作为牺牲者的事务会回滚,从而释放锁持有的锁,从而断开了环路,解决了死锁。

锁的释放

事务提交和回滚是会释放锁

另为自增锁在语句结束时释放lock_unlock_table_autoinc

innodb 表锁和行锁的更多相关文章

  1. mysql的innodb 引擎 表锁与行锁

    innodb 引擎 行锁与表锁 行锁与表锁是基于索引来说的(且索引要生效) 不带索引 (表锁)要全表扫描 1. 执行select @@autocommit; 查看结果 0是不自动提交事务,1是自动提交 ...

  2. 三分钟入门 InnoDB 存储引擎中的表锁和行锁

    各位对 "锁" 这个概念应该都不是很陌生吧,Java 语言中就提供了两种锁:内置的 synchronized 锁和 Lock 接口,使用锁的目的就是管理对共享资源的并发访问,保证数 ...

  3. MySQL中的锁(表锁、行锁)

    锁是计算机协调多个进程或纯线程并发访问某一资源的机制.在数据库中,除传统的计算资源(CPU.RAM.I/O)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所在有数 ...

  4. Mysql表锁、行锁、页锁

    参考 http://www.jb51.net/article/50047.htm <MySQL行级锁.表级锁.页级锁详细介绍> 页级:引擎 BDB.表级:引擎 MyISAM , 理解为锁住 ...

  5. [转]MySQL 表锁和行锁机制

    本文转自:http://www.cnblogs.com/itdragon/p/8194622.html MySQL 表锁和行锁机制 行锁变表锁,是福还是坑?如果你不清楚MySQL加锁的原理,你会被它整 ...

  6. MySQL表锁和行锁

    锁粒度 MySQL 不同的存储引擎支持不同的锁机制,所有的存储引擎都以自己的方式显现了锁机制,服务器层完全不了解存储引擎中的锁实现: InnoDB 存储引擎既支持行级锁(row-level locki ...

  7. MySql中的锁(表锁,行锁)

    锁是计算机协调多个进程或春线程并发访问某一资源的机制.在数据库中,除传统的计算资源(CPU,RAM,I/O)的争用之外,数据也是一种工许多用户共享的资源.如何保证数据并发访问的一致性,有效性是所有数据 ...

  8. MySQL的中的全局锁、表级锁、行锁

    MySQL的中的全局锁.表级锁.行锁 学习极客时间-林晓彬老师-MySQL实战45讲 学习整理 全局锁 对整个数据库实例加锁.通过使用Flush tables with read lock (FTWR ...

  9. 悲观锁,乐观锁,排他锁,行锁----MYSQL

    在说具体的锁结构时,先思考一个问题,那就是为什么要上锁?然后我要如何选择锁?锁具体如何实现? 在文章得末尾我给出了我的个人答案. 一.什么是悲观锁? 1.悲观锁就是在操作数据时,认为此操作会出现数据冲 ...

随机推荐

  1. 【转】深入理解Java中的final关键字

    Java 中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了 什么?使用final的好处是什么?最后也有一 ...

  2. 08 - JavaSE之IO流

    IO流 JAVA流式输入输出原理:可以想象成一根管道怼到文件上,另一端是我们程序,然后流的输入输出都是按照程序本身作为第一人称说明的.比如 input,对于我们程序来说就是有数据输入我们程序,outp ...

  3. HTML5知识汇总,总有你不知道的o(≧v≦)o~~

    html5知识点汇总 一.html5发展历程以及规划 html5从2006年开始立项,用于替代1999年的html4,历经12年,完成了第一个版本html5.0,并于2014年底发布. 在接下来的日子 ...

  4. 揭开Future的神秘面纱——任务执行

    前言 此文承接之前的博文 解开Future的神秘面纱之取消任务 补充一些任务执行的一些细节,并从全局介绍程序的运行情况. 系列目录 揭开Future的神秘面纱——任务取消 揭开Future的神秘面纱— ...

  5. Elasticsearch java客户端调用cat服务

    开发环境,测试环境,预发环境和生产环境一般相互隔离的,使用开发环境或者测试环境可以使用cat来查看索引的情况 例如: 但预防环境和测试环境是不允许访问的,那怎么办呢? 可以使用后台来查看上述信息,提供 ...

  6. VGG 论文研读

    VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNITION 论文地址 摘要 研究主要贡献是通过非常小的3x3卷积核的神经网络架 ...

  7. 使用Akka构建集群(二)

    前言 在<使用Akka构建集群(一)>一文中通过简单集群监听器的例子演示了如何使用Akka搭建一个简单的集群,但是这个例子“也许”离我们的实际业务场景太远,你基本不太可能去做这样的工作,除 ...

  8. C# WebApi 中设置Session可用

    在Global.acax中,添加下面方法 //设置session可用 public override void Init() { PostAuthenticateRequest += MvcAppli ...

  9. [PHP] 排序和查找算法

    知乎:冒泡排序(bubble sort)的原理是什么? 潘屹峰: 冒泡排序的原理可以顾名思义:把每个数据看成一个气泡,按初始顺序自底向上依次对两两气泡进行比较,对上重下轻的气泡交换顺序(这里用气泡轻. ...

  10. MySQL的安装与维护

    一.数据库的基本概念 数据库: 以一定方式储存在一起.能为多个用户共享.具有尽可能小的冗余度的特点.是与应用程序彼此独立的数据集合. DBMS(DataBase Management System,数 ...