[[隔离级别、锁、脏读、不可重复读与幻读问题]]

ACID

  • Atomicity(原子性):事务中的所有操作要么全部完成,要么全部不完成
  • Consistency(一致性):事务将数据库从一个有效状态转移到另一个有效状态
  • Isolation(隔离性):并发事务互不干扰
  • Durability(持久性):一旦事务提交,结果永久保存

多条SQL语句需要显式使用事务控制语句(如BEGIN, COMMIT, ROLLBACK)来保证ACID属性,单条SQL不一定能ACID
单条SQL:
原子性(Atomicity)

  • 通常满足:单条SQL语句在大多数RDBMS中默认作为隐式事务执行
  • 例外情况
    • 批量操作(如INSERT INTO … SELECT)可能部分成功
    • 某些数据库的特定语句(如MySQL的ALTER TABLE可能不支持原子DDL)
      隔离性(Isolation)
  • 受隔离级别影响
    持久性(Durability)
  • 可能不满足的情况
    • 使用内存表(如MySQL的MEMORY引擎)

MySQL 事务详解

事务是数据库管理系统中的一个核心概念,它代表一组必须全部成功或全部失败的数据库操作。MySQL 中的事务主要用于保证数据库操作的完整性和一致性。

一、事务的基本概念

1. 什么是事务?

事务(Transaction)是数据库操作的最小工作单元,是用户定义的一个操作序列,这些操作要么全部执行,要么全部不执行。

2. 事务的典型特性(ACID):

  • **原子性(Atomicity)**:事务是不可分割的工作单位,事务中的操作要么全部成功,要么全部失败回滚
  • **一致性(Consistency)**:事务执行前后,数据库从一个一致状态变到另一个一致状态
  • **隔离性(Isolation)**:多个事务并发执行时,一个事务的执行不应影响其他事务
  • **持久性(Durability)**:一旦事务提交,其所做的修改会永久保存在数据库中

二、MySQL 中的事务操作

1. 基本语法

1
2
3
4
5
START TRANSACTION;-- 或 BEGIN
-- 执行SQL语句
COMMIT;-- 提交事务
-- 或
ROLLBACK;-- 回滚事务

2. 事务控制语句

语句 功能
START TRANSACTIONBEGIN 开始一个新事务
COMMIT 提交当前事务,使更改永久化
ROLLBACK 回滚当前事务,取消所有更改
SAVEPOINT identifier 在事务中创建保存点
ROLLBACK TO [SAVEPOINT] identifier 回滚到指定保存点
RELEASE SAVEPOINT identifier 删除保存点
SET TRANSACTION 设置事务的隔离级别

三、事务的隔离级别

MySQL 支持四种隔离级别:

  1. READ UNCOMMITTED (读未提交)
  • 可能读取到其他事务未提交的数据(脏读)
  • 性能最好,但一致性最差
  1. READ COMMITTED (读已提交)
  • 只能读取已提交的数据
  • 解决脏读问题,但可能出现不可重复读
  1. REPEATABLE READ (可重复读) - MySQL默认
  • 同一事务中多次读取同样数据结果一致
  • 解决不可重复读问题,但可能出现幻读
  1. SERIALIZABLE (串行化)
  • 最高隔离级别,完全串行执行
  • 解决所有并发问题,但性能最差

设置隔离级别:

1
2
3
4
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 或设置全局/会话级别
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

四、事务的实际应用示例

1. 银行转账示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
START TRANSACTION;

-- 从A账户扣款
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

-- 向B账户加款
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;

-- 检查是否有错误
IF (没有错误) THEN
COMMIT;-- 提交事务
SELECT '转账成功';
ELSE
ROLLBACK;-- 回滚事务
SELECT '转账失败';
END IF;

2. 使用保存点(SAVEPOINT)

1
2
3
4
5
6
7
8
9
10
START TRANSACTION;

INSERT INTO orders (order_id, customer_id) VALUES (1, 101);
SAVEPOINT order_created;

UPDATE inventory SET stock = stock - 1 WHERE product_id = 5;
-- 如果库存更新失败
ROLLBACK TO order_created;

COMMIT;

五、事务的注意事项

  1. 存储引擎支持
  • InnoDB 完全支持事务
  • MyISAM 不支持事务
  1. 自动提交模式
  • MySQL 默认是自动提交(autocommit=1)
  • 可以关闭自动提交:SET autocommit=0;
  1. 长事务问题
  • 避免长时间运行的事务,会锁定资源
  • 大事务可以拆分为小事务
  1. 死锁处理
  • MySQL 能检测死锁并自动回滚其中一个事务
  • 应用层应实现重试机制

六、事务的最佳实践

  1. 尽量使事务简短,减少锁定时间
  2. 避免在事务中进行用户交互
  3. 合理设置隔离级别,平衡一致性和性能
  4. 处理事务失败情况,实现重试逻辑
  5. 监控长事务和死锁情况

通过正确使用事务,可以确保数据库操作的安全性和一致性,特别是在处理金融交易、订单处理等关键业务场景时尤为重要。