1、什么是锁

锁机制用于管理对共享资源的并发访问。

lock与latch

latch一般称为闩锁(轻量级的锁),因为其要求锁定的时间必须非常短。若持续的时间长,则应用的性能会非常差。在InnoDB存储引擎中,latch又可以分为mutex(互斥量)和rwlock(读写锁)。其目的是用来保证并发线程操作临界资源的正确性,并且通常没有死锁检测的机制。

lock的对象是事务,用来锁定的是数据库中的对象,如表、页、行。并且一般lock的对象仅在事务commit或rollback后进行释放。不同事务隔离级别释放的时间可能不同,所以分析lock问题,要先看事务隔离级别(select @@tx_isolation;)。

2、MyISAM存储引擎中的锁

MyISAM存储引擎只支持表锁。

MyISAM存储引擎的读锁和写锁是互斥的,读写操作是串行的。

但它认为写锁的优先级比读锁高,所以即使读请求先到锁等待队列,写请求后到,写锁也会插到读锁请求之前!

这也正是MyISAM表不太适合于有大量更新操作和查询操作应用的原因,因为,大量的更新操作会造成查询操作很难获得读锁,从而可能永远阻塞。

可以通过一些设置来调节MyISAM的调度行为。

3、InnoDB存储引擎中的锁

3.1 锁的类型

InnoDB存储引擎实现了如下两种标准的行级锁:

共享锁(S Lock),允许事务读一行数据。

排他锁(X Lock),允许事务删除或更新一行数据。

X锁与任何的锁都不兼容,而S锁仅和S锁兼容,S和X锁都是行锁,兼容是指对同一记录(row)锁的兼容性情况。

意向锁设计目的主要是为了在一个事务中揭示下一行将被请求的锁类型。

如果需要对页上的记录r进行上X锁,那么分别需要对数据库A、表、页上意向锁IX,最后对记录r上X锁。若其中任何一个部分导致等待,那么该操作需要等待粗粒度锁的完成。

两种意向锁:

意向共享锁(IS Lock),事务想要获得一张表中某几行的共享锁

意向排他锁(IX Lock),事务想要获得一张表中某几行的排他锁

意向锁其实不会阻塞除全表扫以外的任何请求。

锁的兼容性情况

type

IS

IX

S

X

IS

兼容

兼容

兼容

不兼容

IX

兼容

兼容

不兼容

不兼容

S

兼容

不兼容

兼容

不兼容

X

不兼容

不兼容

不兼容

不兼容

如果一个事务请求的锁模式与当前的锁兼容,InnoDB 就将请求的锁授予该事务;反之,如果两者不兼容,该事务就要等等锁释放。

3.2 一致性非锁定读

一致性的非锁定读(consistent nonlocking read)是指InnoDB存储引擎通过行多版本控制(multi versioning)的方式来读取当前执行时间数据库中行的数据。如果读取的行正在执行DELETE或UPDATE操作,这时读取操作不会因此去等待行上锁的释放。相反地,InnoDB存储引擎会去读取行的一个快照数据。

InnoDB存储引擎的默认设置下,这是默认的读取方式,即读取不会占用和等待表上的锁。

在不同事务隔离级别下,读取的方式不同,并不是在每个事务隔离级别下都是采用非锁定的一致性读。此外,即使都是使用非锁定的一致性读,但是对于快照数据的定义也各不相同。

3.3 一致性锁定读

InnoDB存储引擎对于SELECT语句支持两种一致性的锁定读(locking read)操作:

SELECT…FOR UPDATE

SELECT…LOCK IN SHARE MODE

3.4 自增长与锁

AUTO-INC Locking,这种锁其实是采用一种特殊的表锁机制,为了提高插入的性能,锁不是在一个事务完成后才释放,而是在完成对自增长值插入的SQL语句后立即释放。

3.5 外键和锁

在InnoDB存储引擎中,对于一个外键列,如果没有显式地对这个列加索引,InnoDB存储引擎自动对其加一个索引,因为这样可以避免表锁。

4、锁的算法

4.1 InnoDB存储引擎有3种行锁的算法

Record Lock:单个行记录上的锁

Gap Lock:间隙锁,锁定一个范围,但不包含记录本身,是一个左开右闭的空间。如索引值有1,3,5,8,GAP的区间:(-∞,1],(1,3],(3,5],(5,8],(8,+∞)。GAP Lock的目的,是为了防止同一事务的两次当前读,出现幻读的情况。

Next-Key Lock∶Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身。对于行的查询,都是采用该方法,主要目的是解决幻读的问题。

4.2 解决Phantom Problem(幻像问题)

在默认的事务隔离级别下,即REPEATABLE READ下,InnoDB存储引擎采用Next-Key Locking机制来避免Phantom Problem(幻像问题)。

Phantom Problem是指在同一事务下,连续执行两次同样的SQL语句可能导致不同的结果,第二次的SQL语句可能会返回之前不存在的行。

InnoDB存储引擎默认的事务隔离级别是REPEATABLE READ,在该隔离级别下,其采用Next-Key Locking的方式来加锁。而在事务隔离级别READ COMMITTED下,其仅采用Record Lock。

5、锁的问题

5.1 幻读

在同一个事务中,同一个查询多次返回的结果不一致。事务A新增了一条记录,事务B在事务A提交前后各执行了一次查询操作,发现后一次比前一次多了一条记录。幻读是由于并发事务增加记录导致的,这个不能像不可重复读通过记录加锁解决,因为对于新增的记录根本无法加锁。需要将事务串行化,才能避免幻读。

5.2 脏读

脏数据是指事务对缓冲池中行记录的修改,并且还没有被提交(commit)。

脏读发生的条件是需要事务的隔离级别为READ UNCOMMITTED。

违反了事务的隔离性。

脏读隔离看似毫无用处,但在一些比较特殊的情况下还是可以将事务的隔离级别设置为READ UNCOMMITTED。例如replication环境中的slave节点,并且在该slave上的查询并不需要特别精确的返回值。

5.3 不可重复读

在一个事务内两次读到的数据是不一样的情况,这种情况称为不可重复读。

不可重复读和脏读的区别是:脏读是读到未提交的数据,而不可重复读读到的却是已经提交的数据,但是其违反了数据库事务一致性的要求。

InnoDB存储引擎的默认事务隔离级别是READ REPEATABLE,采用Next-Key Lock算法,避免了不可重复读的现象。

5.4 丢失更新

一个事务的更新操作会被另一个事务的更新操作所覆盖,从而导致数据的不一致。

要避免丢失更新发生,需要让事务在这种情况下的操作变成串行化,而不是并行的操作。

6、死锁

死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象。除了超时机制,当前数据库还都普遍采用wait-for graph(等待图)的方式来进行死锁检测。

MyISAM总是一次获得SQL语句所需要的全部锁。这也正是MyISAM表不会出现死锁(Deadlock Free)的原因。

产生死锁的必要条件

多个并发事务

每个事务都持有锁

每个事务都需要再持有锁

事务之间产生加锁的循环等待,形成死锁

死锁检测

1.InnoDB的初始化一个事务,当事务尝试申请加一个锁,并且需要等待时(wait_lock),innodb会开始进行死锁检测(deadlock_mark)

2.进入到lock_deadlock_check_and_resolve()函数进行检测死锁和解决死锁。

3.检测死锁过程中,是有计数器来进行限制的,在等待wait-for graph 检测过程中遇到超时或者超过阈值,则停止检测。

4.死锁检测的逻辑之一是等待图的处理过程,如果通过锁的信息和事务等待链构造出一个图,如果图中出现回路,就认为发生了死锁。

5.死锁的回滚,内部代码的处理逻辑之一是比较undo的数量,回滚undo数量少的事务。

死锁日志

update `xxx` set xxx where xxx = xxx

RECORD LOCKS space id 123 page no 13726 n bits 248 index idx_xxx of table `xxx` trx id 123456 lock_mode X locks rec but not gap

Record lock, heap no 123 PHYSICAL RECORD: n_fields 13; compact format; info bits 0

update `xxx` set xxx where xxx = xxx

RECORD LOCKS space id 123 page no 123456 n bits 128 index PRIMARY of table `xxx` trx id 123456 lock_mode X locks rec but not gap

Record lock, heap no 456 PHYSICAL RECORD: n_fields 10; compact format; info bits 0

上面的日志,精简了很多日志,只保留了部分重要信息,从死锁日志中,可以看出,执行哪条SQL,哪个页,哪个索引,锁的模式、锁的属性。

锁的属性

LOCK_REC_NOT_GAP (锁记录)

LOCK_GAP (锁记录前的GAP)

LOCK_ORDINARY (同时锁记录+记录前的GAP 。传说中的Next Key锁)

LOCK_INSERT_INTENTION(插入意向锁,其实是特殊的GAP锁)

死锁案例分析,最简单的、最经典的死锁案例,加锁顺序不一致导致死锁。

session1:

begin;

select * from user where id = 3 for update;

select * from user where id = 5 for update;

commit;

session2:

begin;

select * from user where id = 5 for update;

select * from user where id = 3 for update;

commit;

参考资料

mysql外键读锁_MySQL的锁相关推荐

  1. mysql 外键约束_MySQL之外键约束(FOREIGN KEY)

    定义: MySQL外键约束(FOREIGN KEY)用来在两个表的数据之间建立链接,它可以是一列或者多列.一个表可以有一个或多个外键. 外键对应的是参照完整性,一个表的外键可以为空值,若不为空值,则每 ...

  2. mysql 外键查询_mysql 外键查询(mysql数据库多表联查)

    mysql 外键查询(mysql数据库多表联查) 2020-07-24 11:51:00 共10个回答 查看方式主要是通过第三方工具或者是sql语句,主要有以下三种方式1:使用Navicateform ...

  3. mysql外键教程_MySQL外键使用详解

    最近有开始做一个实验室管理系统,因为分了几个表进行存储·所以要维护表间的关联··研究了一下MySQL的外键 . (1)只有InnoDB类型的表才可以使用外键,mysql默认是MyISAM,这种类型不支 ...

  4. ef mysql 外键 一对一_MySQL 外键 一对一 一对多 多对多 复制

    #外键 ## 1,学习外键首先要明白表与表之间的关系 ​ 首先要换位思考 在考虑了这边 还要考虑另一边 ​ 然后在下定论### 判断表关系的语法 #### 图书与出版社 ​ 一本书可不可以有多个出版社 ...

  5. mysql外键查询_MySQL外键使用详解

    最近有开始做一个实验室管理系统,因为分了几个表进行存储·所以要维护表间的关联··研究了一下MySQL的外键. (1)只有InnoDB类型的表才可以使用外键,mysql默认是MyISAM,这种类型不支持 ...

  6. mysql 外键效率_MYSQL使用外键进行优化

    #转载请联系 假如你是京东的数据库管理员,你现在管理着这样一个数据库. mysql> select * fromgoods;+----+----------------------------- ...

  7. mysql 外键效率_MYSQL外键的使用以及优缺点

    主键和索引是不可少的,不仅可以优化数据检索速度,开发人员还省不其它的工作, 矛盾焦点:数据库设计是否需要外键.这里有两个问题:一个是如何保证数据库数据的完整性和一致性:二是第一条对性能的影响. 正方观 ...

  8. mysql 外键冲突_mysql添加外键错误是什么原因

    mysql添加外键错误的原因:1.外键的字段与关联字段的类型不匹配:2.外键名重复:3.外键没有建立索引:4.外键存在默认值:5.语法错误. 原因分析: 第一种情况:外键的字段与关联的字段的类型不匹配 ...

  9. mysql 外键关联_mysql外键关联

    主键:是唯一标识一条记录,不能有重复的,不允许为空,用来保证数据完整性 外键:是另一表的主键, 外键可以有重复的, 可以是空值,用来和其他表建立联系用的.所以说,如果谈到了外键,一定是至少涉及到两张表 ...

最新文章

  1. CV之SR:超分辨率(Super resolution)的简介、使用方法、案例应用之详细攻略
  2. vmware, failed to lock the file 的解决
  3. 一个串口接2个设备_重庆市有2个大观镇,一个乡村旅游发达,一个特产柚子
  4. RPC(远程过程调用)
  5. as工程放到源码编译_Flutter源码剖析(二):源码的阅读与调试环境配置
  6. bootstrap中轮播图、模态框、提示框/弹出框、滚动监听、弹性布局、响应式flex、多媒体对象
  7. AI5天训练-视觉生产技术探究和应用
  8. ORACLE1.13-综合例子应用01
  9. Django3Vue3前后端分离项目
  10. python笔记:datetime模块中的函数
  11. 实战MongoDB-Replication之Master-Slave
  12. property中的strong 、weak、copy 、assign 、retain 、unsafe_unretained 与autoreleasing区别和作用详解...
  13. 【Spring-tx】ProxyTransactionManagementConfiguration类
  14. 安装内存条后系统蓝屏怎么解决
  15. 平均数 中位数 四分位数 方差 标准差
  16. C#导出VCF格式电话本,遇到QUOTED-PRINTABLE编码的问题,附带QUOTED-PRINTABLE编码解码
  17. 两种特殊卷积:转置卷积和空洞卷积
  18. python面试题-如“上海 深圳 深圳 上海“,要求输入一个匹配模式,比如: aabb,判断是否符合
  19. 手机用计算机微信运动记步吗,微信运动怎么用?微信运动计步功能使用方法介绍...
  20. Qt学习总结之QTableWidget表格填充

热门文章

  1. php 全局变量能定义数组吗,php数组声明、遍历、数组全局变量使用小结
  2. win10系统下查看cpu是否启动虚拟化
  3. TensorFlow学习笔记02:TensorBoard可视化入门
  4. ES6学习笔记02:let 与 const
  5. 【BZOJ3289】Mato的文件管理,莫队+树状数组
  6. java的super是什么意思_java中Super到底是什么意思?必须举例说明!
  7. 2017.8.14 分手是祝愿 失败总结
  8. php数值相加_PHP+Redis 有序集合实现 24 小时排行榜实时更新
  9. sqlite3用python家外键_Django/Sqlite3为带有外键的模型添加一行
  10. MFC模态与非模态对话框的创建与销毁