MySQL 事务


事务

概述

  • 一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元);完整的业务需要批量的DML(insert、update、delete)语句共同联合完成
  • 事务只和DML语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同
  • 事务是为数据安全操作提出的,用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行

使用注意

  • 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务
  • 只在同一连接对象生效

事务的特征(ACID)

事务必须服从ACID原则

  • 原子性(A):
    • 事务是最小单位,不可再分
  • 一致性(C):
    • 必须保证同时成功或者同时失败;数据库的完整性没有被破坏;不能有数据丢失的情况。
  • 隔离性(I):
    • 消除事务间的相互影响;事务A和事务B之间具有隔离性
  • 持久性(D):
    • 保证事务执行的结果在磁盘上永久的存储

事务隔离性的后果

  1. 脏读:事务获取到其它事务执行过程中的结果
  • 解决方案:事务执行过程中获取不到其它事务执行过程中的结果。
  1. 不可重复读(修改操作导致):事务执行过程中获取了其它事务不同的阶段的结果;
  • 解决方案:事务在其它事务执行过程中开启,其它事务相对于该事务透明
  1. 幻读(插入或删除操作导致):事务执行过程中获取到其它事务不同阶段的结果。
  • 解决方案:间隙锁。

事务的隔离级别

  1. 读未提交:read uncommitted
    • 事物A和事物B,事物A未提交的数据,事物B可以读取到;这里读取到的数据叫做“脏数据”
    • 这种隔离级别最低,这种级别一般是在理论上存在,数据库隔离级别一般都高于该级别
  2. 读已提交:read committed
    • 事物A和事物B,事物A提交的数据,事物B才能读取到;这种隔离级别高于读未提交
    • 换句话说,对方事物提交之后的数据,我当前事物才能读取到;这种级别可以避免“脏数据”;这种隔离级别会导致“不可重复读取”
    • Oracle默认隔离级别
  3. 可重复读:repeatable read
    • 事务A和事务B,事务A提交之后的数据,事务B读取不到
    • 事务B是可重复读取数据
    • 这种隔离级别高于读已提交
    • 换句话说,对方提交之后的数据,我还是读取不到
    • 这种隔离级别可以避免“不可重复读取”,达到可重复读取
    • 比如1点和2点读到数据是同一个
    • MySQL默认级别
    • 虽然可以达到可重复读取,但是会导致“幻像读”
  4. 串行化:serializable可序列化:事务变成串行处理
    • 事务A和事务B,事务A在操作数据库时,事务B只能排队等待
    • 这种隔离级别很少使用,吞吐量太低,用户体验差
    • 这种级别可以避免“幻像读”,每一次读取的都是数据库中真实存在数据,事务A与事务B串行,而不并发

      当前隔离级别:每次一个客户端连接服务器,服务器分配给它的隔离级别,修改时修改的是当前隔离级别。
      全局隔离级别:数据库服务端默认的隔离级别(可重复读),在配置文件中写的,数据库加载时直接读取配置文件

事务操作

在 MySQL 的默认设置下,事务是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作

  • 启用自动提交
    SET AUTOCOMMIT=1
  • 禁止自动提交
    使用BEGINSTART TRANSACTIONSET AUTOCOMMIT=0用来禁止使用当前会话(连接)的自动提交
  • 提交事务(执行操作)
    使用COMMITCOMMIT WORK
  • 回滚事务(撤销操作)
    使用ROLLBACKROLLBACK WORK,回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
  • 设置事务点
    SAVEPOINT identifierSAVEPOINT 允许在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT;
  • 删除事务点
    RELEASE SAVEPOINT identifier 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
  • 回滚到事务点
    ROLLBACK TO identifier 把事务回滚到标记点;
  • 设置隔离级别
    SET TRANSACTION用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。

嵌套事务,子事务

使用保留点 SAVEPOINT

savepoint 是在数据库事务处理中实现“子事务”(subtransaction),也称为嵌套事务的方法
事务可以回滚到 savepoint 而不影响 savepoint 创建前的变化, 不需要放弃整个事务
ROLLBACK 回滚的用法可以设置保留点 SAVEPOINT,执行多条操作时,回滚到想要的那条语句之前

使用 SAVEPOINT

SAVEPOINT 保留点名称; // 声明一个 savepoint
ROLLBACK TO 保留点名称; // 回滚到savepoint
删除 SAVEPOINT
保留点再事务处理完成(执行一条 ROLLBACK 或 COMMIT)后自动释放
MySQL5 以来,可以用:
RELEASE SAVEPOINT 保留点名称; – 删除指定保留点


文章作者: zrh
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 zrh !
  目录