MySQL 的锁和事务隔离级别(上)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 我们的数据库一般会并发执行多个事务,多个事务可能会并发的对相同的一批数据进行增删改查操作,可能出现我们常说的脏写、脏读、不可重复读、幻读这些问题。这些问题的本质都是数据库的多事务并发问题,为了解决多事务并发问题,数据库设计了事务隔离机制、锁机制、MVCC多版本并发控制隔离机制。用了一整套机制来解决多事务并发问题,接下来,我们会深入讲解这些机制,让大家彻底理解数据库的内部执行原理。说明:本文中提到的概念和案例是基于 mysql-5.7.x 展开

事务以及其 ACID 属性


事务是由一组 SQL 语句组成的逻辑处理单元,事务具有 4 个属性,通常简称为事务的 ACID 属性。


  • 原子性(Atpmicity) : 事务是一个原子操作单元,其对数据的修改,要么全部执行成功,要么全部失败回滚,主要是体现事务操作层面。


  • 一致性(Consistent):在事务开始和完成时,数据都必须保持一致状态,着意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性。


  • 隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务不在受外部并发操作影响的 “独立” 环境执行。这意味着事务处理过中的中间状态对外部是不可见的。反之亦然。


  • 持久性(Durable): 事务处理完成之后,它对于数据的修改是永久性的, 即出现系统故障也能保持。


并发事务处理带来的问题


更新丢失(Lost Update)或脏写


当两个或者多个事务选择同一个行, 然后给予最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新的问题-最后的更新覆盖了其他事务所做的更新


脏读(Dirty Reads)


一个事务正在对一条数据做秀噶,但是这个事务在完成并提前之前,这条数据就已经就处于不一致的状态;这时,另一个事务也来取同一条记录,如果不加以控制,第二个事务读取了这些 “脏” 数据, 并且做进一步的处理,就会产生未提交的数据以来关系。这种现象叫做“脏”读。


简单理解:事务 A 读取到了事务 B 已经修改但是尚未提交的数据,并且在这个数据的基础上做了操作。此时如果 B 回滚了, A读取的数据就无效了,不符合一致性原理。


不可重复读(No-Repeatable Reads)


一个事务在读取某些数据后的某个事件,再次读取以前读取过的数据,却发现了读出的数据已经发生的改变、或某些数据已经被删除了,这种现象就叫做 “不可重复读”


简单理解: 事务 A 内部相同查询语句在不同的时刻读取出来的结果不一致,不符合隔离性


幻读(Phantom Reads)


一个事务按相同的时间查询重新读取以前检索过的数据, 却发现其他事务插入了满足查询条件的新数据,这种现象称为“幻读”。


简单理解:事务 A 读取到了事务 B 提交的新增数据,不符合隔离性。


事务隔离级别


“脏读” 、“不可重复读”、和 “幻读” 其实都是数据库一致性问题,必须由数据库提供一定的事务隔离机制来解决。


image.png


数据库的事务隔离越严格,并发带来的问题就越小,但是付出的代价也就越大,因为事务隔离实质上就是事务在一定程度上 “串行化” 进行,这显然与 “并发” 是矛盾的。同时,不同的应用对读一致性和事务隔离成都的要求也是不同的,比如许多应用对 “不可重复读” 和 “幻读” 并不敏感, 可能更关心数据并发访问的能力。


可以通过一下命令查询数据库的当前事务隔离级别:


mysql> show variables like 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.01 sec)


设置事务隔离级别:


set tx_isolation = 'REPEATABLE-READ';


MySQL 默认的事务隔离级别是可重复读,用 Spring 开发程序时,如果不设置隔离级别默认采用  MySQL 的隔离级别,如果 Spring  配置中已经设置的就用配置的隔离级别


MySQL 中的锁详解


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


在数据库中,除开传统的计算资源(如 CPU 、RAM、 I/O)的争用之外,数据也是一种需要用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的问题,锁冲突也是影响数据库并发访问性能的一个重要因素。


锁的分类


  • 性能上分为 乐观锁(用版本号对比来实现)和 悲观锁


  • 对数据操作类型分,可以分为 读锁和写锁(都属于悲观锁)


读锁(共享锁, S 锁 (Shared)): 针对同一份数据,多个读操作可以同时进行而不会互相影响。


写锁(排他锁, X 锁(eXclusive)): 当前写操作没有完成前,它会阻隔其他写锁和读锁。


  • 从数据操作的粒度分,分为表锁和行锁


表锁


每次操作会锁住整张表。 开销小,加锁快;不会出现死锁;锁定粒度打,发生锁冲突的概率最高,并发度最低;一般用在整张表数据迁移的场景。


基本操作


-- 创建表 SQL
create table `mylock` (
  `id` int(11) not null auto_increment,
  `name` varchar(20) default null,
  primary key(`id`)
) engine = Myisam default charset = utf8;
-- 插入数据
insert into `mylock` (`id`, `name`) values ('1' , 'a');
insert into `mylock` (`id`, `name`) values ('2' , 'b');
insert into `mylock` (`id`, `name`) values ('3' , 'c');
insert into `mylock` (`id`, `name`) values ('4' , 'd');


手动增加表锁


lock table 表名称 read(write), 表名称2 read(write)


查看表上加过的锁


show open tables;


删除表锁


unlock tables;


加读锁


mysql> lock table mylock read;
Query OK, 0 rows affected (0.00 sec)


当前 session 和其他 session 都可以读取该表


当前 session 中插入或者更新锁的表都会报错,其他 session 插入或更新则会等待。


mysql> insert into `mylock` (`id`, `name`) values ('5' , 'd');
ERROR 1099 (HY000): Table 'mylock' was locked with a READ lock and can't be updated


加写锁


mysql> lock table mylock write;
Query OK, 0 rows affected (0.00 sec)


当前的 session 对当前表增删改查都没有问题,其他 session 对该表所有的操作都被阻塞。


结论


  1. 对 MyISAM 表的读操作(加锁读),不会阻塞其他进程对同一个表的读请求,但是会阻塞对同一个表的写请求。只有当读锁匙放之后,才会执行其他进程的写操作。


  1. 对 MyISAM 表的写操作(加写锁),会阻塞其他进程对同一个表的读和写操作,只有当写锁释放后,才会执行其他进程的写操作。


行锁


每次操作都锁住一行数据。开销大(会涉及到表的查询、所以开销大),加锁慢;会出现死锁;锁定粒度最小,发生冲突的概率最低,并发高度最高。


InnoDB 与 MySIAM 的最大不同点


  • InnoDB 支持事务(Transaction)


  • InnoDB 支持行级锁


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
0
5
分享
相关文章
MySQL底层概述—9.ACID与事务
本文介绍了数据库事务的ACID特性(原子性、一致性、隔离性、持久性),以及事务控制的演进过程,包括排队、排它锁、读写锁和MVCC(多版本并发控制)。文章详细解释了每个特性的含义及其在MySQL中的实现方式,并探讨了事务隔离级别的类型及其实现机制。重点内容包括:ACID特性(原子性、持久性、隔离性和一致性的定义及其实现方式)、事务控制演进(从简单的全局排队到复杂的MVCC,逐步提升并发性能)、MVCC机制(通过undo log多版本链和Read View实现高效并发控制)、事务隔离级别(析了四种隔离级别(读未提交、读已提交、可重复读、可串行化)的特点及适用场景)、隔离级别与锁的关系。
MySQL底层概述—10.InnoDB锁机制
本文介绍了:锁概述、锁分类、全局锁实战、表级锁(偏读)实战、行级锁升级表级锁实战、间隙锁实战、临键锁实战、幻读演示和解决、行级锁(偏写)优化建议、乐观锁实战、行锁原理分析、死锁与解决方案
126 24
MySQL底层概述—10.InnoDB锁机制
京东面试:MySQL MVCC是如何实现的?如何通过MVCC实现读已提交、可重复读隔离级别的?
1.请解释什么是MVCC,它在数据库中的作用是什么? 2.在MySQL中,MVCC是如何实现的?请简述其工作原理。 3.MVCC是如何解决读-写和写-写冲突的? 4.在并发环境中,当多个事务同时读取同一行数据时,MVCC是如何保证每个事务看到的数据版本是一致的? 5.MVCC如何帮助提高数据库的并发性能?
京东面试:MySQL MVCC是如何实现的?如何通过MVCC实现读已提交、可重复读隔离级别的?
如何排查和解决PHP连接数据库MYSQL失败写锁的问题
通过本文的介绍,您可以系统地了解如何排查和解决PHP连接MySQL数据库失败及写锁问题。通过检查配置、确保服务启动、调整防火墙设置和用户权限,以及识别和解决长时间运行的事务和死锁问题,可以有效地保障应用的稳定运行。
161 25
MySQL事务日志-Undo Log工作原理分析
事务的持久性是交由Redo Log来保证,原子性则是交由Undo Log来保证。如果事务中的SQL执行到一半出现错误,需要把前面已经执行过的SQL撤销以达到原子性的目的,这个过程也叫做"回滚",所以Undo Log也叫回滚日志。
134 7
MySQL事务日志-Undo Log工作原理分析
MySQL进阶突击系列(06)MySQL有几种锁?| 别背答案,现场演示一下
本文详细解析了MySQL InnoDB存储引擎的锁机制,涵盖读锁、写锁、意向锁、记录锁、间隙锁和临键锁等8种锁类型。重点探讨了不同锁类型的加锁与释放方式,以及事务并发场景下的实战验证。通过具体示例,展示了在不同情况下锁的行为及其对事务的影响。文章还特别强调了锁的作用范围主要是索引,并解释了锁如何影响数据的读写操作。最后总结了并发事务中加锁规则,帮助读者深入理解MySQL的锁机制。
【MySQL基础篇】事务(事务操作、事务四大特性、并发事务问题、事务隔离级别)
事务是MySQL中一组不可分割的操作集合,确保所有操作要么全部成功,要么全部失败。本文利用SQL演示并总结了事务操作、事务四大特性、并发事务问题、事务隔离级别。
1321 2
【MySQL基础篇】事务(事务操作、事务四大特性、并发事务问题、事务隔离级别)
MySQL进阶突击系列(04)事务隔离级别、AICD、CAP、BASE原则一直搞不懂? | 看这篇就够了
本文详细介绍了数据库事务的四大特性(AICD原则),包括原子性、隔离性、一致性和持久性,并深入探讨了事务并发问题与隔离级别。同时,文章还讲解了分布式系统中的CAP理论及其不可能三角关系,以及BASE原则在分布式系统设计中的应用。通过具体案例和图解,帮助读者理解事务处理的核心概念和最佳实践,为应对相关技术面试提供了全面的知识准备。
MySQL的事务隔离级别
【10月更文挑战第17天】MySQL的事务隔离级别
173 43
mysql事务特性
原子性:一个事务内的操作统一成功或失败 一致性:事务前后的数据总量不变 隔离性:事务与事务之间相互不影响 持久性:事务一旦提交发生的改变不可逆