当前位置: 首页 > news >正文

MYSQL事务原理分析(三)

目录

一. 事务

 1. 事物的定义和必要性

 2. 事务的基本语句

  3. ACID 特性

 4. Undo Log 与 Redo Log

 Undo Log(回滚日志)

 Redo Log(重做日志)

二. 事务隔离级别

 1. 并发问题与隔离级别的关系

 2. 四种隔离级别

 3. 隔离级别操作命令

三.  MVCC(多版本并发控制)(⭐⭐⭐⭐⭐)

 1. MVCC 核心原理

 2. Read View

可见性判断:

3. 不同隔离级别下 MVCC 行为

 4. 快照读 VS 当前读

四.MySQL 锁机制

 1. 锁的粒度

  2. 常见锁类型

        全局锁

         表级锁

        行级锁

 3. 锁算法

记录锁(Record Lock)

间隙锁(Gap Lock)

临键锁(Next-Key Lock)

五.死锁

 1.死锁的概念与原因

  2. 如何避免死锁


一. 事务

 1. 事物的定义和必要性

        在数据库多用户高并发访问场景中,多个连接同时操作数据可能导致数据不一致。

        事务(Transaction)是数据库管理系统提供的一种机制,用于确保一组数据库操作要么全部成功执行,要么全部失败回滚,从而保证数据的完整性和一致性。

 2. 事务的基本语句

        MySQL 提供以下事务控制语句:

--显式开启事务
START TRANSTACTION;    --提交事务,持久化所有更改
COMMIT;--回滚事务,撤销未提交的修改
ROLLBACK;--创建保存点
SAVEPOINT identifier;--删除保存点
RELEASE SAVEPOINT identifier;--回滚到指定保存点
ROLLBACK TO SAVEPOINT identifier;
  3. ACID 特性
特性含义实现机制
原子性(Atomicity)事务中所有操作要么全部完成,要么全部不完成,不可分割通过 Undo log 实现回滚能力
一致性(Consistency)事务执行前后,数据库的完整性约束没有被破坏,数据保持一致依赖约束,外键等规则强制实现
隔离性(Isolation)多个事务并发执行时,事物之间不互相影响通过 MVCC 和锁机制实现
持久性(Durability)一旦事务提交,其对数据库的修改应该永久保存,即使系统崩溃基于 Redo log 实现崩溃恢复
 4. Undo Log 与 Redo Log
 Undo Log(回滚日志)
  • 作用:记录数据修改前的状态,用于事务回滚或 MVCC 的快照读
  • 特点:InnoDB 引擎特有,保证事务原子性 
 Redo Log(重做日志)
  • 作用:记录事务对数据页的修改,确保事务持久化
  • 特点:顺序写入,高效持久化,崩溃回复时用于重建数据

二. 事务隔离级别

 1. 并发问题与隔离级别的关系

多事务并发执行时,若没有适当的隔离机制,可能会出现以下问题:

  • 脏读:一个事务读取了另一个未提交事务修改的数据
  • 不可重复读:同一事务多次读取同一数据返回不同结果
  • 幻读:同一事务中,两次查询的结果集不一致
 2. 四种隔离级别
隔离级别脏读不可重复读幻读
读未提交(READ UNCOMMITED)可能可能可能
读已提交(READ COMMITED)不可能可能可能
可重复读(REPEATABLE READ)(MYSQL默认)不可能不可能可能
可串行化(SERIALIZABLE)不可能不可能不可能
 3. 隔离级别操作命令
-- 查看当前会话隔离级别
SELECT @@tx_isolation;-- 设置当前会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;-- 设置全局隔离级别(需重启或新连接生效)
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

三.  MVCC(多版本并发控制)(⭐⭐⭐⭐⭐)

 1. MVCC 核心原理

MVCC 是 InnoDB 实现高并发的关键技术,通过保存数据的多个版本,使得读写操作可以并发执行而互不阻塞,核心机制包括:

  • Undo Log :存储数据的历史版本
  • Read View :事务执行期间的快照,用于判断可见性

Undo Log 会随着事务提交后被清除(并不是永久保存) 

 2. Read View
属性作用
m_ids当前活跃的事务ID集合(还未提交的事务)
min_trx_id当前活跃事务中最小的事务ID
max_trx_id下一个即将分配的事务ID(并不一定是最大的事务ID)
creat_trx_id每一行数据的创建事务ID(trx_id字段)
可见性判断:
  1. trx_id < min_trx_id:说明该记录在创建read view 之前已经提交,所以对当前事务可见;
  2. trx_id >= max_trx_id:说明该记录是在创建read view 之后启动事务生成的,所以对当前事务不可见
  3. min_trx_id <= trx_id < max_trx_id:此时需要判断是否在 m_ids 集合中;
    1. 在列表中;生成该版本记录的事务仍处于活跃状态,该版本记录对当前事务不可见;
    2. 不在列表中;生成该版本记录的事务已经提交,该版本记录对当前事务可见;
3. 不同隔离级别下 MVCC 行为
隔离级别Read View 创建时机说明
READ COMMITED(读已提交)每次查询时创建新的 Read View可以读取其他事务已提交的修改
REPEATABLE READ(可重复读)事务开始时创建唯一的 Read View事务内查询结果保持一致
 4. 快照读 VS 当前读
类型说明案例
快照读(Snapshot Read)非锁定读,走MVCC快照SELECT * FROM table WHERE id = 1;
当前读(Current Read)加锁读,拿最新版本SELECT * FROM table WHERE id = 1 FOR UPDATE;

四.MySQL 锁机制

 1. 锁的粒度

MySQL 支持多种锁粒度

  • 表级锁:对整张表加锁,开销小但并发度低
  • 页级锁:对数据页加锁(主要用于 MyISAM 索引缓存,InnoDB 不使用)
  • 行级锁:对记录加锁,开销大但并发度高(InnoDB 支持)
  2. 常见锁类型
        全局锁
-- 全局只读锁(用于一致性备份)
FLUSH TABLES WITH READ LOCK;-- 全局写锁(用于表结构变更)
LOCK TABLES table_name WRITE;
  • 全局锁会锁定整个数据库,其他事务无法进行读写操作。
         表级锁
  • 意向共享锁(IS):事务打算对表中某些记录加共享锁
  • 意向排他锁(IX):事务打算对表中某些记录加排他锁

 意向锁不会阻塞其他意向锁,但会与表级的共享或排他锁发生冲突

        行级锁
  • 共享锁(S Lock):允许其他事务读取同一行,但阻止写入
  • 排他锁(X Lock):阻止其他事务获取任何类型的锁

InnoDB 使用MVCC + 行锁结合实现高并发控制

 3. 锁算法

InnoDB 主要实现了三种行锁算法

记录锁(Record Lock)

锁定单个索引记录,防止其他事务修改或删除。

SELECT * FROM user WHERE id = 5 FOR UPDATE;//若 id 有索引,这条语句会对 id=5 的那一条记录加记录锁
间隙锁(Gap Lock)

锁定索引记录之间的间隙,防止插入新纪录,避免幻读

SELECT * FROM user WHERE id < 5 FOR UPDATE;//会锁住 (5, ∞) 范围的间隙,阻止插入 id > 5 的新记录。
临键锁(Next-Key Lock)

记录锁与间隙锁的组合,锁定记录及其前面的间隙,是InnoDB 默认的行锁算法

SELECT * FROM user WHERE id BETWEEN 5 AND 10 FOR UPDATE;

五.死锁

 1.死锁的概念与原因

        死锁是指两个或多个事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象。常见场景包括:

  • 相反加锁顺序:事务 A 锁定资源 X 并请求资源 Y,同时事务 B 锁定资源 Y 并请求资源 X
  • 锁冲突:高并发环境下,多个事务频繁争夺相同资源
  2. 如何避免死锁
方法说明
统一加锁顺序用一致的顺序加锁,避免环形等待
控制事务粒度与范围缩小每个事务锁定的数据范围和执行时间
减少范围查询减少 BRTWEEN/</> 查询,避免间隙锁干扰
合理设置索引避免全表扫描导致不必要的行锁或表锁
设置死锁重试机制捕获错误码 1213,程序自动重试一次事务操作
适当降低隔离级别如使用 Read Committed 替代 Repeatable Read(锁冲突)

相关文章:

  • nginx配置sse流传输问题:直到所有内容返回后才往下传输
  • java反序列化commons-collections链6
  • LVGL(lv_switch开关)
  • 输出重定向
  • 位运算题目:黑板异或游戏
  • 牛客周赛 Round 92
  • ComfyUI的K采样器参数详解:实战演示
  • Python 实现失败重试功能的几种方法
  • 数据同步DataX任务在线演示
  • 部署Superset BI(六)Superset 的主机安装
  • LVGL(lv_list列表控件)
  • Linux服务器管理面板新选择:mdserver-web深度解析与使用指南
  • sqlilab-Less-18
  • CHIP第四次作业
  • Python笔记:windows下永久配置pip镜像源
  • 5.10-套接字通信 - C++
  • 算法题(145):货仓选址
  • SpringAI框架中的RAG模块详解及应用示例
  • Halcon案例(一):C#联合Halcon识别路由器上的散热孔
  • 定时器设计
  • 法治课|争议中的“行人安全距离”于法无据,考量“注意义务”才更合理
  • 外交部:正确认识和对待历史是检验日本能否恪守和平发展承诺的重要标准
  • 习近平出席中拉论坛第四届部长级会议开幕式并发表主旨讲话
  • 北洋“修约外交”的台前幕后——民国条约研究会档案探研
  • 张笑宇:物质极大丰富之后,我们该怎么办?
  • 技术派|巴基斯坦导弹:让印度保持克制的“定海神针”?