MySQL中的锁

  • 前言
  • 一、锁的分类
  • 二、从数据操作的类型划分:读锁、写锁
  • 三、从数据操作的粒度划分:表级锁、页级锁、行锁
    • 1. 表锁
      • 1.1 表级别的s锁、x锁
      • 1.2 意向锁
      • 1.3 自增锁(AUTO-INC锁)
      • 1.4 元数据锁(MDL锁)
    • 2. 行锁
      • 2.1 记录锁
      • 2.2 间隙锁
      • 2.3 临键锁
      • 2.4 插入意向锁
    • 3. 行锁
  • 四、从对待锁的态度划分:乐观锁、悲观锁
    • 1 悲观锁
    • 2. 乐观锁
  • 五、从加锁方式划分:显示锁、隐式锁
    • 1. 显示锁
  • 六、其他锁
    • 1 全局锁
    • 2. 死锁
    • 3. 如何避免死锁
  • 七、锁的结构
  • 八、锁监控

前言

现在很多的工具和编程语言都是多线程异步的(相互之间同时进行或交错进行),但是在某些情况下想要多个线程同步进行(前一个执行完,后一个才能执行),这时就离不开锁。
在mysql中,例如最简单的如果有一列是自增的,那么表中该列同一时刻只能有一个线程在申请自增的id,此时就需要一个锁来保证同步进行,这个锁就叫自增锁。
在java中,当想让一个方法成为同步方法,就在方法前加synchronized。
本文,主要讲解mysql中各种各样的锁。


一、锁的分类


二、从数据操作的类型划分:读锁、写锁

在并发事务中读-读并不会引起什么问题。对于写-写读-写写-读可能会引起一些问题,需要使用mvcc或加锁解决。由于既要允许读-读情况不受影响,所以mysql实现了一个由两种类型的锁组成的锁系统来解决。通常被称为共享锁(Share Lock)排他锁(Exclusive Lock),也叫读锁和写锁。

(1) 对记录加S锁

SELECT ... LOCK IN SHARE MODE;
或者
SELECT ... FOR SHARE;(8.0)

(2) 对记录加X锁

SELECT ... FOR UPDATE;(8.0)

在mysql5.7及之前版本,如果获取不到锁,会一直等待,直到innodb_lock_wait_timeout超时。在8.0中,如果后面加nowait、skip locked可以跳过等待,或者只返回没锁定的行。


三、从数据操作的粒度划分:表级锁、页级锁、行锁

锁定的数据范围越小,往往系统需要耗费更高的资源。所以数据库系统需要在高并发响应系统性能两方面进行平衡,这样就产生了锁粒度的概念。

1. 表锁

该锁会锁定整张表,并不依赖存储引擎。表锁可以避免死锁问题,但是并发率大打折扣。
表锁分为:表级别的s锁、x锁意向锁自增锁元数据锁

1.1 表级别的s锁、x锁

一般情况下,不会使用innodb存储引擎提供的表级s锁和x锁。在一些特殊情况下,比如崩溃恢复过程中用到。在系统遍历autocommit = 0,innodb_table_locks=1时,手动获取表锁方式未:

LOCK TABLES t READ
LOCK TABLES t WRITE
unlock tables : 解锁当前加锁的表
show open tables : 查看表当前是否加锁

1.2 意向锁

意向锁是一种表锁,它的存在是为了协调行锁和表锁关系的,它不与行锁冲突,表明某个事务正在某些行持有了锁。
意向锁分为意向共享锁(IS)和意向排他锁(IX)。
如果我们给某一行数据加上了排他锁,数据库会自动给更大一级的空间加上意向锁。

1.3 自增锁(AUTO-INC锁)

所有插入数据的方式总共分三类,分别是:

  • Simple inserts (简单插入),可以预先确定要插入的行数。
  • Bulk inserts (批量插入),事先不知道要插入的行数。
  • Mixed-mode-inserts (混合模式插入),只指定了部分id的值,还有未知id。

在插入时,mysql采用自增锁的方式来实现。当向使用auto_increment列插入数据时需要获取一种特殊的表级锁,在插入语句时加一个自增锁。然后再语句执行后,再把自增锁释放掉。一个事务再持有锁时,其他事务的插入语句都要被阻塞,所以并发性并不高。所以innodb通过innodb_autoinc_lock_mode的不同取值来提供不同的锁定机制。

  • 0 (传统锁定模式),并发差,就如上面所说的流程。
  • 1 (连续锁定模式) ,mysql8.0之前默认的模式。对于插入数量已知情况下,只在分配过程中保持,而不是直到语句完成。
  • 2 (交错锁定模式),在这种模式下,所有类insert语句都不会使用表级自增锁。自动递增保证在所有并发执行中是唯一且单调递增的。但是可能存在间隙。

1.4 元数据锁(MDL锁)

当对一个表做增删改查操作的时候,会自动给表加MDL读锁。当要对表的结构变更时,会自动给表加MDL写锁。
读读不会冲突,其余情况会冲突,所以用来解决DML和DDL操作之间一致性问题,不需要显式使用。

2. 行锁

行锁也成为记录锁,mysql服务器层并没有实现行锁机制,行锁只在存储引擎层实现。
InnoDB与MyISAM的最大不同有两点:一是支持事务,二是采用了行级锁。
行锁分为:记录锁间隙锁临键锁插入意向锁

2.1 记录锁

官方的类型名称为:LOCK_REC_NOT_GAP,用来锁住一条记录的。
记录锁分为S型记录锁X型记录锁

2.2 间隙锁

MYSQL在RR隔离级别下是可以解决幻读的。解决方案有两种,第一种是MVCC,第二种是加间隙锁。对一条记录加了gap锁,并不会限制其他事务对这条记录加记录锁或者gap锁。

  • 索引上的等值查询(唯一索引),给不存在的记录加锁时, 优化为间隙锁 。
  • 索引上的等值查询(普通索引),向右遍历时最后一个值不满足查询需求时,next-key lock 退化为间隙锁。
  • 索引上的范围查询(唯一索引)–会访问到不满足条件的第一个值为止。

2.3 临键锁

临键锁可以理解为一种特殊的间隙锁,上面说过了通过临建锁可以解决幻读的问题。 每个数据行上的非唯一索引列上都会存在一把临键锁,当某个事务持有该数据行的临键锁时,会锁住一段左开右闭区间的数据。

2.4 插入意向锁

在插入一条记录时,如果插入位置被别的事务加了gap锁,那么就需要等待。在等待时,innodb规定必须再内存中生成一个锁结构,表明有事务再等待。把这种类型的锁命名为Insert intention locaks
插入意向锁是一种特殊的间隙锁。(insert只有在插入时需要等待时才会生成插入意向锁,当插入完成后,该条记录上实际并没有锁,是一种隐式锁)。

3. 行锁

页锁就是在页的粒度上进行锁定,锁定的数据资源比行锁多,开销介于表锁和行锁之间,会出现死锁。
每个层级的锁数量是有限制的,应为锁会占用空间,锁空间的大小是有限的。当某个层级的锁数量超过了这个层级的阈值时,就会进行锁升级。锁升级就是用更大粒度的锁替代多个更小粒度的锁。

四、从对待锁的态度划分:乐观锁、悲观锁

1 悲观锁

悲观锁总是假设最坏的情况,每次去拿数据都认为别人会修改,所以每次在拿数据的时候都会上锁。(每次只有一个线程使用,其他线程阻塞)。比如行锁、表锁都是在操作前就上锁,其他资源都需要阻塞。
java中的synchronized和reentrantlock等独占锁就是悲观锁思想的实现。
注意: select … fro update语句在执行过程中所有扫描的行都会被锁上,因此在mysql中用悲观锁必须确定使用了索引,而不是全表扫描,否则将会把整个表锁住。

2. 乐观锁

乐观锁认为对同一数据的并发操作不会总发生,不用每次都上锁。在更新的时候判断有没有人去更新这个数据即可。也就是不采用数据库自身的锁机制,而是通过程序来实现。在java中juc.atomic包下的原子变量类就是使用了乐观锁的一种实现方式:cas实现的。

  • 乐观锁的版本号机制
  • 乐观锁的时间戳机制

五、从加锁方式划分:显示锁、隐式锁

1. 显示锁


即一个事务对新插入的记录可以不显示的加锁。但是由于事务id的存在,相当于加了一个隐式锁。别的事务在对这条记录加锁时,会帮当前事务生成一个锁结构,从而减少锁的数量。

六、其他锁

1 全局锁

全局锁就是对整个数据库加锁。当你需要让整个库处于只读状态的时候,可以使用这个命令。典型的使用场景是:做全库逻辑备份。

Flush tables with read lock

2. 死锁

死锁就是两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环。处理方式有两种:

  • 等待,直到超时(innodb_lock_wait_timeout=50s)
  • 使用死锁检测进行死锁处理。

3. 如何避免死锁

  • 合理设计索引,使业务sql尽可能通过索引定位更少的行,减少锁竞争。
  • 调整业务sql执行顺序,避免长时间持有锁的事务在前面。
  • 避免大事务,尽量将大事务拆成多个小事务处理。

七、锁的结构

一个锁的本质就是在内存中创建一个锁结构与之相关,符合下边条件的记录会被放到一个锁结构中。

  • 在同一个事务中进行加锁操作
  • 被加锁的记录在同一页面中
  • 加锁的类型是一样的
  • 等待状态是一样的

innodb存储引擎中的锁结构如下:

八、锁监控

show status like 'innodb_row_lock%'



mysql中把事务和锁的信息记录在了information_schema库中,涉及到的三张表为:innodb_trx、innodb_locks和innodb_lock_waits。

MySQL高级篇——锁相关推荐

  1. mysql高级篇学习笔记

    目录 前言 1 mysql安装及运行(linux环境) 1.1 安装前检查 1.2 MySQL卸载 ①**关闭 mysql 服务** ②**查看当前 mysql 安装状况** ③**卸载上述命令查询出 ...

  2. 【MySQL高级篇笔记-MySQL事务日志(下) 】

    此笔记为尚硅谷MySQL高级篇部分内容 目录 一.redo日志 1.为什么需要REDO日志 2.REDO日志的好处.特点 3.redo的组成 4.redo的整体流程 5.redo log的刷盘策略 6 ...

  3. MySQL高级篇知识点——索引优化与查询优化

    目录 1.数据准备 1.1.建库建表 1.2.创建相关函数 1.3.创建存储过程 1.4.调用存储过程 1.5.删除某表上的索引 2.索引失效案例 2.1.全值匹配 2.2.最佳左前缀匹配原则 2.3 ...

  4. MySQL高级篇(事务视图存储过程与函数)

    目录 一.事务 1.1什么是事务? 1.2事务的特性 1.3事务的分类 1.4事务的操作步骤 1.5事务的隔离级别(面试题常考) 二.视图 2.1视图的操作 2.1.1视图的创建 2.1.2视图更新( ...

  5. MySQL高级篇知识点——其它数据库日志

    目录 1.其他数据库日志 1.1.日志类型 1.2.日志的弊端 2.慢查询日志 (slow query log) 3.通用查询日志 (general query log) 3.1.问题场景 3.2.查 ...

  6. 深入浅出Mysql - 优化篇(锁)

    深入浅出Mysql - 优化篇(锁) 锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保 ...

  7. mysql高级篇(二)mysql索引优化分析

    mysql高级篇笔记 mysql高级篇(一)mysql的安装配置.架构介绍及SQL语句的复习. mysql高级篇(二)mysql索引优化分析. mysql高级篇(三)查询截取分析(慢查询日志).主从复 ...

  8. 【MySQL高级篇】第15章_锁

    第15章_锁 1. 概述 在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的 资源.为保证数据的一致性,需要对 并发操作进行控制 ,因此产生了 锁 .同 ...

  9. 程序猿必备技能之MySQL高级篇

      MySQL是我们非常常用的关系型数据库,非常重要,所以在这里给大家整理下MySQL的高级内容. 1. MySQL高级特性 1.1. MySQL体系结构 Client Connectors: 接入方 ...

  10. Mysql高级(锁、日志)

    Mysql高级(事务.索引) Mysql中查询缓存优化 开启Mysql的查询缓存,当执行完全相同的SQL语句的时候,服务器就会直接从缓存中读取结果,当数据被修改,之前的缓存会失效,修改比较频繁的表不适 ...

最新文章

  1. UML和模式应用学习笔记-1(面向对象分析和设计)
  2. 【成长之路】【python】python基础5-模块
  3. 函数的嵌套调用-函数嵌套调用的执行线路图
  4. log4j配置文件及nutch中的日志配置
  5. Markdown编辑器模板
  6. ubuntu设置mysql可以非本地访问_ubuntu server下设置mysql的远程访问权限
  7. window获取历史url_Facebook 开出历史最高赏金,55,000 美元奖励十年漏洞发现者
  8. 7-6 顺序存储的二叉树的最近的公共祖先问题 (10 分)
  9. 《虚拟化技术原理与实现》读书笔记之前序
  10. 设计模式(三):单例模式
  11. max std value 宏_【转载】:【C++跨平台系列】解决STL的max()与numeric_limits::max()和VC6 min/max 宏冲突问题...
  12. 【数学建模】基于matlab重庆三号线地铁运行仿真【含Matlab源码 042期】
  13. vscode集成linux的git,vscode中内置集成终端显示为git(bash.exe)
  14. winrar 4.20 注册码
  15. 开展网络口碑营销的前提
  16. n9009+android+4.4.2,三星N9009 (Galaxy Note 3 电信版 Android 4.4)ROOT教程,一键获取ROOT权限...
  17. LINUX未来的发展前景
  18. C语言读取文件时txt中的汉字出现乱码的解决方案
  19. Windows Server 2008R2 取消屏幕自动锁定
  20. Scrapy 爬虫框架(基础)

热门文章

  1. CTF Alice与Bob
  2. PAT|1138 Postorder Traversal(二叉树重建,遍历)
  3. python的spider程序下载_开源网络爬虫程序(spider)一览
  4. 4种实现Web前端可视化的常用方法
  5. 网页版在线使用PS网站源码
  6. php作为客户端websocket,使用PHP客户端连接到websocket
  7. 随机生成20以内加减法,5次答题并统计正确和错误题数
  8. Microsoft 环回适配器安装
  9. 乖乖地听我们三班的指挥
  10. 2022 第二届中国移动“梧桐杯”大数据应用创新大赛-基于移动大数据的网约车司机识别 线上0.95+ 方案