详解MySQL事务(transaction),用图直观解释了MySQL脏读、不可重复读、幻读的问题

事务

事务是一组操作的集合,会把所有操作作为一个整体去执行,要么同时成功,要么同时失败。

事务操作

  • 查看/设置事务提交方式
SELECT @@autocommit; # 1为自动,0为手动
SET @@autocommit = 0; # 改手动提交
  • 提交事务
COMMIT;
  • 回滚事务
ROLLBACK;
  • 开启事务
START TRANSACTION 或 BEGIN;

事务的四大特性(ACID)

  • 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
  • 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
  • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
  • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变是永久的。

并发事务问题

  • 脏读:一个事务读到另外一个事务还有没提交的数据。
  • 不可重复读:一个事务先读取同一条记录,但两次读取的数据不同。
  • 幻读:一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在。

事务的隔离级别

  • Read uncommitted
    • 可发生 脏读、不可重复读、幻读
  • Read committed
    • 可发生 不可重复读、幻读
  • Repeatable Read(默认)
    • 可发生 幻读
  • Serializable
    • 隔离级别最高,不会发生
# 查看事务隔离级别
SELECT @@TRANSACTION_ISOLATION;
# 设置事务隔离级别
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

隔离等级为Read uncommitted,发生脏读的例子

脏读:一个事务读到另外一个事务还有没提交的数据。

  • 代码:
    image
  • 代码运行图及结果:
    • 首先,设置事务隔离级别为Read uncommitted,并开启事务A和事务B
    • 1.执行 事务A代码 查询张三余额,结果为2000
    • 2.执行 事务B代码 修改张三余额,注意:并没有提交事务B
    • 3.执行 事务A代码 查询张三余额,结果为1000
      image

隔离等级为Read committed,发生不可重复读的例子

不可重复读:一个事务先读取同一条记录,但两次读取的数据不同。

  • 代码:
    image

  • 代码运行图及结果:

    • 首先,设置事务隔离级别为Read committed,并开启事务A和事务B
    • 1.执行 事务A代码 查询张三余额,结果为1000
    • 2.执行 事务B代码 修改张三余额,注意:并没有提交事务B
    • 3.执行 事务A代码 查询张三余额,结果为1000
    • 4.执行 事务B代码,commit
    • 5.执行 事务A代码 查询张三余额,结果为0
      image

隔离等级为Repeatable Read(默认),发生幻读的例子

  • 幻读:一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在。

  • 代码:
    image

  • 代码运行图及结果:

    • 首先,设置事务隔离级别为Repeatable Read,并开启事务A和事务B
    • 1.执行 事务A代码 查询id为3的数据,结果查询不到
    • 2.执行 事务B代码 插入id为3的数据
    • 3.执行 事务B代码 执行commit,结果提示成功插入
    • 4.执行 事务A代码 插入id为3的数据,提示插入失败,已存在id为3的数据
    • 5.执行 事务A代码 查询id为3的数据,结果查询不到,但是插入时却提示已存在id为3的数据
      image

隔离等级为Serializable

隔离等级为Serializable,只允许一个事务进行操作,只有当这个执行的事务操作完成后,才会去执行其他事务,从而避免了 脏读、不可重复读、幻读 问题。

posted @ 2022-12-24 00:33  乌药ice  阅读(228)  评论(0编辑  收藏  举报