文章目录

  • 什么是锁机制
  • 并发的访问相同数据的情况
    • 读读
    • 写写
    • 读写/写读
  • 锁的分类
    • 共享锁(S锁)
    • 排他锁( X锁)
  • 表锁
    • 表级别的S、X锁.
    • 意向锁.
    • 自增锁
    • 元数据锁
  • 行锁
    • 记录锁
    • 间隙锁
    • 临键锁
    • 插入意向锁
  • 页锁
  • 其他锁
    • 全局锁
    • 死锁

什么是锁机制

锁是计算机协调多个进程或线程并发访问某一资源的控制.

  • 锁不仅仅限于数据库领域,在计算机中,当多个进程或线程并发的访问某个数据的时候,对于一些重要敏感的数据,为了保证数据的完整性一致性,我们需要保证最多只有一个线程在访问,所以诞生了锁机制
  • 锁机制的作用是对并发操作进行控制
  • 在MySQL中,锁保证了事务的隔离性

并发的访问相同数据的情况

读是查询操作,写是增删改操作.

读读

两个事务并发读取相同数据的情况.

  • 读读操作都是查询操作,本身对数据没有什么影响,所以没有什么问题.

写写

两个并发事务相继对同一个数据进行修改的情况.

  • 写写情况下,会发生数据脏写问题,脏写问题非常严重,任何的事物隔离级别都不允许发生这个问题
  • 为了避免脏写,数据库强制未提交事务必须排队执行,通过锁实现强制.
  • 假设事务T1想要修改一条记录,如果内存中没有与之相关的锁结构,会生成一个锁结构与它进行关联。简化图:.

锁结构中,trx标识该锁结构属于哪个事务,is_waiting标识该事务是否在等待

  • T1之前没有任何事务对该记录进行修改,所以is_waiting是false,表示无须等待,可以直接修改,即加锁成功.在事务T1未提交之前,如果事务T2也想对该记录修改,就需要等待,is_waiting是true,需要等待,即加锁失败.

  • 在事务T1提交后,锁会释放,交给T2,T2的is_waiting变为false,然后T2就会开始执行.

读写/写读

两个并发事务,对于同一条数据,一个读取,一个修改。

  • 读写/写读情况下会发生脏读、不可重复读、幻读问题
  • 解决这些问题有两个办法:一是对读操作使用MVCC,写操作进行加锁.方法二是读写操作都进行加锁.

锁的分类

  • 对数据的操作类型划分:共享锁(读锁)、排他锁(写锁)
  • 从锁粒角度划分:表锁、行锁、页锁
  • 从锁的态度进行划分:悲观锁、乐观锁
  • 从加锁方式划分:隐式锁、显式锁
  • 从其他角度划分:全局锁、死锁

共享锁(S锁)

  • 共享锁(Shared Lock) 也叫读锁,对于同一份数据,多个事务进行读取时可以同时进行互不影响

排他锁( X锁)

  • 排他锁(Exclusive Lock)也叫写锁、X锁,对于同一份数据,当一个数据进行写操作时,禁止其他事务的读、写操作.

对于Innodb引擎,读锁和写锁可以加在表上,也可以加在行上.

两个锁之间的兼容性

锁定读操作

读取时加S锁:
SELECT ... Lock in share mode;
或者
select....for share;
为这条记录添加了S锁后,就不允许其他事务获得该记录的X锁
读取时加X锁:
SELECT.... for update:为这条记录加了X锁后,就不允许其他事务获得该记录的S、X锁.

锁定写操作

写操作只有三种:delete、update、insert对于delete操作:获取记录位置,然后获取它的X锁,再进行deletemark操作----可以理解为获取X的锁定读对于update操作:
获取记录位置,相当于获取X锁,锁定读。然后主键更改,就删除,并重新添加一个,如果没更改,就直接在原记录中更新.对于insert操作:
并不加锁.有隐式锁来保护不被其他事务打扰.

表锁

表锁会锁住整张表,是MySQL中最基本的锁策略,并且不依赖于任何存储引擎.

表级别的S、X锁.

  • 对表执行普通的增加删除修改更新操作时,不会添加表级的S、X锁.
  • 当事务A对表执行增加删除修改更新操作,事务B并发执行影响表结构的操作(如alter tabledrop table)时,才会有表级锁的出现,对事务进行阻塞
  • 同理,事务A对表结构进行修改时,如果事务B并发执行普通的增删查改,也会发生阻塞.

为表添加S、X锁

LOCK TABLES T read;LOCK TABLES t WRITE;虽然可以手动添加表锁,但一般很少使用,因为有更强大的行锁

限制关系

对限制关系的演示

初始化数据
mysql> create table mylock(-> id int not null primary key auto_increment,-> name varchar(20)-> )engine myisam;
Query OK, 0 rows affected (0.06 sec)mysql> insert into mylock(name) values('a');
Query OK, 1 row affected (0.04 sec)加锁
mysql> lock tables mylock read;
Query OK, 0 rows affected (0.00 sec)加锁后自己可读
mysql> select*from mylock;
+----+------+
| id | name |
+----+------+
|  1 | a    |
+----+------+
1 row in set (0.00 sec)自己不可写
mysql> update mylock set name='a1' where id=1;
## ERROR 1099 (HY000): Table 'mylock' was locked with a READ lock and can't be updated;#自己不可操作其他表
mysql> select *from account;
## ERROR 1100 (HY000): Table 'account' was not locked with LOCK TABLES他人可读
mysql> select* from mylock;
+----+------+
| id | name |
+----+------+
|  1 | a    |
+----+------+
1 row in set (0.00 sec)
他人不可写 会阻塞
mysql> update mylock set name='a2' where id=1;释放锁
mysql> unlock tables ;
Query OK, 0 rows affected (0.00 sec)改为写锁
mysql> lock tables mylock write;
Query OK, 0 rows affected (0.00 sec)自己可以读取
mysql> select*from mylock;
+----+------+
| id | name |
+----+------+
|  1 | a    |
+----+------+
1 row in set (0.00 sec)
自己可以写入
mysql> update mylock set name='a3' where id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0
自己不能操作其他表
mysql> select*from account;
ERROR 1100 (HY000): Table 'account' was not locked with LOCK TABLES他人读取会阻塞
mysql> select*from mylock;
## 阻塞
他人写入会阻塞
mysql> update mylock set name='a4' where id=1;
## 阻塞

意向锁.

事务A对某一行数据加了一个锁,事务B如果想对整张表加一个锁,就需要检查该表中是否已经存在锁,在数据量非常大的情况下,一页一页的检索是非常复杂的一件事情.此时就可以用到意向锁.

  • 意向锁是表级别的锁,对整张表添加
  • 意向锁是存储引擎自动添加,不需要手动添加
  • 意向锁不会与行锁发生冲突
  • 意向锁分两种:意向共享锁、意向排他锁
  • 如果我们给某一行数据加上了排他锁,数据库会自动给更大一级的空间(比如数据页、数据表)加上意向锁,告诉他人这个数据页或数据表已经有人上过排他锁了

意向共享锁(IS锁)
存在事务想对表中的某个数据添加共享锁

--事务想要获取某项行的S锁,必须先获得表的IS锁
select...from table...lock in share mode;

意向排他锁(IX锁)
存在事务想对表中的某个数据添加排他锁

---事务想要获得某项行的X锁,必须先获得表的IX锁
select ... from table...for update;
  • 意向锁之间相互兼容,互不影响
  • 意向锁和表级别的X,S锁不兼容,除了IS和S

自增锁

  • 特殊的表级锁,事务向AUTO_INCREMENT字段添加新数据时就会持有自增锁
  • 如果事务A正在向自增列添加新数据,此处事务B尝试INSERT,就会被阻塞.
  • 不同锁模式下运行机制不同,行为不同,锁模式通过参数innodb_autoinc_lock_mode进行设置
  • 自增列必须是索引才能用自增锁.

元数据锁

  • 元数据锁(meta data lock,MDL锁)是表锁.
  • 当事务对一个表进行增删改查时,会自动添加MDL读锁,当事务对表结构进行修改的时候,会自动添加MDL写锁
  • 自动添加MDL锁的作用就是防止表在增删改时,表结构被改动。
  • 读读不互斥、读写、写写互斥
  • 自动添加,无须手动

行锁

  • 对某一条记录进行加锁
  • 优势是锁定单位小,所以冲突概率低,并发性非常高,劣势是会用太多的锁资源,加锁慢,容易出现死锁问题
  • Innodb和MyISAM引擎最大的不同:支持事务;支持行锁

记录锁

  • 非常普通的锁,就是对某一条记录加锁
  • 分为S、X型。
  • 当事务获的某条记录的S型记录锁后,其他事务只能获取S型
  • 当事务获得某条记录的X型锁后,其他事务只能等待

间隙锁

  • 我们可以通过加锁的方式解决幻读问题,但是问题是幻读产生的那些幻影记录一开始并不存在,无法加锁,为了解决这个问题,就产生了间隙锁gap锁
  • 间隙锁只有一个作用:防止插入幻影记录
  • 比如我们对id=8的记录加上间隙锁,那么上一条记录和id=8的记录之间就不允许插入新的记录,如果其他事务想要插入新的记录,会被阻塞.
  • 对某记录之后的区间加上gap锁,需要用两条伪记录:Infimum记录,表示该页中最小记录;Supremum记录,表示该页中最大的记录;
  • 直接对Supremum记录加gap锁即可

临键锁

  • 临键锁=记录锁+间隙锁
  • 作用:锁住某条记录,并阻止其他事务在该事务前面的间隙插入事务
  • 分为临键S和临键X锁,互斥情况和记录锁相同
begin;
select*from student where id<=8 and id>3 for update;

插入意向锁

  • 插入意向锁是在插入一条记录时,由INSERT操作产生的一种间隙锁.
  • 插入意向锁本质是间隙锁
  • 在插入一条记录时,需要看插入位置是否被别的事务加了间隙锁,如果有,需要等待,知道间隙锁的事物提交.等待时,会生成一个锁结构,表名某事务有在某位置插入数据的意图,这个锁结构就是意向锁
  • 插入意向锁互不排斥

当事务T1结束后,事务T2和T3都会获取到插入意向锁:

页锁

  • 粒度大小介于表锁和行锁之间
  • 开销介于表锁和行锁之间
  • 锁的空间大小有限,超过大小时,会自动进行锁升级.

粒度越大,开销越小。粒度大小:表>页>行。开销:表<页<行

其他锁

全局锁

  • 对整个数据库实例加锁,整个库处于只读的状态
  • 增删查改、修改表结构的等都会阻塞
  • 使用场景:全库备份(对数据库进行备份时,不允许操作)
  • 命令:Flush tables with read lock

死锁

  • 两个或多个事务在同一资源上进行占用,都有对方的需要的锁,但都不释放,陷入死循环
  • 例如下图:事务1对id=1的记录设置了X锁,事务2又对id=2的记录设置了X锁。事务1在尝试更新记录2时陷入阻塞,事务2再尝试更新记录1时陷入阻塞。然后两个事务互相僵持,陷入死锁状态

死锁条件

  • 必须有两个事务
  • 每个事务都持有锁,还申请新的锁
  • 新锁恰好为对方所有

如何处理死锁

  • 方法1:等待,直到超时

  • 两个事务互相等待,当一个事务等待时间超过设置的阈值时,就将其回滚。另一个事务就可以继续进行。

  • Innodb中,使用innodb_lock_wait_timeout设置时间

  • 方法2:使用死锁检测进行死锁处理

  • innodb中有wait-for graph算法主动检测死锁,每次加锁需要等待时就会触发

  • 死锁检测原理:
    数据库会保存锁的信息链表事务等待链表


根据上面两个信息,可以画出等待有向图:

在等待图中,如果有环的存在,就是死锁。

  • 如果出现死锁,存储引擎就会回滚操作量最小的事务.

MySQL~锁的大集合(S锁、X锁、意向锁、自增锁、元数据锁、记录锁、间隙锁、临键锁、全局锁、死锁)相关推荐

  1. MySQL锁:全局锁、表级锁和行锁

    事务的实现离不开MySQL数据库的锁机制,设计锁的目的也是为了处理并发访问问题,本文简单介绍MySQL 里面的全局锁.表级锁和行锁三类锁. 目录 全局锁 表级锁 表锁 1.读锁实例 2.写锁实例 元数 ...

  2. mysql锁(全局锁、表锁、行锁、页锁、排他锁、共享锁)

    mysql锁 简介 数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则. MySQL数据库由于其自身架构的特点,存在多种数据存储引擎,每种存储 ...

  3. mysql进阶: mysql中的锁(全局锁/表锁/行锁/间隙锁/临键锁/共享锁/排他锁)

    锁在生活中处处可见,门锁,手机锁等等. 锁存在的意义是保护自己的东西不被别人偷走/修改. 在mysql中锁的意义也是一样,是为了保护自己的数据不被别人进行修改,从而导致出现脏读,幻读等问题.在学习锁的 ...

  4. mysql主键查询gap锁失效,mysql记录锁(record lock),间隙锁(gap lock),Next-key锁(Next-key lock)...

    1. 什么是幻读? 幻读是在可重复读的事务隔离级别下会出现的一种问题,简单来说,可重复读保证了当前事务不会读取到其他事务已提交的 UPDATE 操作.但同时,也会导致当前事务无法感知到来自其他事务中的 ...

  5. mysql 写锁需要等待读锁释放吗_Mysql实战45讲笔记:5、全局锁和表锁

    全局锁: 对整个数据库实例加锁. MySQL提供加全局读锁的方法:Flush tables with read lock(FTWRL) 这个命令可以使整个库处于只读状态.使用该命令之后,数据更新语句. ...

  6. mysql主键更新被锁_MySQL 的加锁处理,你都了解的一清二楚了吗?

    MySQL加锁分析,一直是一个比较困难的话题. 我在工作过程中,经常会有同事咨询这方面的问题.本文,准备就MySQL加锁问题,展开较为深入的分析与讨论,主要是介绍一种思路,运用此思路,拿到任何一条SQ ...

  7. mysql是表级锁还是行级锁_带你了解MySQL数据库中的全局锁、表级锁、行级锁

    在 MySQL 数据库中,有很多各种各样的锁,这些锁大致可以分为三类:全局锁.表级锁.行级锁.这篇文章小编就带你简单了解一下这三种锁. 1. 全局锁 全局锁是粒度比较大的锁,基本上也使用不上,就像我们 ...

  8. mysql 锁 行级_全局锁、表级锁、行级锁mysql 极客评论笔记

    根据加锁范围:MySQL里面的锁可以分为: 一.全局锁: 对整个数据库实例加锁. MySQL提供加全局读锁的方法:Flush tables with read lock(FTWRL) 这个命令可以使整 ...

  9. mysql全局读写怎么锁_MySQL全局锁和表锁

    最近正好在看操作系统中关于线程,锁的部分,也可以学习一下数据库种的锁. MySQL的锁分为全局锁,表级锁,行锁三类. 全局锁 名思义,全局锁就是对整个数据库实例加锁.MySQL提供了一个加全局读锁的方 ...

  10. Mysql 全局锁入门

    全局锁顾名思义,全局锁就是对整个数据库实例加锁. 如何手动使用全局锁? MySQL 提供了一个加全局读锁的方法,命令是 Flush tables with read lock (FTWRL).当你需要 ...

最新文章

  1. Contact Bubble View
  2. C# cs文件表头模版
  3. springboot 集成rabbitmq 实例
  4. socket认证客户端链接合法性
  5. 数据结构(一)线性表链式存储实现
  6. 对C# 程序员来说现在是到目前为止最好的时代
  7. antd autoplay按f12才会轮播_涨知识了!原来这才是电脑键盘上,F1到F12的正确用法...
  8. java源码如何启动脚本_使用Shell脚本如何启动/停止Java的jar程序
  9. 日常的SQL 语句使用
  10. java收_收java的小程序……谢谢
  11. Qt数据可视化(QPieSeries饼状图)
  12. 【源码阅读 | 03】only-allow 统一规范团队包管理器
  13. 学嵌入式为什么要学Linux?
  14. 【AD】原理图放置差分对,报错Missing Negative Net for differential pair
  15. 嵌入式课程设计linux,嵌入式课程设计报告
  16. Cannot find ./catalina.sh The file is absent or does not hav
  17. 一台机子上运行多个mysql实例
  18. POI 设置单元格背景色,背景色编码与实际颜色对照表(SXSSFWorkbook4.1.2)
  19. 图片中的alt标签和title标签
  20. 微信多平台版本日志大全.2021-12-17

热门文章

  1. nginx -s reopen 命令小解
  2. html文本内容自动滚动,网页HTML代码滚动文字制作
  3. 原生js获取元素非行内样式属性的方法
  4. java发送邮件连接超时,Java邮件超时和连接超时处理
  5. 百度搜索推广账户搭建思路
  6. 搭档之家|紧跟信息消费大发展时代步伐
  7. 以云为翼—走近神州数码武汉云基地
  8. 矩阵求逆的一万种方法
  9. 离散数学复习笔记——命题逻辑——命题
  10. Google中Gson的巧妙使用 —————— 开开开山怪