MySQL 事务全面解析

事务是数据库系统中保证数据一致性的核心机制,MySQL 的事务功能主要围绕 InnoDB 存储引擎实现。以下从基础概念到高级特性全面解析 MySQL 事务。

一、事务基础

1. ACID 特性

特性

描述

MySQL 实现机制

原子性 (Atomicity)

事务是不可分割的工作单位

undo log 回滚

一致性 (Consistency)

数据库从一个一致状态变到另一个一致状态

约束、触发器

隔离性 (Isolation)

事务执行不受其他事务干扰

锁机制/MVCC

持久性 (Durability)

事务提交后永久生效

redo log 持久化

2. 事务控制语句

START TRANSACTION;  -- 或 BEGIN
INSERT INTO accounts VALUES (1, 1000);
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;  -- 提交-- 出错时回滚
ROLLBACK;

二、事务隔离级别

1. 四种隔离级别

隔离级别

脏读

不可重复读

幻读

实现方式

读未提交 (READ UNCOMMITTED)

可能

可能

可能

无锁

读已提交 (READ COMMITTED)

不可能

可能

可能

记录锁

可重复读 (REPEATABLE READ)

不可能

不可能

可能(InnoDB避免)

MVCC+间隙锁

串行化 (SERIALIZABLE)

不可能

不可能

不可能

全表锁

2. 设置隔离级别

-- 查看当前隔离级别
SELECT @@transaction_isolation;-- 设置全局/会话级别
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

事务实现机制

1. MVCC (多版本并发控制)

核心组件

  • 隐藏字段:DB_TRX_ID(事务ID)、DB_ROLL_PTR(回滚指针)、DB_ROW_ID(行ID)
  • ReadView:事务快照,决定可见哪些版本

工作流程

  1. SELECT 时通过 ReadView 判断数据版本可见性
  2. UPDATE/DELETE 时创建新版本(写undo log)
  3. 旧版本通过回滚指针形成版本链
2. 锁机制
(1) 锁类型

锁类型

描述

共享锁(S锁)

读锁,多个事务可同时持有

排他锁(X锁)

写锁,独占资源

意向锁

表级锁,快速判断表中是否有行锁

(2) 行锁算法

锁算法

描述

解决什么问题

记录锁

锁定索引记录

避免写冲突

间隙锁

锁定索引记录间隙

防止幻读

临键锁

记录锁+间隙锁组合

InnoDB默认

3. 日志系统

日志类型

作用

特点

redo log

保证事务持久性

循环写入、物理日志

undo log

实现事务回滚

逻辑日志、形成版本链

binlog

主从复制

逻辑日志、追加写入

三、MySQL 事务传播机制详解

事务传播机制主要出现在 Spring 等框架管理的事务中,用于定义多个事务方法相互调用时事务应该如何传播。虽然原生 MySQL 不直接支持传播行为的概念,但在应用层通过框架可以实现。以下是全面解析:

一、Spring 事务传播类型

Spring 定义了 7 种传播行为(通过 @Transactional(propagation=...) 指定):

传播行为

说明

适用场景

REQUIRED (默认)

如果当前存在事务,则加入该事务;否则新建一个事务

大多数业务场景

SUPPORTS

如果当前存在事务,则加入该事务;否则以非事务方式执行

查询方法

MANDATORY

必须在一个已有的事务中执行,否则抛出异常

强制要求事务的方法

REQUIRES_NEW

新建事务,如果当前存在事务,则挂起当前事务

独立事务操作(如日志记录)

NOT_SUPPORTED

以非事务方式执行,如果当前存在事务,则挂起当前事务

不涉及数据一致性的操作

NEVER

以非事务方式执行,如果当前存在事务,则抛出异常

禁止事务的方法

NESTED

如果当前存在事务,则在嵌套事务内执行;否则新建事务

部分可回滚的子操作

二、传播机制工作原理

1. REQUIRED (默认)
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {methodB();  // 加入methodA的事务
}@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {// 操作数据库
}
  • 如果 methodB 抛出异常,methodA 也会回滚
2. REQUIRES_NEW
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {methodB();  // 挂起methodA的事务,新建独立事务// 即使methodB回滚,methodA可能继续执行
}@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {// 独立事务
}
3. NESTED (嵌套事务)
@Transactional
public void methodA() {try {methodB();  // 在嵌套事务中执行} catch (Exception e) {// 只回滚methodB的操作}// methodA的其他操作
}@Transactional(propagation = Propagation.NESTED)
public void methodB() {// 嵌套事务
}
  • 嵌套事务使用保存点(SAVEPOINT)实现部分回滚
  • 外层事务提交时,嵌套事务才会真正提交

三、MySQL 底层实现对应

虽然传播行为是应用层概念,但对应到 MySQL 底层机制:

传播行为

MySQL 对应机制

REQUIRED

共用同一个数据库连接/事务

REQUIRES_NEW

新建数据库连接和事务

NESTED

使用 SAVEPOINT 实现

NOT_SUPPORTED

自动提交模式(auto-commit=1)

四、传播机制实战案例

案例1:日志记录需要独立事务
public void placeOrder(Order order) {// 主业务逻辑orderDao.save(order);  // REQUIRED传播try {logService.saveLog(order);  // 日志需要独立事务} catch (Exception e) {// 日志失败不影响主业务}
}@Service
public class LogService {@Transactional(propagation = Propagation.REQUIRES_NEW)public void saveLog(Order order) {// 日志记录}
}
案例2:部分操作可回滚
@Transactional
public void processBatch(List<Item> items) {for (Item item : items) {try {processItem(item);  // 单个item失败不影响其他} catch (Exception e) {// 记录错误继续处理}}
}@Transactional(propagation = Propagation.NESTED)
public void processItem(Item item) {// 处理单个item
}

五、传播机制选择建议

  1. 默认选择 REQUIRED
    适用于大多数需要事务的业务方法
  2. REQUIRES_NEW 使用场景
    • 审计日志记录
    • 次要业务(如积分变更)不阻塞主业务
    • 需要独立提交/回滚的操作
  1. NESTED 适用场景
    • 批量处理中的单个项目处理
    • 可部分回滚的业务流程
  1. 避免滥用 NOT_SUPPORTED/NEVER
    除非明确知道不需要事务,否则可能破坏数据一致性

六、常见问题与解决方案

问题1:事务不生效

原因

  • 方法非 public
  • 自调用(同一个类内方法调用)
  • 异常被捕获未抛出

解决

// 正确示例
@Transactional
public void methodA() {this.methodB();  // 仍然不生效!需通过代理对象调用
}// 解决方案1:注入自身代理
@Autowired 
private MyService self;  // 通过self调用// 解决方案2:使用AopContext
((MyService) AopContext.currentProxy()).methodB();
问题2:嵌套事务回滚异常

现象
NESTED 传播的方法抛出异常,但外层事务未回滚

原因
外层方法捕获了异常未继续抛出

解决

@Transactional
public void outer() {try {inner();  // NESTED传播} catch (Exception e) {// 需要手动标记回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();throw e;}
}

七、性能考量

  1. REQUIRES_NEW 开销
    • 需要新建数据库连接
    • 适合低频操作(如日志)
  1. NESTED 与 MySQL
    • 依赖 MySQL 的 SAVEPOINT 支持
    • 比 REQUIRES_NEW 轻量

最佳实践

// 高频调用方法避免REQUIRES_NEW
@Transactional(propagation = Propagation.SUPPORTS)
public Data getData() {// 只读查询
}

通过合理选择传播机制,可以构建出既保证数据一致性又具备良好性能的事务体系。建议结合业务场景进行针对性设计。

四、事务实战应用

1. 转账事务示例

START TRANSACTION;
-- 检查账户存在
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
-- 扣款
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- 存款
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

2. 死锁处理

死锁场景

-- 事务1
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;-- 事务2 (相反顺序)
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

解决方案

  1. 统一资源访问顺序
  2. 设置锁等待超时

SET innodb_lock_wait_timeout = 30; -- 单位秒

  1. 自动检测回滚

SET innodb_deadlock_detect = ON; -- 默认开启

五、高级事务特性

1. 保存点(SAVEPOINT)

START TRANSACTION;
INSERT INTO orders VALUES(1, '2023-01-01', 100);
SAVEPOINT sp1;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- 可部分回滚
ROLLBACK TO SAVEPOINT sp1;
COMMIT;

2. 分布式事务(XA)

-- 协调者
XA START 'transaction_id';
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
XA END 'transaction_id';
XA PREPARE 'transaction_id';
XA COMMIT 'transaction_id';  -- 或 XA ROLLBACK

3. 事务性能优化

  • 短事务:减少锁持有时间
  • 合适隔离级别:避免过度使用SERIALIZABLE
  • 索引优化:减少锁定范围
  • 批量操作:减少事务次数

六、事务监控与问题排查

1. 查看当前事务

-- 查看运行中的事务
SELECT * FROM information_schema.INNODB_TRX;-- 查看锁等待
SELECT * FROM performance_schema.events_waits_current;

2. 长事务排查

-- 查找运行超过60s的事务
SELECT * FROM information_schema.INNODB_TRX 
WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 60;

3. 死锁日志分析

-- 查看最近死锁信息
SHOW ENGINE INNODB STATUS\G
-- 重点关注 "LATEST DETECTED DEADLOCK" 部分

七、InnoDB 事务参数配置

# 核心参数
innodb_flush_log_at_trx_commit = 1  # 1=最安全, 2=折衷, 0=性能
sync_binlog = 1                     # 控制binlog刷盘
transaction-isolation = REPEATABLE-READ  # 默认隔离级别# 性能相关
innodb_lock_wait_timeout = 50       # 锁等待超时(秒)
innodb_rollback_on_timeout = ON     # 超时自动回滚
innodb_deadlock_detect = ON         # 死锁检测

最佳实践建议

  1. 事务设计原则
    • 保持事务短小精悍
    • 避免在事务中进行网络I/O
    • 合理设置隔离级别
  1. 锁优化建议
    • 精确锁定需要的行(使用索引)
    • 批量操作使用批量提交
    • 高并发场景考虑乐观锁
  1. 异常处理
DECLARE EXIT HANDLER FOR SQLEXCEPTION 
BEGINROLLBACK;-- 记录错误日志
END;

通过深入理解 MySQL 事务机制,可以构建出既保证数据一致性又具备高性能的数据库应用。建议结合业务场景选择合适的隔离级别和锁策略。


 

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

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

相关文章

WEB或移动端常用交互元素及组件 | Axure / 元件类型介绍(表单元件、菜单和表格 、流程元件、标记元件)

文章目录 引言I Axure / 元件类型介绍基本元件表单元件菜单和表格流程元件标记元件II Axure 基础Axure / 常用功能介绍Axure / 常用元素实例Axure / 动态交互实例Axure / 常用设计分辨率推荐III Axure / 创建自己的元件库元件库作用元件库的创建及使用引言 I Axure / 元件类型介…

如何排查C++程序的CPU占用过高的问题

文章目录 可能的原因程序设计的BUG系统资源问题恶意软件硬件问题 通常步骤一个简单的问题代码在windows平台上如何排查Windows Process ExplorerWinDBG 在Linux平台如何排查使用TOP GDBPerf 可能的原因 程序设计的BUG 有死循环低效算法与数据结构滥用自旋锁频繁的系统调用&a…

19726 星际旅行

19726 星际旅行 ⭐️难度&#xff1a;困难 &#x1f31f;考点&#xff1a;Dijkstra、省赛、最短路问题、期望、2024 &#x1f4d6; &#x1f4da; import java.util.*;public class Main {static int N 1005;static ArrayList<Integer>[] g new ArrayList[N]; // …

vue3 + ant-design-vue4实现Select既可以当输入框也可以实现下拉选择

近日工作中&#xff0c;遇到一个需求&#xff0c;就是select的有一个前置切换条件&#xff0c;有些条件需要时输入&#xff0c;有些条件需要时下拉选择&#xff0c;但是在切换的时候&#xff0c;后面的这个输入或者选择组件不能闪烁&#xff0c;于是也就只能采用select去实现&a…

Unity UGUI - 六大基础组件

目录 一、Canvas上 1. Canvas&#xff1a;复制渲染子UI控件 2. ✨Canvas Scaler✨&#xff1a;画布分辨率自适应 3. Graphics Raycaster&#xff1a;射线事件响应 4. ✨Rect Transform✨&#xff1a;UI位置锚点对齐 二、Event System上 5. Event System 6. Standalone …

VSCode中使用Markdown以及Mermaid实现流程图和甘特图等效果

前言 Markdown&#xff08;简称md&#xff09;这种文件格式&#xff0c;渐渐盛行起来。有点类似html格式的意思。特别是内嵌的对Marmaid的支持&#xff0c;对流程图、甘特图等的绘制&#xff0c;都非常的方便。 一、安装Markdown的插件 二、创建.md文件 新建一个Markdown文件&…

如何让 history 记录命令执行时间?Linux/macOS 终端时间戳设置指南

引言:你真的会用 history 吗? 有没有遇到过这样的情况:你想回顾某个重要命令的执行记录,却发现 history 只列出了命令序号和内容,根本没有时间戳?这在运维排查、故障分析、甚至审计时都会带来极大的不便。 想象一下,你在服务器上误删了某个文件,但不知道具体是几点执…

css—— object-fit 属性

一&#xff0c;属性值 object-fit: fill | contain | cover | none | scale-down;原本的图片&#xff1a; 属性值效果&#xff1a; <!DOCTYPE html> <html> <head><style>.container {display: flex;flex-wrap: wrap;gap: 20px;}.box {width: 200px…

端游熊猫脚本游戏精灵助手2025游戏办公脚本工具!游戏脚本软件免费使用

在当下这个崇尚高效与便捷的时代&#xff0c;自动化工具已然成为诸多开发者与企业提升工作效率的关键选择。熊猫精灵脚本助手作为一款极具实力的自动化工具&#xff0c;凭借其多样的功能以及广泛的应用场景&#xff0c;逐步成为众多用户的首要之选。 熊猫精灵脚本助手整合了丰…

Docker安装MySql 8.0

1、验证环境 docker -v使用上面的命令检查一下本机的docker的运行环境。执行完成之后&#xff0c;会输出docker的版本号 我本地输出以下内容: Docker version 27.5.1, build 9f9e4052、拉取镜像 docker pull mysql:8.0拉取mysql8.0版本对的镜像。正常情况如下: 如果报下面的…

Jmeter-负载测试

目录 一. 基础负载测试场景&#xff1a;固定并发用户数 1、线程组配置 2、HTTP请求配置 3、添加定时器 4、添加监听器 4.1 聚合报告 4.2 响应时间图 4.3 查看结果树 5、结果分析指标 二. 阶梯式加压场景&#xff08;逐步增加并发&#xff09; 1、插件安装 2、阶梯配…

【新手初学】读取数据库数据

利用注入点让SQL注入语句执行读取数据库数据相关的操作&#xff01; 以下均以pikachu靶场的字符型注入为例进行介绍说明 一、读取用户名&#xff0c;数据库版本信息 在原URL后面添加如下代码&#xff1a; union select user(),version(&#xff09;-- 效果&#xff1a; 补…

Ubuntu与Windows之间相互复制粘贴的方法

一、打开Ubuntu终端 二、卸载已有的工具 sudo apt-get autoremove open-vm-tools 三、安装工具 sudo apt-get install open-vm-tools-desktop 四、重启 直接输入reboot 注&#xff1a;有任何问题欢迎评论区交流讨论或者私信&#xff01;

免去繁琐的手动埋点,Gin 框架可观测性最佳实践

作者&#xff1a;牧思 背景 在云原生时代的今天&#xff0c;Golang 编程语言越来越成为开发者们的首选&#xff0c;而对于 Golang 开发者来说&#xff0c;最著名的 Golang Web 框架莫过于 Gin [ 1] 框架了&#xff0c;Gin 框架作为 Golang 编程语言官方的推荐框架 [ 2] &…

【QT】新建QT工程(详细步骤)

新建QT工程 1.方法(1)点击new project按钮&#xff0c;弹出对话框&#xff0c;新建即可&#xff0c;步骤如下&#xff1a;(2) 点击文件菜单&#xff0c;选择新建文件或者工程&#xff0c;后续步骤如上 2.QT工程文件介绍(1).pro文件 --》QT工程配置文件(2)main.cpp --》QT工程主…

优化MyBatis-Plus批量插入策略

优化MyBatis-Plus批量插入策略 优化MyBatis-Plus批量插入策略一、用Mybatis-plus中的saveBatch方法二、InsertBatchSomeColumn插件1.使用前配置2.代码示例1.配置类 MybatisPlusConfig2).实体类 User3).Mapper 接口 UserMapper4).测试类 InsertBatchTest 优化MyBatis-Plus批量插…

记一次系统单点登录、模拟web系统登录方式的开发过程,使用AES加密

1.系统原始登录方式 访问登录页 输入账号密码登录后 2.从登录页找进去&#xff0c;从代码层面查看系统登录逻辑 常规登录方式为前端ajax请求LoginService服务-->返回200则跳转到home系统首页 查看LoginService登录逻辑 后台获取ajax传递的信息-->比较验证码-->查询…

iPhone mini,永远再见了

世界属于多数派&#xff0c;尽管有极少数人对 iPhone mini 情有独钟&#xff0c;但因为销量惨淡&#xff0c;iPhone mini 还是逃不开停产的命运。 据 Counterpoint 的数据&#xff0c;iPhone 12/13 mini 两代机型&#xff0c;仅占同期 iPhone 销量的 5%。 因为是小屏手机&…

监控易一体化运维:监控易机房管理,打造高效智能机房

在数字化浪潮中&#xff0c;企业对数据中心和机房的依赖程度与日俱增&#xff0c;机房的稳定运行成为业务持续开展的关键支撑。信息化的变迁&#xff0c;见证了机房管理从传统模式向智能化、精细化转变的过程。今天&#xff0c;就为大家深度剖析监控易在机房管理方面的卓越表现…

概率与决策理论

1.Q-learning Q-Learning 是一种无模型&#xff08;model-free&#xff09;强化学习算法&#xff0c;用于学习在马尔可夫决策过程&#xff08;MDP&#xff09;中的最优策略。它通过迭代更新 ​Q 值&#xff08;动作价值函数&#xff09;​ 来估计在某个状态下采取某个动作的长…