专栏首页呆呆熊的技术路关于数据库锁的那些事

关于数据库锁的那些事

锁对于传统数据库来说是非常重要的, 里面也掺杂各种权衡, 概念类较多, 本文只针对部分内容做了讲解.

1. 从影响的数据范围看数据库锁

行锁

单独给一行数据记录加锁, mysql 中 我们常用的 InnoDB 引擎支持行锁.

优势: 是常见关系型数据库中锁粒度最小的一种锁, 能够有效的提高并发操作.

劣势: 消耗更多资源, 用法不规范容易产生死锁

表锁

顾名思义, 对当前操作的整张表加锁,是目前 mysql 锁粒度最大的一种

最常见的 myisam 引擎只支持表锁.

InnoDB 引擎 sql 使用不当(如非主键、索引条件)会退化为表锁.

优势: 并发读没问题, 消耗资源少, 加减锁速度快, 可以避免死锁.

劣势: 大部分情况下DML操作并发低, 频繁对全表加锁, 发生锁冲突的概率非常高.

页锁

页锁是介于比表锁和行锁之间的一种锁, 只是对数据页进行锁定

页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但并发低,行级并发高,但耗资源。所以取了折衷的页级,一次锁定数据页中相邻的一组记录

mysql 中的BDB引擎支持页级锁

大概锁的层次结构关系

2. 深入 mysql 的锁

锁分类 (latch 和 lock)

在 mysql 数据库中, 从全局看, 共分为这两种锁, 但他们的用处有很大区别.

latch 直译过来为“门闩(shuān)”, 类似于下图

它在数据库中的学名叫做 闩锁(一种轻量级的锁), 在 InnoDB 存储引擎中,latch又可以分为 mutex(互斥量)和 rwlock(读写锁), 其目的是用来保证并发线程操作临界资源的正确性,并且通常没有死锁检测的机制.

# 查看关于闩锁的统计信息
SHOW ENGINE INNODB MUTEX ;  
+--------+------------------------+---------+
| Type   | Name                   | Status  |
+--------+------------------------+---------+
| InnoDB | rwlock: log0log.cc:838 | waits=1 |
+--------+------------------------+---------+

lock 锁, 是我们打交道最多的一种, 它主要针对的是事务,用来锁定的是数据库中的对象,如前面提到的表锁、页锁、行锁。并且一般lock的对象仅在事务 commit 或 rollback 后进行释放(不同事务隔离级别释放的时间可能不同)。此外,lock,正如在大多数数据库中一样,是有死锁机制的.

3. InnoDB 实现 lock 锁分类

共享锁 (S Lock)

允许事物读取数据

当你拿到了共享锁, 你可以读取这条数据, 另一个人同样可以拿到共享锁去读取数据(这里我们称为锁兼容)

但是同时另一个人也来了, 他同时想要拿排他锁去更新此条数据,那么他必须等待释放共享锁才可以拿到排他锁更新数据(这里我们称之为锁不兼容)

排他锁 (X Lock)

允许事物删除或更新一行数据

前面我们举例了 如果别人已经持有共享锁了, 其他人是不能拥有排他锁的.

当一个人拿到此条数据的排他锁, 不能同时再拿到排他锁和共享锁的(锁不兼容).

排他锁(X Lock)和任何锁都不兼容.

4. Innodb 面对锁是怎么读取的

一致性的非锁定读

我们知道 当我们频繁 更新数据 加排他锁 (X Lock) 的时候, 因为其锁的不兼容性, 会严重影响正常的数据查询性能.

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

一致性非锁定读的快照数据其实是读的 undo 数据(undo是用来回滚事务中的数据), 没有额外的锁操作, 所以读取速度非常的快.

一致性的非锁定读因为不需要等待排他锁 (X Lock) 的释放, 所以极大的提高了并发的性能, 在 innodb 事务隔离级别 不可重复读(read-committed)、可重复读(repeatable-read 默认级别) select 使用的是 一致性的非锁定读.

思考: 一致性的非锁定读 解决了什么问题? 带来了什么问题?

一致性锁定读

在一些强一致的场景, 我们是希望让用户读取到的永远是最新的数据. 这时候, 我们需要使用 一致性锁定读 的场景.

下面展示了两种基于数据库查询语句上X锁和S锁, 一般与显示的事务组合使用.

SELECT…FOR UPDATE对读取的行记录加一个X锁,其他事务不能对已锁定的行加上任何锁 SELECT…LOCK IN SHARE MODE对读取的行记录加一个S锁,其他事务可以向被锁定的行加S锁,但是如果加X锁,则会被阻塞

FOR UPDATE 也是我们经常所说的悲观锁, 对应的还有乐观锁, 乐观锁更多是业务层面的实现, 这里不再讲述.

死锁

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去.

目前主要还是靠业务逻辑来解决, 如果程序是串行, 就不会产生死锁, 只有并发情况下才有可能产生, 程序并行+数据库并行(行级锁)运行, 可能会发生死锁.

这里可以使用此命令查看所有线程, 对应的提示直接 kill 掉即可

show processlist

查看目前锁的情况

1:查看当前的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

2:查看当前锁定的事务

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;

3:查看当前等锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

当然你也可以通过配置 innodb_lock_wait_timeout 属性,来指定锁的超时时间, 超时数据库系统自动 kill.

不过如果出现了长时间获取不到锁, 数据库会自动进行死锁检测, 并进行终止.

当然,保证业务中操作数据库的执行顺序, 避免交叉执行, 基本能够避免的死锁情况。

总结

本文一部分参考概念 《mysql 技术内幕》一书.

本文分享自微信公众号 - 呆呆熊的技术路(gh_93f28f51010a),作者:近视小猴子

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

原始发表时间:2019-07-22

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 设计模式第五讲-适配器模式

    存在两种适配器: “对象适配器” 和 “类”适配器 (因为大部分语言不支持多重继承,所以此处指的是对象适配器)

    用户2825413
  • TCP/IP网络编程之I/O复用select函数

    之前我们使用了几种服务器模型,一个是单进程的, 同一时刻只能给一个客户端提供服务, 后来我们使用了多进程, 每个客户端fork新进程进行请求处理

    用户2825413
  • gdb工具的简单使用

    打了一周末的王者,终于上了星耀.但是还是百忙之中,小妲己抽空谢写了一些操作步骤。

    用户2825413
  • 《Experiment with MATLAB》读书笔记(二)

    读书笔记(二) 这是第二部分函数与绘图 将代码复制到m文件即可运行 函数部分需新建m文件保存 %% 函数 % 变量在用之前先赋0站位 % 计数或者...

    万木逢春
  • 使用TensorFlow一步步进行目标检测(5)

    本教程进行到这一步,您选择了预训练的目标检测模型,转换现有数据集或创建自己的数据集并将其转换为TFRecord文件,修改模型配置文件,并开始训练模型。接下来,您...

    云水木石
  • UE4中的单映射:TMap容器

    一、TMap<T>是么 TMap<T>是UE4中的一种关联容器,每个键都关联着一个值,形成了单映射关系。因此你可以通过键名来快速查找到值。此外,单映射要求每...

    用户1198337
  • python3 下调用zabbix api 获取多个机房的IP

    根据工作的需要,需要查看监控中的所有ip,我们一共有三个机房,每个机房都部署了同样的zabbix监控 根据三个园区的 监控api的url 实现功能:不输入参数 ...

    98k
  • Js运动框架

    用户1749219
  • h5页面在不同iOS设备上的问题总结

    在做文章评论的功能时,会遇到很多兼容性的问题,在不同机型上的表现也很不一致,总结了以下这些问题。

    grain先森
  • 基于矩阵分解原理的推荐系统

    矩阵分解是推荐系统系列中的一种算法,顾名思义,就是将矩阵分解成两个(或多个)矩阵,它们相乘后得到原始矩阵。在推荐系统中,我们通常从用户与项目之间的交互/评分矩阵...

    老齐

扫码关注云+社区

领取腾讯云代金券