Published on

事务隔离级别

Authors
  • avatar
    Name
    Pony Ma
    Twitter

事务隔离级别

可序列化,串行 Serializable

无问题

可重复读 Repeatable Read

默认的隔离级别 可能发生幻读问题 更新数据时不仅会对数据加行级锁,还会增加GAP lock

为什么默认是可重复读?

MySQL早期只有statement这一种binlog格式 以下两种隔离级别可能会遇到bug: 已有数据a=2,b=1 同时执行两个事物AB, A1: UPDATE t1 SET a=1 WHERE b=2; B1: UPDATE t1 SET b=2 WHERE b=1; B2: COMMIT; A2: COMMIT; A2: SELECT * FROM t1; 此时主数据库数据为a=2,b=2 此时的statement binlog为: UPDATE t1 SET b=2 WHERE b=1; UPDATE t1 SET a=1 WHERE b=2; 从数据库执行binlog文件,从数据库数据为a=1,b=2

提交读 Read Committed

可能发生幻读,不可重复读问题

未提交读 Read Uncommitted

可能发生脏读,幻读,不可重复读问题

事务的特性

原子性

事务是一系列的操作,要么全部执行,要么全都不执行,基于redo/undo日志的机制。 undolog用来记录数据更新前的值,方便回滚 redolog用来记录数据块被修改后的值,用来恢复,为写入data file的已成功修改的数据

回滚日志(undo log)

为了保证事务的原子性,就需要再异常发生时,对已经执行的操作进行回滚,回滚的机制是通过undo log来实现的, 所有事务进行的修改都会先记录到这个回滚日志中,然后再执行相应的数据库操作。

回滚日志除了在发生错误或者用户执行rollback时提供回滚相关的信息,它还能在系统崩溃、数据库进程被杀死, 用户再次启动数据库时,通过查询回滚日志,将之前未完成的事务进行回滚。这也就要求回滚日志必须先于数据持久化到磁盘上。

回滚日志并不能将数据库物理地恢复到执行语句或者事务之前的样子,他只是逻辑回滚,他会按照日志逻辑将数据库中的修改撤销掉, 通过执行与我们实际操作相反的SQL

事务的状态

通常来讲事务的状态会有三个值,active、committed, failed。

但如果放大来看的话其实不止这么多 active: 事务的初始状态,表示事务正在执行。 partially committed: 在最后一条语句执行之后。 failed: 发现事务无法正常执行之后。 aborted: 事务被回滚并且数据库恢复到了事务进行之前的状态之后。 committed: 事务成功执行完成。

事务可以回滚,但你在事务中发起的第三方请求却无法回滚。

并行事务的原子性

在实际工作中,并行执行的事务才是常态。 当事务1在执行读写操作,并且未提交或者回滚,而事务2对同样的数据执行了读写操作并提交了事务,也就是说 事务2是依赖事务1的,当事务1需要回滚时,为了保证原子性,事务2也需要回滚

一致性

执行事物前后的状态要一致

隔离性

事务间相互隔离,不受影响,受事务间隔离级别的影响

持久性

事务提交后,这个事务的状态会被持久化到数据库中