mysql中的锁机制详解(MYSQL锁机制)

前言

本文讲述mysql锁定义,lock与latch区别,Innodb中的锁,强制开启S/X锁,自增长锁,行锁的3中算法,锁升级等,主要参照来自《MYSQL技术内幕 第2版》这本书,以及参杂了自己的一些理解。

锁定义/作用

为支持对 共享资源 的并发访问,保证数据的 一致性 与 完整性 ,数据库所提供的一种 约束机制 。不同的数据库和不同的引擎有着不同实现方式及支持度,可分为行,页,表锁。(MyISAM是表锁,SQL SERVER是行级锁,InnoDB默认也是行级锁)

mysql中的锁机制详解(MYSQL锁机制)(1)

前三个都是MYSQL的不同引擎。

lock与latch(门闩shuan)

latch适用于短期锁定的 轻量级锁 (门闩不防盗嘛),锁定时间过长时,性能会非常差。

lock的对象是事务,锁定的是数据库中的对象:行、页、表,锁在commit或rollback时才会释放。

latch分为mutex(互斥锁)和rwlock(读写锁),用于保证 并发线程 操作临界资源(可以理解为共享资源)的正确性。

latch是面向数据库系统底层的,目前没找供用户开发的api,除非DBA,普通开发者基本用不到,了解即可。

mysql中的锁机制详解(MYSQL锁机制)(2)

mysql innodb中: 查看latch命令: `show engine innodb latch` 查看lock命令: `show engine innodb status`

Innodb引擎中的锁

innodb支持行锁和表锁(不支持表锁),默认为行锁。

两种行级锁:

  1. 共享锁(S lock):允许事务读1行
  2. 排他锁(X lock):允许事务删除或更新1行

在A获得S锁后,B可获S锁,但不能加X,否则A会阻塞。(读不影响数据)

在A获得X锁后,B不能再获得任何锁。(修改必须独占)

S锁可以理解为读锁,X锁可以理解为独占锁,且X优先级高于S。

Innodb支持多粒度锁定,允许行级、表级上的锁同时存在。(Innodb不支持页级锁)为此推出一种新的锁方式 意向锁 (Intention Lock):将锁定的对象分为多个层次,以满足事务在更细的细粒度上加锁。

一句话概括就是,对上层对象(页,表)加同样的意向锁(IS/IX)。同样的意思就是记录加S,上层对象就加IS;同理,记录加X,上层对象就加IX。

mysql中的锁机制详解(MYSQL锁机制)(3)

所有兼容情况:(兼容就是能获取,不兼容就是要等待阻塞)

很明显,是对称矩阵哦

mysql中的锁机制详解(MYSQL锁机制)(4)

一致性非锁定读

一致性非锁定读(consistent nolocking read):指的是在读取被加X锁的行时,不需要等待行锁的释放,会去读它的快照(snapshot)。

mysql中的锁机制详解(MYSQL锁机制)(5)

一个行有多个快照数据,究竟读哪一个呢?

READ COMMITED是读最新的,READ REPEATEABLE(Innodb默认隔离级别)是读的是 自己 事务begin前的。(这里的场景是开启两个事务,一个查,一个改,有先后。)READ COMMITD会破坏隔离性(Isolation)

一致性锁定读--强制开启锁

虽然可重复读(默认隔离级别)保证了隔离性,但为了确保数据的一致性,我们可以显式 强制加锁 :

  • SELECT ... IN SHARE MODE
  • SELECT ... FOR UPDATE

上面的 in share mode 是加的S锁。 for update 是加的X锁。

自增长锁

对字段设置auto_incrment时,自增计算器会保存在表中,锁会在insert语句之后,事务commit之前释放。(特殊的机制,为提高插入性能,没有选择事务结束再释放,而是Insert后)。后面MYSQL还新增了 innodb_autoinc_mode 来进一步控制自增长。

注:Innodb下自增列必须是索引,而且是索引的第一列(组合索引情况下),否则抛出异常。MyISAM没有这要求。

行锁的3种算法

  • Record Lock :记录锁,锁定自己的记录
  • Gap Lock:沟锁,锁自己附近的范围,不包括自己记录(开区间)
  • Next-key Lock :范围 自己,Record Gap结合(闭区间)

Record Lock是锁住 索引记录 ,主键也是索引之一。

Next-key是 行查询 select默认采用的锁算法 ,如有索引:10,13,20。则锁区间为:(-∞,10],(10,13],(13,20],(20, ∞)。

显知,gap的话就包含自己,]变成了)。

next-key这里的next指的就是右区间为闭区间,推理:previous-key指的是左区间闭合。

注:自动降级:若索引中含有唯一属性(**唯一**索引),则next-key会自动降级为record-key。(范围锁——>只锁自己)

next-key机制的发明是为了解决 Phantom problem (幻像问题),是的mysql可以不到serializable就可以解决幻读。

幻像:一个事务A在未提交时,两次sql的执行的结果的 数据条数 不一样,B向其中修改的数据被A在第二次读走了。违背了隔离性。

脏读:A读到了B中 未提交 的数据,若B之后回滚了,则读到了脏数据。

不可重复读:B对A读到的值进行了修改,A第二次读到的 数据值 变了。

锁升级(lock escalation)

定义:锁的粒度降低。如:行锁——>页锁——>表锁

作用: 锁是稀有资源,升级是为了提高效率,防止系统使用太多内存来维护锁。

Innodb存储引擎不存在锁升级。因为它不是根据记录来产生行锁,而是根据事务访问的每个页来管理锁,采用 位图 方式。锁住一个页的一条与锁住多条的开销一样。

这里的`页来管理锁`和上面`innodb不支持页锁`有点绕,我也没理解,我后面去查证一下。

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页