白话Mysql的锁和事务隔离级别!死锁、间隙锁你都知道吗?

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 我们把那些可能会被多个线程同时操作的资源称为临界资源,加锁的目的就是让这些临界资源在同一时刻只能有一个线程可以访问。这是当时在讲synchronized锁时提出的锁的概念。数据库作为用户共享的一个资源,如何保证数据并发访问一致性也是所有数据库必须解决的问题,如何加锁是数据库并发访问性能的一个重要因素。

听说微信搜索《Java鱼仔》会变更强哦!


本文收录于JavaStarter ,里面有我完整的Java系列文章,学习或面试都可以看看哦


(一)概述


我们把那些可能会被多个线程同时操作的资源称为临界资源,加锁的目的就是让这些临界资源在同一时刻只能有一个线程可以访问。这是当时在讲synchronized锁时提出的锁的概念。


数据库作为用户共享的一个资源,如何保证数据并发访问一致性也是所有数据库必须解决的问题,如何加锁是数据库并发访问性能的一个重要因素。


(二)关于数据库的锁


从加锁形式上分为乐观锁悲观锁


从对数据库操作的类型分为读锁(共享锁)写锁(排他锁)


读锁:多个读操作可以同时进行不会互相影响写锁:当前写操作没有完成前,会排斥其他的读锁和写锁


从数据操作粒度上可以分为表锁行锁


2.1 表锁


顾名思义,表锁就是锁住整张表。这种操作开销小,加锁快,不会出现死锁,但是锁的粒度大,并发度低。MyISAM引擎在操作数据时就会自动给数据加上表锁。


可以通过下面几个参数手动增加表锁:


lock table 表名 read(write)

查看表上加过的锁:


show open tables;

网络异常,图片无法展示
|


删除锁:


unlock tables;

加了读锁后,将限制写入;加了写锁之后,将限制读和写;


2.2 行锁


行锁就是锁住一行数据,这种做法开销大,加锁慢,会出现死锁。但是锁的粒度小,并发度最高。InnoDB支持行锁,同时InnoDB还支持事务


通过一个简单的例子来介绍一下行锁,我们开启两个session(navicat中就是开启两个查询窗口)去操作数据库,其中在第一个查询中修改数据,但是不提交:



begin;update test_innodb set name='javayz2'where id=1;

这个时候用另外一个查询窗口去修改同一行数据:


update test_innodb set name='javayz3'where id=1;

这时候这行更新语句会被一直阻塞,现在把第一个查询中修改的数据提交:


commit

你会发现第二个查询中的修改也立刻生效了: 查看结果,阻塞了30秒


网络异常,图片无法展示
|


注意:InnoDB的行锁是加在索引上的,如果索引失效或者修改的是非索引字段,行锁就会升级为表锁。


(三)Mysql的事务隔离级别


在讲事务隔离级别之前需要确保知道以下几个概念:


事务的ACID属性:原子性、一致性、隔离性、持久性


并发可能带来的问题:更新丢失、脏读、不可重复读、幻读


更新丢失:即多个事务同时更新一行数据,导致最后的更新覆盖了前面事务的更新。脏读:即事务A读取到了事务B已修改但是未提交的数据。 不可重复读:即事务A读取某些数据后再读取这些数据,发现这些数据发生了改变。因为事务A读取到了其他事务提交的数据,不符合隔离性。幻读:即事务A读取某些数据后按相同条件再读取发现多了新的数据,也是因为事务A读取到了其他事务新增的数据,不符合隔离性。


了解上面的概念之后,就可以知道Mysql的事务隔离级别了。事务隔离级别分为四种,下面通过表格的形式进行展示:



隔离级别
脏读

不可重复读

幻读
读未提交(read-uncommitted)
读已提交(read- committed) ×
可重复读(repeatable- read) × ×
可串行化(Serializable) × × ×

隔离级别越严格,并发带来的问题就越小,但是并发度也越低。


Mysql默认的事务隔离级别是可重复读。通过下列语句可查看


show VARIABLES like'tx_isolation'

通过下列语句修改事务隔离级别:


set tx_isolation='READ-COMMITTED'//READ-UNCOMMITTED、READ-COMMITTED、REPEATABLE-READ、SERIALIZABLE

(四)MVCC机制


当事务隔离级别设置为可重复读时,事务A执行select之后,如果事务B修改了数据,事务A再select依然是上一次的数据,但是如果用insert、update和delete时,采用的数据就会是事务B修改后的数据,


比如事务A第一次查询到的age是23、事务B将age加1,事务A第二次查询age依然是23;如果事务A将age加1,再查询就是25。


可重复读的隔离级别采用的是MVCC(multi-version concurrency control)的机制,它的实现机制比较复杂,我后续会出一篇专门的文章来讲一下。他所实现的目的是select操作读取的是历史的快照版本,insert、update、delete更新的是最新的版本


(五)可重复读的情况下如何解决幻读问题


Mysql默认的事务隔离级别是可重复读,但是没有解决幻读的问题,如果改为可串行化,并发度又太低,因此能否在可重复读的情况下解决幻读问题也是面试中比较常遇见的。

解决办法是用间隙锁。在其中一个事务中执行update语句时,增加一个范围,比如:



update test_innodb set name='javayz3'where id>1and id<10

id在1到10之间的数据就无法在其他事务中被插入或修改,自然也不会出现幻读的情况。


(六)关于死锁


在项目中偶尔会遇到死锁的情况,死锁的产生其实很简单,sessionA在等待sessionB的完成,sessionB在等待sessionA的完成,形成死循环。比如下面的更新语句:



A:begin;update test_innodb set name='aa'where id=1;//锁住id为1的行
B:begin;update test_innodb set name='bb'where id=2;//锁住id为2的行  
A:update test_innodb set name='aa'where id=2;B:update test_innodb set name='bb'where id=1;

最终A被B阻塞,B被A阻塞,从而导致了死锁。


网络异常,图片无法展示
|


Mysql中增加了死锁处理机制,对于死锁他会通过rollback解锁,但是有时遇到复杂的死锁情况就无法解锁。


(七)总结


整篇文章首先讲了Mysql的锁,Myisam使用表锁,InnoDB使用行锁。接着介绍了事务的基本原理,从而带出Mysql的事务隔离级别。简单介绍了MVCC机制,然后对于间隙锁、死锁进行讲解。掌握这些能让你在工作中或面试中遇到Mysql的问题有解决的思路。好了,这就是本期的所有内容了,我们下期再见!



相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
7天前
|
存储 关系型数据库 MySQL
从新手到高手:彻底掌握MySQL表死锁
通过本文的介绍,希望你能深入理解MySQL表死锁的概念、原因、检测方法及解决方案,并在实际开发中灵活应用这些知识,提升系统的稳定性和性能。
59 9
|
2月前
|
存储 SQL 关系型数据库
MySQL的事务隔离级别
【10月更文挑战第17天】MySQL的事务隔离级别
122 43
|
21天前
|
关系型数据库 MySQL
mysql事务特性
原子性:一个事务内的操作统一成功或失败 一致性:事务前后的数据总量不变 隔离性:事务与事务之间相互不影响 持久性:事务一旦提交发生的改变不可逆
|
1月前
|
SQL 算法 关系型数据库
面试:什么是死锁,如何避免或解决死锁;MySQL中的死锁现象,MySQL死锁如何解决
面试:什么是死锁,死锁产生的四个必要条件,如何避免或解决死锁;数据库锁,锁分类,控制事务;MySQL中的死锁现象,MySQL死锁如何解决
|
20天前
|
关系型数据库 MySQL 数据库
MySQL事务隔离级别及默认隔离级别的设置
在数据库系统中,事务隔离级别是一个关键的概念,它决定了事务在并发执行时如何相互隔离。MySQL提供了四种事务隔离级别,每种级别都解决了不同的并发问题。本文将详细介绍这些隔离级别以及MySQL的默认隔离级别。
|
2月前
|
关系型数据库 MySQL 数据库
一个 MySQL 数据库死锁的案例和解决方案
本文介绍了一个 MySQL 数据库死锁的案例和解决方案。
136 3
|
2月前
|
存储 关系型数据库 MySQL
优化 MySQL 的锁机制以提高并发性能
【10月更文挑战第16天】优化 MySQL 锁机制需要综合考虑多个因素,根据具体的应用场景和需求进行针对性的调整。通过不断地优化和改进,可以提高数据库的并发性能,提升系统的整体效率。
113 1
|
2月前
|
SQL 关系型数据库 MySQL
阿里面试:MYSQL 事务ACID,底层原理是什么? 具体是如何实现的?
尼恩,一位40岁的资深架构师,通过其丰富的经验和深厚的技術功底,为众多读者提供了宝贵的面试指导和技术分享。在他的读者交流群中,许多小伙伴获得了来自一线互联网企业的面试机会,并成功应对了诸如事务ACID特性实现、MVCC等相关面试题。尼恩特别整理了这些常见面试题的系统化解答,形成了《MVCC 学习圣经:一次穿透MYSQL MVCC》PDF文档,旨在帮助大家在面试中展示出扎实的技术功底,提高面试成功率。此外,他还编写了《尼恩Java面试宝典》等资料,涵盖了大量面试题和答案,帮助读者全面提升技术面试的表现。这些资料不仅内容详实,而且持续更新,是求职者备战技术面试的宝贵资源。
阿里面试:MYSQL 事务ACID,底层原理是什么? 具体是如何实现的?
|
2月前
|
存储 关系型数据库 MySQL
MySQL锁,锁的到底是什么?
【10月更文挑战第16天】MySQL 锁锁定的是与数据和资源相关的对象,其目的是为了保证数据的一致性、避免冲突,并在并发环境下合理协调事务或操作的执行。理解锁的对象和意义对于优化数据库性能、处理并发问题至关重要。
79 0
|
2月前
|
关系型数据库 MySQL 数据库
mysql锁详解
通过理解并合理运用MySQL中的锁机制,开发者可以有效管理数据库并发访问,平衡性能与数据一致性需求。更多关于MySQL锁的深入探讨和最佳实践,请参考专业的数据库管理资源[[深入MySQL锁机制详解
57 0