{"msg":"操作成功","code":200,"data":{"createBy":"admin","createTime":"2020-04-19 18:18:35","updateBy":"admin","updateTime":"2020-04-19 18:18:35","remark":null,"id":26,"articleTitle":"MySQL（八）事务TRANSACTION","articleUrl":"mysql_transaction","articleThumbnail":"https://www.asumimoe.com/imgfiles/20220908/9e192744fab244d39d3b15fca035c9f7.jpg","articleFlag":"0","draftStatus":"1","reprintStatement":"1","articleSummary":"事务是数据库管理系统的核心功能，用于确保数据操作的完整性和一致性。MySQL 通过 InnoDB 存储引擎提供了强大的事务支持，满足 ACID 特性要求。","articleContent":"事务是数据库管理系统的核心功能，用于确保数据操作的完整性和一致性。MySQL 通过 InnoDB 存储引擎提供了强大的事务支持，满足 ACID 特性要求。\n\n## 基本概念\n\n### 1. 什么是事务？\n\n事务是数据库操作的最小逻辑单元，由一组SQL语句组成，这些语句要么**全部成功执行**，要么**全部失败回滚**。\n\n### 2.ACID 特性\n\n| 特性                         | 描述                                                         | MySQL 实现机制                                               |\n| ---------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |\n| **原子性**<br/>(Atomicity)   | **全有或全无**：事务中的所有操作要么全部成功执行，要么全部失败回滚<br/>**不可分割**：事务是最小工作单元，不能被部分执行 | Undo Log<br/>在执行变更前，将原始数据拷贝到 Undo Log<br>若事务失败，使用 Undo Log 回滚到原始状态<br/>事务提交后，Undo Log 可被安全删除 |\n| **一致性**<br/>(Consistency) | **状态有效性**：事务使数据库从一个有效状态转换到另一个有效状态<br/>**约束保持**：事务执行后，所有数据库约束仍然满足<br/>**业务规则**：保证业务逻辑的正确性 | 约束、触发器、外键                                           |\n| **隔离性**<br/>(Isolation)   | **并发控制**：多个并发事务相互隔离，互不干扰<br/>**透明执行**：每个事务感觉不到其他事务的存在<br/>**问题防范**：解决脏读、不可重复读、幻读问题 | 锁机制：<br/>共享锁(S锁)：允许多个事务并发读取<br/>排他锁(X锁)：只允许一个事务读写<br/>间隙锁(Gap Lock)：防止幻读<br/><br/>多版本并发控制(MVCC)：<br/>每个事务看到数据库的特定时间点快照<br/>通过 Read View 和 Undo Log 实现<br/>非锁定读提高并发性能 |\n| **持久性**<br/>(Durability)  | **永久保存**：事务提交后，对数据库的修改永久保存<br/>**故障恢复**：系统崩溃后能恢复到最近一致状态<br/>**持久存储**：数据写入非易失性存储设备 | Redo Log（重做日志）：<br/>顺序写入，高性能<br/>记录物理修改（页级别）<br/>崩溃恢复时重放未完成事务<br/><br/>双写缓冲(Double Write Buffer)：<br/>防止页断裂(partial page writes)<br/>先将页写入缓冲区，再写入数据文件 |\n\n## MySQL 事务控制语句\n\n### 1.基本事务操作\n\n```sql\n-- 开始事务\nSTART TRANSACTION;  -- 或 BEGIN\n\n-- 执行SQL操作\nUPDATE accounts SET balance = balance - 100 WHERE id = 1;\nUPDATE accounts SET balance = balance + 100 WHERE id = 2;\n\n-- 提交事务（确认更改）\nCOMMIT;\n\n-- 回滚事务（撤销更改）\nROLLBACK;\n```\n\n### 2.保存点（Savepoints）\n\n```sql\nSTART TRANSACTION;\n\n-- 操作1\nINSERT INTO orders (customer_id, amount) VALUES (123, 500.00);\nSAVEPOINT order_created;\n\n-- 操作2\nUPDATE inventory SET stock = stock - 1 WHERE product_id = 456;\nSAVEPOINT inventory_updated;\n\n-- 条件回滚\nIF /* 库存不足 */ THEN\n    ROLLBACK TO SAVEPOINT order_created;  -- 回退到订单创建点\nEND IF;\n\nCOMMIT;\n```\n\n## 事务隔离级别\n\nMySQL 支持四种隔离级别，不同级别解决不同的并发问题：\n\n| 隔离级别                        | 脏读 | 不可重复读 | 幻读 | 性能 |\n| ------------------------------- | ---- | ---------- | ---- | ---- |\n| **READ UNCOMMITTED**            | ❌    | ❌          | ❌    | 最高 |\n| **READ COMMITTED**              | ✅    | ❌          | ❌    | 较高 |\n| **REPEATABLE READ** (MySQL默认) | ✅    | ✅          | ⚠️    | 中等 |\n| **SERIALIZABLE**                | ✅    | ✅          | ✅    | 最低 |\n\n### 1.设置隔离级别\n\n```sql\n-- 设置会话级隔离级别\nSET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;\n\n-- 设置全局级隔离级别\nSET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;\n\n-- 查看当前隔离级别\nSELECT @@transaction_isolation;\n```\n\n### 2.不同隔离级别的并发问题\n\n#### 1. 脏读（Dirty Read）\n\n- **场景**：事务A读取了事务B未提交的数据\n\n- **示例**：\n\n  ```sql\n  -- 事务A\n  SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;\n  START TRANSACTION;\n  SELECT balance FROM accounts WHERE id = 1; -- 读到未提交的修改\n  \n  -- 事务B\n  START TRANSACTION;\n  UPDATE accounts SET balance = 500 WHERE id = 1; -- 未提交\n  ```\n\n#### 2. 不可重复读（Non-Repeatable Read）\n\n- **场景**：同一事务内两次读取相同数据结果不同\n\n- **示例**：\n\n  ```sql\n  -- 事务A\n  SET TRANSACTION ISOLATION LEVEL READ COMMITTED;\n  START TRANSACTION;\n  SELECT balance FROM accounts WHERE id = 1; -- 第一次读取\n  \n  -- 事务B提交更新\n  UPDATE accounts SET balance = 300 WHERE id = 1;\n  COMMIT;\n  \n  -- 事务A再次读取\n  SELECT balance FROM accounts WHERE id = 1; -- 结果不同\n  ```\n\n#### 3. 幻读（Phantom Read）\n\n- **场景**：同一事务内两次查询返回不同行数\n\n- **示例**：\n\n  ```sql\n  -- 事务A\n  START TRANSACTION;\n  SELECT COUNT(*) FROM orders WHERE customer_id = 123; -- 返回5条\n  \n  -- 事务B插入新订单并提交\n  INSERT INTO orders (customer_id, amount) VALUES (123, 200.00);\n  COMMIT;\n  \n  -- 事务A再次查询\n  SELECT COUNT(*) FROM orders WHERE customer_id = 123; -- 返回6条\n  ```\n\n## MySQL 事务实现机制\n\n### 1. 锁机制\n\n| 锁类型          | 描述                     | 适用场景                         |\n| --------------- | ------------------------ | -------------------------------- |\n| **共享锁(S锁)** | 允许多事务并发读取       | `SELECT ... LOCK IN SHARE MODE`  |\n| **排他锁(X锁)** | 仅允许一个事务读写       | `SELECT ... FOR UPDATE`、DML语句 |\n| **意向锁**      | 表级锁，表示行级锁的存在 | 自动管理                         |\n| **记录锁**      | 锁定索引记录             | 行级锁基础                       |\n| **间隙锁**      | 锁定索引记录间的间隙     | 防止幻读                         |\n| **临键锁**      | 记录锁+间隙锁组合        | REPEATABLE READ 默认             |\n\n### 2. 多版本并发控制(MVCC)\n\nInnoDB 使用 MVCC 实现非锁定读：\n\n- **Read View**：事务启动时的数据快照\n- **Undo Log**：存储数据的历史版本\n- **版本链**：通过 DB_ROLL_PTR 连接历史版本\n\n```mermaid\ngraph LR\n    A[当前数据] --> B[版本1]\n    B --> C[版本2]\n    C --> D[版本3]\n```\n\n### 3.日志系统\n\n| 日志类型     | 作用               | 关键特性                                |\n| ------------ | ------------------ | --------------------------------------- |\n| **Redo Log** | 确保事务持久性     | 物理日志、循环写入、崩溃恢复            |\n| **Undo Log** | 支持事务回滚和MVCC | 逻辑日志、版本链管理                    |\n| **Binlog**   | 主从复制和数据恢复 | 逻辑日志、三种格式(Statement/Row/Mixed) |\n\n## 事务编程实践\n\n### 1.基础事务模式\n\n```sql\nSTART TRANSACTION;\n\nDECLARE EXIT HANDLER FOR SQLEXCEPTION\nBEGIN\n    ROLLBACK;\n    RESIGNAL;\nEND;\n\n-- 业务操作\nINSERT INTO orders (...) VALUES (...);\nUPDATE inventory SET stock = stock - 1 WHERE ...;\n\nCOMMIT;\n```\n\n### 2. 嵌套事务模拟\n\n```sql\n-- 使用保存点实现伪嵌套事务\nSTART TRANSACTION;\n\nSAVEPOINT level1;\n-- 操作1...\n\nSAVEPOINT level2;\n-- 操作2...\n\n-- 部分提交\nRELEASE SAVEPOINT level2;\n\n-- 部分回滚\nROLLBACK TO SAVEPOINT level1;\n\nCOMMIT;\n```\n\n### 3.分布式事务(XA)\n\n```sql\n-- 协调器\nXA START 'xid1';\nUPDATE db1.accounts ...;\nXA END 'xid1';\nXA PREPARE 'xid1';\n\n-- 参与者\nXA START 'xid1';\nUPDATE db2.ledger ...;\nXA END 'xid1';\nXA PREPARE 'xid1';\n\n-- 全局提交/回滚\nXA COMMIT 'xid1';  -- 或 XA ROLLBACK 'xid1';\n```\n\n## 事务性能优化\n\n### 1.优化策略\n\n1. **短事务原则**：尽量减少事务执行时间\n\n2. **减少锁竞争**：\n\n   - 访问相同数据的操作集中处理\n   - 使用合适的索引减少锁定范围\n\n3. **避免长查询**：复杂查询放在事务外\n\n4. **合理设置隔离级别**：根据业务需求选择最低可用级别\n\n5. **批量操作优化**：\n\n   ```sql\n   -- 低效\n   START TRANSACTION;\n   FOR i IN 1..1000 LOOP\n     INSERT INTO log VALUES (...);\n   END LOOP;\n   COMMIT;\n   \n   -- 高效\n   START TRANSACTION;\n   INSERT INTO log VALUES (...), (...), ...; -- 批量插入\n   COMMIT;\n   ```\n\n### 2.死锁处理\n\n```sql\n-- 查看死锁日志\nSHOW ENGINE INNODB STATUS;\n\n-- 死锁自动检测参数\nSET GLOBAL innodb_deadlock_detect = ON;  -- 默认开启\nSET GLOBAL innodb_lock_wait_timeout = 50; -- 锁等待超时(秒)\n```\n\n## 事务监控与诊断\n\n### 1.查看事务信息\n\n```sql\n-- 当前运行事务\nSELECT * FROM information_schema.INNODB_TRX;\n\n-- 事务锁信息\nSELECT * FROM performance_schema.data_locks;\nSELECT * FROM performance_schema.data_lock_waits;\n\n-- 长事务监控\nSELECT \n  trx_id, \n  TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS duration_sec,\n  trx_query\nFROM information_schema.INNODB_TRX\nORDER BY duration_sec DESC;\n```\n\n### 2.事务日志分析\n\n```sql\n-- Redo Log状态\nSHOW GLOBAL STATUS LIKE 'Innodb_redo_log%';\n\n-- Undo Log信息\nSHOW VARIABLES LIKE 'innodb_undo%';\n```\n\n## 高级事务模式\n\n### 1.乐观并发控制\n\n```sql\n-- 添加版本号字段\nALTER TABLE products ADD version INT DEFAULT 0;\n\n-- 更新时检查版本\nUPDATE products \nSET stock = 10, version = version + 1 \nWHERE id = 100 AND version = 5;\n\n-- 检查影响行数\nif (affectedRows == 0) {\n    // 发生冲突，重试或提示用户\n}\n```\n\n### 2.柔性事务模式\n\n| 模式                             | 适用场景     | 特点                 |\n| -------------------------------- | ------------ | -------------------- |\n| **TCC**<br/>(Try-Confirm-Cancel) | 高一致性要求 | 业务侵入性强         |\n| **Saga**                         | 长流程业务   | 最终一致性、补偿机制 |\n| **消息队列**                     | 异步解耦     | 基于可靠消息         |","categoryId":4,"viewCount":759,"categoryName":"MySQL","author":"球接子","authorAvatar":null,"tagIds":[2,17],"tagNames":["MySQL","数据库"]}}