专栏首页携程技术干货 | MySQL锁之源码探索

干货 | MySQL锁之源码探索

作者简介

姜宇祥,2012年加入携程,10年数据库核心代码开发经验,相关开发涉及达梦,MySQL数据库。现致力于携程MySQL的底层研发,为特殊问题定位和处理提供技术支持。

锁是计算机程序运行时协调并发访问同一数据资源的机制。对于数据库系统来说,数据是一种供许多用户共享的资源,那么如何保证数据并发访问的一致性、有效性是必须解决的一个问题。所以,锁对于数据库来说,是非常重要的一个功能。通过各种锁,实现了数据库事务中的隔离性。本篇文章将从源码层面介绍MySQL的元数据锁和InnoDB的实现。

一、MySQL的架构与锁

MySQL在架构上分为两层,服务和存储引擎层。服务层集中了网络通讯、语法分析和计划生成等通用功能;存储引擎层主要负责数据的存储。元数据的并发管理集中在服务层,数据的并发管理在存储引擎层。因此对于元数据的锁在服务层进行实现,数据的隔离特性在存储引擎层实现。本篇将介绍服务层的元数据锁的实现,以及现下使用率最高的具有ACID特性的InooDB的数据锁。

二、元数据锁

2.1 元数据锁类型

元数据类型

说明

GLOBAL

全局锁

TABLESPACE

表空间锁

SCHEMA

数据库锁

TABLE

表锁

FUNCTION

函数锁

PROCEDURE

存储过程锁

TRIGGER

触发器锁

EVENT

事件锁

COMMIT

事务锁,在服务器层进行提交事务时进行上锁

USER_LEVEL_LOCK

用户锁,通过GET_LOCK/RELEASE_LOCK进行获取和释放

LOCKING_SERVICE

安装locking_service.so插件后使用,为用户提供所服务

2.2 元数据锁申请与释放

在申请元数据锁的同时,会指定锁释放的时间。在程序执行到指定位置时,如语句执行结束或者事务执行结束,会检查元数据锁的上锁情况,并释放那些需要在该位置释放的元数据锁。

释放类型

说明

MDL_STATEMENT

语句执行结束时释放

MDL_TRANSACTION

事务结束时释放

MDL_EXPLICIT

显式释放

抽象元数据锁的上锁和释放的过程,整理为如下流程图

2.3 元数据锁关系

MySQL的元数据也是有从属关系的。有些元数据进行上锁的同时,需要配合其他元数据锁,这里称这种关系为从属关系。这种从属关系如下图所示,其箭头所指方向为元数据锁所依赖关系。比如在为SCHEMA元数据加锁时,需要GLOBAL元数据锁。

2.4 元数据锁级别

由于对元数据的访问存在不同的需求,因此设置不同级别锁级别,用于对元数据及数据的访问控制。

级别

说明

MDL_INTENTION_EXCLUSIVE(IX)

意向排它锁,可升级为排它锁。可与其他连接的意向排它锁兼容,但不兼容于共享锁。

MDL_SHARED(S)

共享锁

MDL_SHARED_HIGH_PRIO(SH)

高优先级共享锁。

MDL_SHARED_READ(SR)

共享读锁,对表数据存在意向读

MDL_SHARED_WRITE(SW)

共享写锁,对表数据存在意向写

MDL_SHARED_WRITE_LOW_PRIO

低优先级共享写锁

MDL_SHARED_UPGRADABLE(SU)

可升级共享锁

MDL_SHARED_READ_ONLY(SRO)

共享只读锁,该锁将阻塞对表的元信息和数据的更新

MDL_SHARED_NO_WRITE(SNW)

可升级的表锁,该锁将阻塞对表数据的更新,但允许进行表数据的读取

MDL_SHARED_NO_READ_WRITE(SNRW)

可升级的表锁,该锁将阻塞对表数据的读和更新。

MDL_EXCLUSIVE(X)

排它锁

2.5 元数据锁源码

该部分介绍MySQL源码的主要源文件和主要函数。其中源文件以mdl.h/mdl.cc为核心,定义了元数据锁的主要数据结构和函数,lock.cc/sql_db.cc等源文件使用元数据锁所定义的数据结构和函数。

主要源文件及其关系如下,蓝框内所列源文件依赖于红框内的源文件所定义的内容。

主要函数如下图关系所列

三、InnoDB锁

3.1 事务隔离级简介

存储引擎InnoDB实现事务的四个隔离级,也就是读未提交和读提交等四个事务隔离级。所谓事务隔离级,是并发访问中控制数据读写的方式。在这里先简单介绍这四个事务隔离级的来龙去脉,以便于理解MySQL的锁机制。

InnoDB事务采用不同的锁机制,会产生不同的现象。

现象

说明

脏读

此时事务忽略其他事务的任何锁,因此可以读取其他事务未提交的修改数据,当其他事务回滚数据时所读取的数据为错误数据。

不可重复读

在同一事务中,对同一行读取不同的值。此时读取数据时未对数据进行读取保护,故其他事务可修改该事务。

幻读

在同一事务中,使用相同的过滤条件,获取不同结果集。此时事务读取数据时,未对查询数据进行范围保护。

事务隔离级和各种现象的关系,“X”表示在该事务隔离级下现象可发生,“--”表示在该事务隔离级下现象不会发生。

事务隔离级

脏读

不可重复读

幻读

读未提交

X

X

X

读提交

--

X

X

可重复读

--

--

X

串行化

--

--

--

3.2 InnoDB的锁类型

InnoDB为保护并发访问下的数据,根据不同的粒度对数据进行。

锁类型

说明

表锁

全表上锁,此锁对表中所有数据进行保护

行锁

单行数据进行保护

间隙锁

和行锁结合,对行数据进行范围上锁,对该范围数据进行保护

3.3 InnoDB的锁级别

InnoDB的锁

锁级别

说明

意向共享锁(IS)

用于对表锁,不能用于行锁

意向排它锁(IX)

用于对表锁,不能用于行锁

共享锁(S)

主要用于行锁,只有在“lock tables for read”时用于表锁

排它锁(X)

主要用于行锁,只有在“lock tables for write”时用于表锁

自增锁(AI)

表级锁,用于语句级的MySQL binlog

各个级别锁之间存在兼容性问题,如下表格列出各个级别锁之间的兼容性。“X”表示不兼容,“O”表示兼容。

IS

IX

S

X

AI

IS

O

O

O

X

O

IX

O

O

X

X

O

S

O

X

O

X

X

X

X

X

X

X

X

AI

O

O

X

X

X

3.4 间隙锁

InnoDB间隙锁(next-key lock)的用处是在repeatable read的隔离级下防止幻读现象的出现,所以一定要记住,在其他隔离级下是不会出现间隙锁的。间隙锁的原理是在通过对行锁进行特殊标识(此时的行锁就被称为间隙锁),指出在该范围内行记录的左开右闭区间被封锁,不可进行更新操作。正是采用这种针对行记录之间间隙上锁方式,所以称为间隙锁或者next-key锁。

如下图所示,假设索引中的key值为5、17、23和29。当执行如下SQL:begin; select * from t4 where id2=16 forupdate;会对key:17创建一个行锁,并标识该行锁为间隙锁,其锁定区间为红框内6到17,也就是这个区间的值域发生了变化,如果再发生变化可能会影响该区域的数据行集合,所以需要锁定该区域为不可更新。

3.5 源码结构

核心代码包含了有关锁的宏定义和函数定义等锁的类型定义和操作定义,应用代码为使用这些宏和函数的模块。

本文分享自微信公众号 - 携程技术中心(ctriptech),作者:姜宇祥

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-03-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 干货 | 数据分析在携程产品设计中的应用

    林传毅,携程旅行网资深交互设计,负责酒店产品和客栈通(www.kztpms.com)的整体设计。先后毕业于复旦大学计算机系和香港大学商学院,曾就职解放日报和柯达...

    携程技术
  • 干货 | 携程新风控数据平台建设

    作者简介 刘丹青,携程信息安全部高级开发工程师。2014年加入携程,主要负责验证码、风控数据平台的开发设计工作,提供性能测试与性能优化的相关支持。 前言 近几...

    携程技术
  • 干货 | 携程酒店浏览客户流失概率预测

    作者简介 陈无忌,就读于中国科学技术大学计算机学院,15 级硕士研究生。研究方向机器学习、大数据、智能交通等。在校期间多次参加大数据竞赛,在携程云海平台比赛中,...

    携程技术
  • MySQL的可重复读级别能解决幻读吗

    之前在深入了解数据库理论的时候,了解到事物的不同隔离级别可能存在的问题。为了更好的理解所以在MySQL数据库中测试复现这些问题。关于脏读和不可重复读在相应的隔离...

    本人秃顶程序员
  • 大数据24小时 | 李彦宏“画饼”互惠金融,数据新闻第一人黄志敏离职转型抢滩大数据

    <数据猿导读> SAP推出最新数据仓库应用,帮助企业实现实时数字化运营;“麦谷科技”获同创伟业领投5000万元融资;财新传媒首席技术官黄志敏宣布离职……以下为您...

    数据猿
  • 微信小程序开发技巧总结 (一)

    结合自己在平时的开发中遇到的各种问题,和浏览各种问题的解决方案总结出一些自己在日常开发中常用的技巧和知点,希望各位不吝斧正。

    Kindear
  • 【Java面试总结】MySQL

    字符集指的是一种从二进制编码到某类字符符号的映射。校对规则则是指某种字符集下的排序个规则。

    silentcow
  • flask 扩展开发(flask 113)

    Flask,一个微框架,通常需要一些重复的步骤来让第三方库工作。因为在很多时候, 这些步骤可以被分离出,来支持多个项目,就有了 Flask Extension ...

    用户5760343
  • 关联分析(4):购物篮数据转换R语言

    我们现在有这样一份数据,记录了近173万用户的爱好情况(数据为随机生成)。数据中每行为一个用户,每列为一个爱好属性,“y”代表有此爱好,“n”代表无此爱好,我们...

    三猫
  • 重磅!2019大数据白皮书发布(附PPT解读)

    中国信通院发布了《大数据白皮书(2019)》(以下简称“白皮书”),这是中国信通院第四次发布大数据白皮书。白皮书在前三版的基础上,聚焦一年多来大数据各领域的发展...

    钱塘数据

扫码关注云+社区

领取腾讯云代金券