【MySQL 流浪之旅】 第六讲 浅谈 MySQL 锁

系列文章目录

【MySQL 流浪之旅】 第一讲 MySQL 安装
【MySQL 流浪之旅】 第二讲 MySQL 基础操作
【MySQL 流浪之旅】 第三讲 MySQL 基本工具
【MySQL 流浪之旅】 第四讲 MySQL 逻辑备份
【MySQL 流浪之旅】 第五讲 数据库设计的三个范式


目录

系列文章目录

一、什么是锁?

二、锁的类型?

三、锁的算法?

四、锁与事务隔离级别

4.1. 隔离级别简介

4.2. Read Uncommitted(读取未提交内容)

4.3. Read Committed(读取提交内容) 

4.4. Repeatable Read(可重读)

4.5. Serializable(可串行化)

五、死锁


一、什么是锁?

锁是实现事务隔离性最广泛使用的技术。以 MySQL InnoDB 为例,数据库的锁有排他锁,共享锁,意向锁,自增锁,间隙锁。

按照粒度分为锁定整个表的表级锁(table-level locking)和锁定数据行的行级锁(row-level locking):

  • 表级锁具有开销小、加锁快的特性;但是表级锁的锁定粒度较大,发生锁冲突的概率高,支持的并发度低;
  • 行级锁具有开销大,加锁慢的特性;但是行级锁的锁定粒度较小,发生锁冲突的概率低,支持的并发度高。

InnoDB 存储引擎同时支持行级锁(row-level locking)和表级锁(table-level locking),默认情况下采用行级锁。
InnoDB的行锁是实现在索引上的,而不是锁在物理行记录上。所以如果访问没有命中索引,就无法使用行锁,将要退化为表锁(共享行锁上升为共享表锁,排他行锁上升为排他表锁)。

二、锁的类型?

InnoDB存储引擎实现的是行级锁

  • 共享锁(S Lock):允许事务读一行数据
  • 排他锁(X Lock):允许事务删除或更新一行数据

排他锁和共享锁的兼容性

 

  • 意向共享锁(IS Lock):事务想要获得一张表中某几行的共享锁
  • 意向排他锁(IX Lock):事务想要获得一张表中某几行的排他锁

 意向排他锁和意向共享锁的兼容性

  • 间隙锁:where条件是一个范围时,数据库会锁定区间数据,主要是解决幻读问题。 
  • 自增锁:自增锁是一种特殊的表级别锁(table-level lock),专门针对事务插入AUTO_INCREMENT类型的列。最简单的情况,如果一个事务正在往表中插入记录,所有其他事务的插入必须等待,以便第一个事务插入的行,是连续的主键值。控制同一sql 语句插入的所有记录的自增id是连续的。

平时还有提到的悲观锁,乐观锁,在数据库层面上没有这个锁的概念,如果要做简单映射,悲观锁可以映射成排他锁,乐观锁是由应用层面保障的,和 DB 的锁概念无关。

  • 乐观锁:认为冲突概率低,操作数据时,不会锁定数据,只有在提交修改时,才检查。如果数据已被修改,则回滚,否则提交。 
  • 悲观锁:一种并发控制方法。认为冲突概率高,每次读写前都加锁。

所以我们说,锁的分类从不同角度来看有不同的类型:

三、锁的算法?

  • Record Lock:单个行记录上的锁
  • Gap Lock:间隙锁,锁定一个范围,但不包含基本本身
  • Next-key Lock:Gap Lock + Record Lock:锁定一个范围,并且锁定记录本身 

四、锁与事务隔离级别

4.1. 隔离级别简介

事务的隔离级别是用来描述并发控制机制中不同事务之间隔离程度的参数。以下是几种常见的隔离级别及其特点:

  • Read Uncommitted(读取未提交内容)
  • Read Committed(读取提交内容)
  • Repeatable Read(可重读)
  • Serializable(可串行化)
事务隔离级别脏读不可重复读幻读
Read Uncommitted(读取未提交内容)
Read Committed(读取提交内容)
Repeatable Read(可重读)
Serializable(可串行化)

4.2. Read Uncommitted(读取未提交内容)

定义:所有事务都可以看到其他未提交事务的执行结果。(本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少)读取未提交的内容也称为脏读,所以在该隔离级别下是存在脏读这种缺陷的。在该隔离级别是允许脏读。

锁的状态:Read Uncommitted这个隔离级别是不加锁的,所有的事物都能任意操作数据,数据是没有任何一致性可言,其实数据就是处于混乱的状态中。

图示

图中所示,会导致什么问题呢?

tab2在B时刻查询到了表的数据,但是如果在C时刻发生了回滚,那么tab1的数据的插入不成功的,其实这时表里是没有数据的,但是事务tab2却查询到了数据,这就导致数据不一致了。

4.3. Read Committed(读取提交内容) 

定义:只能读取到已经提交的数据,这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 会出现所谓的不可重复读(Nonrepeatable Read)这种缺陷,因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。

锁的状态:该隔离级别下,数据的读取都是不加锁的,但是事务的写入、修改、删除是加锁的。

4.4. Repeatable Read(可重读)

定义:这是MySQL的默认事务隔离级别,他确保一事务的多个会话在并发读取数据时,会看到同样的数据行。

T1

T2

T3

begin;

begin;

begin;

root@localhost> select id,class_name,teacher_id from class_teacher;

+----+--------------+------------+

| id | class_name   | teacher_id |

+----+--------------+------------+

|  1 | 初三一班     |          1|

|  2 | 初三二班     |         1 |

+----+--------------+------------+

2 rows in set (0.00 sec)

update class_teacher set class_name='初三三班' where id=1;

Waiting……

root@localhost> select id,class_name,teacher_id from class_teacher;

+----+--------------+------------+

| id | class_name   | teacher_id |

+----+--------------+------------+

|  1 | 初三一班     |          1|

|  2| 初三二班     |         1 |

+----+--------------+------------+

2 rows in set (0.00 sec)

insert into class_teacher values (null,'初三三班',1);

commit;

root@localhost> select id,class_name,teacher_id from class_teacher;

+----+--------------+------------+

| id | class_name   | teacher_id |

+----+--------------+------------+

|  1 | 初三一班     |          1|

|  2 | 初三二班     |         1 |

|  3 | 初三三班     |         1 |

+----+--------------+------------+

3 rows in set (0.00 sec)

从上图可以看出,传统的Repeatable Read(可重读),为了保证可重读,读取出来的数据行是加锁的,所以这些行在commit(锁释放)前是不能修改的,但是他不会对新插入的行加锁,所以T3是可以插入数据的,并且再次查询的时候就会看到新插入的的行,这种现象就是幻读。

4.5. Serializable(可串行化)

定义:这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁(每次读都需要获得表级共享锁)。在这个级别,可能导致大量的超时现象和锁竞争,读写相互都会阻塞。因此,会导致大量的超时现象。

锁的状态:MySQL从MVCC并发控制退化为基于锁的并发控制。不区别快照读与当前读,所有的读操作均为当前读,读加读锁 (S锁),写加写锁 (X锁)。Serializable隔离级别下,读写冲突,因此并发度急剧下降,在MySQL/InnoDB下不建议使用。

五、死锁

死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象。

show engine innodb status查看死锁信息

死锁通常包括以下四个必要条件:

  1. 互斥条件(Mutual Exclusion):每个资源只能同时被一个线程占用。如果一个线程占用了某个资源,其他线程就无法同时占用它。
  2. 请求与保持条件(Hold and Wait):线程在持有某些资源的同时,又请求其他资源。如果线程在等待其他资源时不释放已占用的资源,就可能导致死锁。
  3. 不可剥夺条件(No Preemption):系统不能抢占线程占用的资源,只能由线程自愿释放。
  4. 循环等待条件(Circular Wait):多个线程之间形成一个环形等待其他线程释放资源的情况。 

为了预防和解决死锁问题,可以采取以下策略:

  1. 加强互斥条件:尽量减少共享资源的互斥性,或者使用更高级的同步机制来替代基本的互斥锁。
  2. 加强请求与保持条件:要求数资源时,尽量一次性请求所有需要的资源,而不是逐个请求。
  3. 加强不可剥夺条件:允许操作系统抢占线程占用的资源,以避免某些线程长时间占用资源而导致死锁。
  4. 加强循环等待条件:引入资源分配图,检测潜在的死锁情况,然后采取措施来打破等待环路。
  5. 使用超时:线程在等待资源时,设置一个超时时间,超时后可以放弃等待或者重试。
  6. 使用死锁检测和恢复机制:系统可以定期检测死锁,并采取措施来解除死锁,如终止某些线程或回滚操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/440276.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

25考研北大软微该怎么做?

25考研想准备北大软微,那肯定要认真准备了 考软微需要多少实力 现在的软微已经不是以前的软微了,基本上所有考计算机的同学都知道,已经没有什么信息优势了,只有实打实的有实力的选手才建议报考。 因为软微的专业课也是11408&am…

D1675滤波器和缓冲器用于单通道6阶高清视频滤波驱动电路,可提高视频信号性能

D1675单电源工作电压为2.5V到5V,是一款高清视频信号译码、编码的滤波器和缓冲器。与使用分立元件的传统设计相比,D1675更能节省PCB板面积,并降低成本以及提高视频信号性能。D1675集成了一个直流耦合输入缓冲器、一个消除带外噪声的视频编码器…

C++ 数论相关题目 求组合数Ⅱ

给定 n 组询问,每组询问给定两个整数 a,b ,请你输出 Cbamod(1097) 的值。 输入格式 第一行包含整数 n 。 接下来 n 行,每行包含一组 a 和 b 。 输出格式 共 n 行,每行输出一个询问的解。 数据范围 1≤n≤10000 , 1…

时序数据库 Tdengine 执行命令能够查看执行的sql语句

curl是 访问6041端口,在windows系统里没有linux里的curl命令,需要用别的工具实现。我在cmd里是访问6030端口 第一步 在安装是时序数据库的服务器上也就是数据库服务端 进入命令窗口 执行 taos 第二步 执行 show queries\G;

冬季养生攻略,打造健康与美丽的秘诀

冬季养生攻略,打造健康与美丽的秘诀 寒冬时节,寒气袭人,养生更加重要。如何在冬季保持健康与美丽?本文将为您揭示冬季养生的秘诀,让您在寒冷的季节中依然散发健康的光彩。 一、合理饮食,保持体内平衡 冬季…

蓝桥杯---加法变乘法

我们都知道:123 ….. 491225,现在要求你把其中两个不相邻的加号变成乘号,使得结果为2015 比如:123 ... 10*1112 ... 27*2829 ... 492015 就是符合要求的答案. 请你寻找另外一个可能的答案,并把位置靠前的那个乘号左边的数字提交(对于示例,就是 提交10)…

Prometheus:普罗米修斯

Promethues:普罗米修斯 promethues是一个开源的系统监控以及报警系统。整合了zabbix的功能,系统,网络,设备。 promethues可以兼容网络,设备。容器监控。告警系统。因为他和k8s是一个项目基金开发的产品,天生匹配k8s的原…

通过Nacos权重配置,模拟微服务金丝雀发布效果(不停机部署)

在微服务项目迭代的过程中,不可避免需要上线;上线对应着部署,或者升级部署;部署对应着修改,修改则意味着风险。 传统的部署都需要先停止旧系统,然后部署新系统,之后需要对新系统进行全面的功能测试&#xf…

盘点热门的GPTS智能体,生产力远超原生ChatGPT4

OPENAI开放了GPTS智能体商店,类似于appstore的应用商店,在GPTS商店里面你可以发现并创建自定义版本的ChatGPT,这些版本结合了指令、额外知识和任何技能组合! 本周精选 GPTS智能体不仅可以通过API的方式将你的私有化的数据和能力…

外汇天眼:芬泰尔完成对Synaptic Software的收购

Fintel(伦敦证券交易所代码:FNTL)是一家为英国零售金融服务行业提供金融科技和支持服务的公司,已完成对Synaptic Software的收购。Synaptic Software是一家独立的金融顾问规划和研究软件提供商。 根据2023年12月5日宣布的消息&…

C++笔试强训选择题7

1.对于以下代码,说法正确的是() char * p new char[100];A p 和 new出来的内存都在栈上 B p 和 new出来的内存都在堆上 C p在栈上 new出来的在堆上 D p在堆上 new出来的在栈上 new默认情况下申请的空间在堆上 2. 类模板的使用…

【毕业快刊】仅用时15天!Springer旗下2区SCI,分区上升!审稿超快!

关注公主号【SciencePub学术】,发现期刊更多精彩~ 本期,小编给大家推荐的是一本Springer旗下2区计算机领域进展超顺的SCI期刊,最快仅用时15天录用! 01 期刊基本信息 【期刊简介】IF:4.5-5.0,JCR2区&…