一文讲清楚 MySQL 事务隔离级别和实现原理

云游道人 2025-03-07 828 阅读 0评论

一、MySQL 事务隔离级别

MySQL 支持四种事务隔离级别,分别是:

  1. 读未提交(Read Uncommitted)

  • 最低的隔离级别,事务可以读取其他事务未提交的数据。
  • 可能导致脏读、不可重复读和幻读。
  1. 读已提交(Read Committed)

  • 事务只能读取其他事务已提交的数据。
  • 避免了脏读,但可能导致不可重复读和幻读。
  1. 可重复读(Repeatable Read)

  • 确保在同一事务中多次读取同一数据时,结果一致。
  • 避免了脏读和不可重复读,但可能导致幻读。
  1. 串行化(Serializable)

  • 最高的隔离级别,事务串行执行,避免了脏读、不可重复读和幻读。
  • 但性能最差,因为事务需要排队执行。

二、事务隔离级别的实现原理

MySQL 通过 多版本并发控制(MVCC, Multi-Version Concurrency Control) 和 锁机制 来实现事务隔离级别。

  1. MVCC

  • MVCC 通过为每行数据维护多个版本来实现并发控制。
  • 每个事务在开始时都会获得一个唯一的事务 ID(Transaction ID),事务只能看到在该事务开始之前已经提交的数据版本。
  • 通过这种方式,MVCC 实现了读操作不加锁,提高了并发性能。
  1. 锁机制

  • MySQL 使用锁来保证事务的隔离性。
  • 常见的锁有共享锁(S锁)和排他锁(X锁)。
  • 读操作可以加共享锁,写操作需要加排他锁。

三、代码实例讲解

1. 设置事务隔离级别

-- 设置事务隔离级别为读未提交
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

-- 设置事务隔离级别为读已提交
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- 设置事务隔离级别为可重复读
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

-- 设置事务隔离级别为串行化
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

2. 事务操作示例

假设我们有一个 accounts 表,结构如下:

CREATE TABLE accounts (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    balance DECIMAL(102)
);

插入一些初始数据:

INSERT INTO accounts (id, name, balance) VALUES (1'Alice'1000.00);
INSERT INTO accounts (id, name, balance) VALUES (2'Bob'500.00);

3. 读未提交(Read Uncommitted)

-- 事务1:更新数据但未提交
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

-- 事务2:读取未提交的数据
START TRANSACTION;
SELECT * FROM accounts WHERE id = 1;  -- 可能读取到未提交的数据
COMMIT;

-- 事务1:回滚
ROLLBACK;

4. 读已提交(Read Committed)

-- 事务1:更新数据并提交
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;

-- 事务2:读取已提交的数据
START TRANSACTION;
SELECT * FROM accounts WHERE id = 1;  -- 只能读取到已提交的数据
COMMIT;

5. 可重复读(Repeatable Read)

-- 事务1:更新数据并提交
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;

-- 事务2:在同一事务中多次读取数据
START TRANSACTION;
SELECT * FROM accounts WHERE id = 1;  -- 第一次读取
-- 事务1提交后,事务2再次读取
SELECT * FROM accounts WHERE id = 1;  -- 结果与第一次读取一致
COMMIT;

6. 串行化(Serializable)

-- 事务1:更新数据
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

-- 事务2:尝试读取数据,但会被阻塞
START TRANSACTION;
SELECT * FROM accounts WHERE id = 1;  -- 事务1提交后才会执行
COMMIT;

-- 事务1:提交
COMMIT;

四、总结

  • 读未提交

    :最低隔离级别,可能导致脏读。
  • 读已提交

    :避免了脏读,但可能导致不可重复读。
  • 可重复读

    :避免了脏读和不可重复读,但可能导致幻读。
  • 串行化

    :最高的隔离级别,避免了所有并发问题,但性能最差。

MySQL 通过 MVCC 和锁机制来实现这些隔离级别,开发者可以根据业务需求选择合适的隔离级别。

喜欢就支持以下吧
点赞 0

发表评论

快捷回复: 表情:
aoman baiyan bishi bizui cahan ciya dabing daku deyi doge fadai fanu fendou ganga guzhang haixiu hanxiao zuohengheng zhuakuang zhouma zhemo zhayanjian zaijian yun youhengheng yiwen yinxian xu xieyanxiao xiaoku xiaojiujie xia wunai wozuimei weixiao weiqu tuosai tu touxiao tiaopi shui se saorao qiudale qinqin qiaoda piezui penxue nanguo liulei liuhan lenghan leiben kun kuaikule ku koubi kelian keai jingya jingxi jingkong jie huaixiao haqian aini OK qiang quantou shengli woshou gouyin baoquan aixin bangbangtang xiaoyanger xigua hexie pijiu lanqiu juhua hecai haobang caidao baojin chi dan kulou shuai shouqiang yangtuo youling
提交
评论列表 (有 0 条评论, 828人围观)

最近发表

热门文章

最新留言

热门推荐

标签列表