MySQL事务以及事务隔离级别

  • MySQL事务主要用于处理操作量大,复杂度高的数据。比如在人员管理系统中,你删除一个人员,你就要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等,这些数据库操作语句就构成了一个事务

    • MySQL中只有使用了Innodb数据库引擎的数据库或表才支持事务
    • 事务处理可以用来维护数据库的完整性,保证成批的SQL语句要么全部执行,要么全部不执行
    • 事务用来管理insert,update,delete语句
  • 一般来说,事务必须满足4个条件:原子性,一致性,隔离性,持久性
    • 原子性:一个事务中所有操作,要么全部执行,要么全部不执行不会结束在中间某个环节。事务在执行过程中发生错误会被回滚到事务开始前的状态
    • 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,包含资料的精确度,串联性以及后续数据库可以自发性的完成预定的工作
    • 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读取未提交内容,读取提交内容,可重复读和可串行化
    • 持久化:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失

在MySQL命令行的默认是设置下,事务都是自动提交的,即执行SQL语句后就会马上执行COMMIT操作。因此要显式的开启一个事务需要使用命令BEGIN或START TRANSACTION,或者执行命令SET AUTOCOMMIT=0,用来禁止使用当前绘画的自动提交

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

事务控制语句:

  • BEGIN或START TRANSACTION;显式地开启一个事务
  • COMMIT;也可以使用COMMIT WORK,二者等价的。COMMIT会提交事务,并使已对数据库进行的所有修改成为永久性
  • ROLLBACK;也可以使用ROLLBACK WORK,二者等价。回滚会结束用户的事务,并撤回正在进行的所有未提交的修改
  • SAVEPOINT identifier;SAVEPOINT允许在事务中创建一个保存点,一个事务可以有多个SAVEPOINT
  • RELESE SAVEPOINT identifier;删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常
  • ROLLBACK TO identified;把事务回滚到标记点
  • SET TRANSACTION;用来设置事务的隔离级别。InnoDB存储引擎提供事务隔离级别有READ UNCOMMITTED,READ COMMITTED,REPEATABLE READ和SERIALIZABLE

MySQL事务处理主要有两种方法:

  1. 用BEGIN,ROLLBACK,COMMIT来实现
    • BEGIN开始一个事务
    • ROLLBACK事务回滚
    • COMMIT事务确认
  2. 直接SET来改变MySQL的自动提交模式:
    • SET AUTOCOMMIT=0禁止自动提交
    • SET AUTOCOMMIT=1开启自动提交

事务四大特性之一:隔离性

  1. 事务A跟事务B之间具有一定的隔离性
  2. read uncommited 读未提交
    • 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用。读取未提交的数据称为脏数据
  3. read COMMIT
    • 大多数数据库系统的默认隔离级别(但不是MySQL)。一个事务只能看见已经提交事务所作的改变。其避免了脏读,但仍然存在不可重复读和幻读问题
  4. repeatable read
    • MySQL的默认级别;确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。避免了脏读和不可重复读,但是会导致另一个问题:幻读。幻读是指用户读取某一个范围的数据行时,另一个事务又在该范围插入了新行,当用户再读取该范围的数据行时,会发现新的幻影行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC)机制解决了该问题
    • 可重复读的隔离级别下使用了MVCC机制,select操作不会更新版本号,是快照读(历史版本);insert,update和delete会更新版本号,是当前读(当前版本)
  5. serializable
    • 最高隔离级别,通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争

设置事务隔离级别

  1. 在my.cnf文件设置
- READ-UNCOMMITTED
- READ-COMMITED
- REPEATABLE-READ
- SERIALIZABLE
* 例如
[mysqlId]
transaction-isolation = READ-COMMITTED
  1. 通过命令动态设置隔离级别
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL <isolation-level>
其中isolation-level可以是:
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE

GLOBAL|SESSION表示事务隔离级别的作用范围:
GLOBAL:表示对所有会话有效
SESSION:表示对当前会话有效

事务并发问题

  1. 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
  2. 不可重复读:事务A多次读取到同一数据,事务B在事务A多次读取过程中,对数据做了更新并未提交,导致事务A多次读取同一条数据,结果不一致
  3. 幻读:前后读取的结果数据条数不一致。这是因为事务A的多次读取过程中,事务B对表进行插入或删除操作
扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄