MYSQL之事务

事务有哪些特性?

四大特性:ACID

  • 原子性:一个事务的操作要么全部成功,要么全部失败。

  • 一致性:是指事务操作前和操作后,数据满足完整性约束,数据库保持一致性状态。

  • 隔离性:事务和事务之间是互不干扰的,MYSQL使用了MVCC机制和next-key lock机制来实现隔离性。

  • 持久性:事务执行完后,数据是持久化到磁盘的,属于永久操作。

  • MYSQL是怎么保证事务的这些特性的?

    • 原子性:是由 undo log(回滚日志)保证

    • 一致性:是由 redo log(重做日志)保证

    • 隔离性:是由 MVCC机制 和 next-key lock机制 保证

    • 持久性:是由 原子性+一致性+隔离性+持久性 保证

 

并行事务会引发什么问题?

同时处理多个事务时,可能出现:脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read)

  • 脏读(dirty read)一个事务「读到」了另一个「未提交事务修改过的数据」

  • 不可重复读(non-repeatable read)在一个事务内多次读取同一个数据,出现前后两次读到的数据不一样的情况

  • 幻读(phantom read)在一个事务内多次查询某个符合查询条件的「记录数量」,出现前后两次查询到的记录数量不一样的情况

 

事务的隔离级别有哪些?

同时处理多个事务时,就可能出现:脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read)

  • 读未提交:

    • 一个事务未提交时,可以被其他事务看到

    • 可能发生脏读、不可重复读和幻读现象

  • 读已提交:

    • 一个事务提交之后,才能被其他事务看到

    • 可能发生不可重复读和幻读现象

  • 可重复读:

    • 一个事务执行过程中看到的数据,和开始事务时看到的数据是一致的。

    • MySQL InnoDB 引擎的默认隔离级别

    • 可能发生幻读现象

  • 可串化:

    • 对记录加上 读写锁,在多个事务对这条记进行读写操作时,如果发生读写冲突,后访问的事务需等待前一个事务执行完成,才能继续执行。

    • 脏读、不可重复读和幻读现象都不可能会发生。

 

MySQL InnoDB 引擎的默认隔离级别虽然是「可重复读」,但是它很大程度上避免幻读现象(并不是完全解决了)

  • 针对 快照读(select...),数据库采用的是 MVCC机制 来解决幻读,只有某些特殊情况还是会产生幻读。

    • 因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。

  • 针对 当前读(select ... for update),数据库采用的是 next-key lock(记录锁+间隙锁)

    • 因为当执行 select ... for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。

 

 特殊情况:
  • 事务A开始

  • 事务A执行查询id=5,但id=5这个记录在行中是不存在的,所以查出为null

  • 事务B开始

  • 事务B执行增加id=5的数据

  • 事务B提交

  • 事务A对id=5的数据进行更新操作

  • 事务A执行查询id=5,搜索到了事务B提交的数据

  • 事务A提交

在可重复读隔离级别下,事务 A 第一次执行普通的 select 语句时生成了一个 ReadView,之后事务 B 向表中新插入了一条 id = 5 的记录并提交。接着,事务 A 对 id = 5 这条记录进行了更新操作,在这个时刻,这条新记录的 trx_id 隐藏列的值就变成了事务 A 的事务 id,之后事务 A 再使用普通 select 语句去查询这条记录时就可以看到这条记录了,于是就发生了幻读。

所以MVCC机制并不能完全解决幻读

上一篇:数据库讲解---(数据更新、视图、数据控制)【MySQL版本】