Mysql事务

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 RDS MySQL,高可用系列 2核4GB
简介: Mysql事务

目的

事务将数据库从一种一致性状态转换为另一种一致性状态;

组成

事务可由一条非常简单的SQL语句组成,也可以由一组复杂的SQL语句组成;

特征

在数据库提交事务时,可以确保要么所有修改都已经保存,要么所有修改都不保存;

事务是访问并更新数据库各种数据项的一个程序执行单元。

在 MySQL innodb 下,每一条语句都是事务;可以通过 set autocommit = 0; 设置当前会话手 动提交;

事务控制语句

-- 显示开启事务
START TRANSACTION | BEGIN
-- 提交事务,并使得已对数据库做的所有修改持久化
COMMIT
-- 回滚事务,结束用户的事务,并撤销正在进行的所有未提交的修改
ROLLBACK
-- 创建一个保存点,一个事务可以有多个保存点
SAVEPOINT identifier
-- 删除一个保存点
RELEASE SAVEPOINT identifier
-- 事务回滚到保存点
ROLLBACK TO [SAVEPOINT] identifier

ACID特性

原子性(A)

事务的隔离性要求每个读写事务的对象对其他事务的操作对象能相互分离,也就是事务提交前对其他事务都不可见;通过 MVCC 和 锁来实现;MVCC 是多版本并发控制,主要解决一致性非锁定读,通过记录和获取行版本,而不是使用锁来限制读操作,从而实现高效并发读性能。锁用来处理 并发 DML 操作;数据库中提供粒度锁的策略,针对表(聚集索引B+树)、页(聚集索引B+树叶 子节点)、行(叶子节点当中某一段记录行)三种粒度加锁;

隔离性(I)

事务的隔离性要求每个读写事务的对象对其他事务的操作对象能相互分离,也就是事务提交前对其 他事务都不可见;通过 MVCC 和 锁来实现;MVCC 时多版本并发控制,主要解决一致性非锁定 读,通过记录和获取行版本,而不是使用锁来限制读操作,从而实现高效并发读性能。锁用来处理 并发 DML 操作;数据库中提供粒度锁的策略,针对表(聚集索引B+树)、页(聚集索引B+树叶 子节点)、行(叶子节点当中某一段记录行)三种粒度加锁;

持久性(D)

事务提交后,事务DML操作将会持久化(写入redolog磁盘文件 哪一个页 页偏移值 具体数据); 即使发生宕机等故障,数据库也能将数据恢复。redolog记录的是物理日志;

一致性(C)

一致性指事务将数据库从一种一致性状态转变为下一种一致性的状态,在事务执行前后,数据库完 整性约束没有被破坏。例如:一个表的姓名是唯一键,如果一个事务对姓名进行修改,但是在事务 提交或事务回滚后,表中的姓名变得不唯一了,这样就破坏了一致性;一致性由原子性、隔离性以 及持久性共同来维护的。

事务并发异常

脏读

事务(A)可以读到另外一个事务(B)中未提交的数据;也就是事务A读到脏数据;在读写分离的场景下,可以将slave节点设置为 READ UNCOMMITTED;此时脏读不影响,在slave上查询并不需要特别精准的返回值。

不可重复读

事务(A) 可以读到另外一个事务(B)中提交的数据;通常发生在一个事务中两次读到的数据是不 一样的情况;不可重复读在隔离级别 READ COMMITTED 存在。一般而言,不可重复读的问题是可以接受的,因为读到已经提交的数据,一般不会带来很大的问题,所以很多厂商(如Oracle、 SQL Server)默认隔离级别就是READ COMMITTED;

幻读

事务中一次读操作不能支撑接下来的业务逻辑;通常发生在一个事务中一次读判断接下来写操作失败的情况;例如:以name为唯一键的表,一个事务中查询 select * from t where name = 'mark'; 不存在,接下来 insert into t(name) values ('mark'); 出现错误,此时另外一个 事务也执行了 insert 操作;幻读在隔离级别 REPEATABLE READ 及以下存在命令;但是可以在 REPEATABLE READ 级别下通过读加锁(使用next-key locking)解决;

解决

隔离级别

ISO和ANIS SQL标准制定了四种事务隔离级别的标准,各数据库厂商在正确性和性能之间做了妥 协,并没有严格遵循这些标准;MySQL innodb默认支持的隔离级别是 REPEATABLE READ;

READ UNCOMMITTED

读未提交;该级别下读不加锁,写加排他锁,写锁在事务提交或回滚后释放锁;

READ COMMITTED

读已提交;从该级别后支持 MVCC (多版本并发控制),也就是提供一致性非锁定读;此时读取操作 读取历史快照数据;该隔离级别下读取历史版本的最新数据,所以读取的是已提交的数据;

REPEATABLE READ

可重复读;该级别下也支持 MVCC,此时读取操作读取事务开始时的版本数据;'

SERIALIZABLE

可串行化;该级别下给读加了共享锁;所以事务都是串行化的执行;此时隔离级别最严苛;

不同隔离级别下并发异常

命令

-- 设置隔离级别
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- 或者采用下面的方式设置隔离级别
SET @@tx_isolation = 'REPEATABLE READ';
SET @@global.tx_isolation = 'REPEATABLE READ';
-- 查看全局隔离级别
SELECT @@global.tx_isolation;
-- 查看当前会话隔离级别
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;
-- 手动给读加 S 锁
SELECT ... LOCK IN SHARE MODE;
-- 手动给读加 X 锁
SELECT ... FOR UPDATE;
-- 查看当前锁信息
SELECT * FROM information_schema.innodb_locks;

锁机制用于管理对共享资源的并发访问;用来实现事务的隔离级别 ;

锁类型

共享锁和排他锁都是行级锁;MySQL当中事务采用的是粒度锁;针对表(B+树)、页(B+树叶子 节点)、行(B+树叶子节点当中某一段记录行)三种粒度加锁;

意向共享锁和意向排他锁都是表级别的锁;

共享锁(S)

事务读操作加的锁;对某一行加锁;

在 SERIALIZABLE 隔离级别下,默认帮读操作加共享锁;

在 REPEATABLE READ 隔离级别下,需手动加共享锁,可解决幻读问题;

在 READ COMMITTED 隔离级别下,没必要加共享锁,采用的是 MVCC;

在 READ UNCOMMITTED 隔离级别下,既没有加锁也没有使用 MVCC;

排他锁(X)

事务删除或更新加的锁;对某一行加锁;

在4种隔离级别下,都添加了排他锁,事务提交或事务回滚后释放锁;

意向共享锁(IS)

对一张表中某几行加的共享锁;

意向排他锁(IX)

对一张表中某几行加的排他锁;

锁的兼容性

由于innodb支持的是行级别的锁,意向锁并不会阻塞除了全表扫描以外的任何请求; 意向锁之间是互相兼容的; IX 对共享锁和排他锁都不兼容; IS 只对排他锁不兼容; 当想为某一行添加 S 锁,先自动为所在的页和表添加意向锁 IS,再为该行添加 S 锁; 当想为某一行添加 X 锁,先自动为所在的页和表添加意向锁 IX,再为该行添加 X 锁;

锁算法

Record Lock

记录锁,单个行记录上的锁;

Gap Lock

间隙锁,锁定一个范围,但不包含记录本身;全开区间;REPEATABLE READ级别及以上支持间隙 锁; 如果 REPEATABLE READ 修改 innodb_locks_unsafe_for_binlog = 0 ,那么隔离级别相当于 退化为 READ COMMITTED;

-- 查看是否支持间隙锁,默认支持,也就是 innodb_locks_unsafe_for_binlog = 0;

SELECT @@innodb_locks_unsafe_for_binlog;

Next-Key Lock

记录锁+间隙锁,锁定一个范围,并且锁住记录本身;左开右闭区间;

Insert Intention Lock

插入意向锁,insert操作的时候产生;在多事务同时写入不同数据至同一索引间隙的时候,并不需要等待其他事务完成,不会发生锁等待。

假设有一个记录索引包含键值4和7,两个不同的事务分别插入5和6,每个事务都会产生一个加在 4-7之间的插入意向锁,获取在插入行上的排它锁,但是不会被互相锁住,因为数据行并不冲突。

锁兼容

横向:表示已经持有的锁;纵向:表示正在请求的锁;

AUTO-INC Lock

自增锁,是一种特殊的表级锁,发生在 AUTO_INCREMENT 约束下的插入操作;采用的一种特殊 的表锁机制;完成对自增长值插入的SQL语句后立即释放;在大数据量的插入会影响插入性能,因 为另一个事务中的插入会被阻塞;从MySQL 5.1.22开始提供一种轻量级互斥量的自增长实现机 制,该机制提高了自增长值插入的性能;

锁的对象

行级锁是针对表的索引加锁;索引包括聚集索引和辅助索引;

表级锁是针对页或表进行加锁;

考虑 InnoDB 在 read committed 和 repeatable read 级别下锁的情况;

示例1

select * from t where id = 5 for update; lock in share mode
-- id 为主键 Read committed 隔离级别
-- 在主键 id = 5 行上加 X 锁
-- id 是唯一索引 Read committed 隔离级别
-- 在唯一索引id=5行上加X锁,在主键索引上对应行加X锁
-- id 是非唯一索引 Read committed 隔离级别
-- 在非唯一索引上所有id=5行加上X锁,对应的主键索引列加上X锁
-- id 不是索引 Read committed 隔离级别
-- 在聚集索引上扫描,所有行上加X锁,此处有个优化,不满足的行在加锁后,判断不满足即可释放锁
-- id 为主键 repeatable read 隔离级别
-- 在主键id=5行上加X锁
-- id 是唯一索引 repeatable read 隔离级别
-- 在唯一索引id=5行上加X锁,在主键索引上对应列加X锁
-- id 是非唯一索引 repeatable read 隔离级别
-- 在非唯一索引上查找id=5行,找到则加上X锁和GAP锁,然后对应的聚集索引加上X锁; 没有找到则
加上GAP锁
-- id 不是索引 repeatable read 隔离级别
-- 在聚集索引上扫描,所有行加上X锁和GAP锁

示例2

-- 在 RR 下
-- 不加任何锁
select .. from t;
-- 扫描到任何索引行上加S锁(next-key lock) 在聚集索引上加X锁
select...from t lock in share mode;
-- 扫描到任何索引行上加X锁(next-key lock) 在聚集索引上加X锁
select..from t for update;
-- 扫描到任何索引行上加X锁(next-key lock) 在聚集索引上加X锁
update..where condition
delete from..where condition
-- 如果是间隙插入,先添加 insert intention lock, 后在该行上添加X锁;
-- 如果是递增插入,添加 auto-inc lock 或者 轻量级的互斥锁;
insert into ...

MVCC

多版本并发控制;用来实现一致性的非锁定读;非锁定读是指不需要等待访问的行上X锁的释放; 在 read committed 和 repeatable read下,innodb使用MVCC;然后对于快照数据的定义不同; 在 read committed 隔离级别下,对于快照数据总是读取被锁定行的最新一份快照数据;而在 repeatable read 隔离级别下,对于快照数据总是读取事务开始时的行数据版本;

思考:为什么读取快照数据不需要上锁? 因为没有事务需要对历史的数据进行修改操作;

当这个sql语句访问到X locked的时候不会阻塞  而是会访问快照数据,然后接着向后访问。

示例

redo

redo 日志用来实现事务的持久性;内存中包含 redo log buffer,磁盘中包含 redo log file;

当事务提交时,必须先将该事务的所有日志写入到重做日志文件进行持久化,待事务的commit操 作完成才完成了事务的提交;

redo log 顺序写,记录的是对每个页的修改(页、页偏移量、以及修改的内容);在数据库运行 时不需要对 redo log 的文件进行读取操作;只有发生宕机的时候,才会拿redo log进行恢复;

undo

undo 日志用来帮助事务回滚以及MVCC的功能;存储在共享表空间中;undo 是逻辑日志,回滚 时将数据库逻辑地恢复到原来的样子,根据 undo log 的记录,做之前的逆运算;比如事务中有 insert 操作,那么执行 delete 操作;对于 update 操作执行相反的 update 操作; 同时 undo 日志记录行的版本信息,用于处理 MVCC 功能;

 

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
1月前
|
SQL 关系型数据库 MySQL
MySQL锁机制:并发控制与事务隔离
本文深入解析了MySQL的锁机制与事务隔离级别,涵盖锁类型、兼容性、死锁处理及性能优化策略,助你掌握高并发场景下的数据库并发控制核心技巧。
|
2月前
|
存储 监控 Oracle
MySQL事务
MySQL事务具有ACID特性,包括原子性、一致性、隔离性和持久性。其默认隔离级别为可重复读,通过MVCC和间隙锁解决幻读问题,确保事务间数据的一致性和并发性。
MySQL事务
|
3月前
|
存储 SQL 关系型数据库
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
|
6天前
|
关系型数据库 MySQL 数据库
【赵渝强老师】MySQL的事务隔离级别
数据库并发访问时易引发数据不一致问题。如客户端读取到未提交的事务数据,可能导致“脏读”。MySQL通过四种事务隔离级别(读未提交、读已提交、可重复读、可序列化)控制并发行为,默认为“可重复读”,以平衡性能与数据一致性。
101 0
|
29天前
|
关系型数据库 MySQL 数据库
MySql事务以及事务的四大特性
事务是数据库操作的基本单元,具有ACID四大特性:原子性、一致性、隔离性、持久性。它确保数据的正确性与完整性。并发事务可能引发脏读、不可重复读、幻读等问题,数据库通过不同隔离级别(如读未提交、读已提交、可重复读、串行化)加以解决。MySQL默认使用可重复读级别。高隔离级别虽能更好处理并发问题,但会降低性能。
|
3月前
|
安全 关系型数据库 MySQL
mysql事务隔离级别
事务隔离级别用于解决脏读、不可重复读和幻读问题。不同级别在安全与性能间权衡,如SERIALIZABLE最安全但性能差,READ_UNCOMMITTED性能高但易导致数据不一致。了解各级别特性有助于合理选择以平衡并发性与数据一致性需求。
156 1
|
10月前
|
SQL 安全 关系型数据库
【MySQL基础篇】事务(事务操作、事务四大特性、并发事务问题、事务隔离级别)
事务是MySQL中一组不可分割的操作集合,确保所有操作要么全部成功,要么全部失败。本文利用SQL演示并总结了事务操作、事务四大特性、并发事务问题、事务隔离级别。
4339 56
【MySQL基础篇】事务(事务操作、事务四大特性、并发事务问题、事务隔离级别)
|
9月前
|
SQL 关系型数据库 MySQL
MySQL事务日志-Undo Log工作原理分析
事务的持久性是交由Redo Log来保证,原子性则是交由Undo Log来保证。如果事务中的SQL执行到一半出现错误,需要把前面已经执行过的SQL撤销以达到原子性的目的,这个过程也叫做"回滚",所以Undo Log也叫回滚日志。
384 7
MySQL事务日志-Undo Log工作原理分析
|
12月前
|
存储 SQL 关系型数据库
MySQL的事务隔离级别
【10月更文挑战第17天】MySQL的事务隔离级别
272 43
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
2219 14
MySQL事务日志-Redo Log工作原理分析

推荐镜像

更多