什么是数据库的事务?
数据库事务是访问并可能操作各种数据项的一个数据库操作序列,这些要么全部执行,要么全部不执行
2.事务的四大特性?
- 原子性:包含事务的操作要么全部执行成功,要么全部执行失败并回滚
- 一致性:一致性是指事务在执行前后状态是一致的,保证事务按预期生效,即正确性
- 隔离性:一个事务所进行的修改在最终提交之前,对其他事务是不可见的
- 持久性:数据一旦提交,其所作的修改将永久的保存在数据库中
3.数据库的并发一致性问题
当多个事务并发执行时,可能出现以下问题
- 脏读:事务A更新了数据,当时还没有提交,这时事务B读取到事务A更新后的数据,然后事务A回滚了,事务B读取的数据就成为脏数据了
- 不可重复读:事务A对数据进行多次读取,事务B在事务A多次读取的过程中执行了更新操作并提交了,导致事务A多次读取到的数据并不一致
- 幻读:事务A在读取数据后,事务B向事务A多次读取的数据中插入了几条数据,事务A再次读取数据是发现多了几条数据,和之前读取的数据不一致
- 丢失修改:事务A和事务B都对同一个数据进行修改,事务A先修改,事务B后修改,事务B的修改覆盖了事务A的修改
不可重复读和幻读的主要区别:在不可重复读中,发现数据不一致主要是数据被更行了;而在幻读中,发现数据不一致主要是数据增多了或者减少了
4.数据库的隔离级别有哪些?
-
未提交读:一个事务在提交前,它的修改对其他事务也是可见的
-
提交读:一个事务提交之后,它的修改才能被其他事务看到
-
可重复读:在同一个事务中多次读取到的数据是一致的
-
串行化:需要加锁实现,会强制事务串行执行
隔离级别 脏读 不可重复读 幻读 未提交读 允许 允许 允许 提交读 不允许 允许 允许 可重复读 不允许 不允许 允许 串行化 不允许 不允许 不允许 MySQL的默认隔离级别是可重复读
5.隔离级别是如何实现的?
事务的隔离机制主要是依靠锁机制和MVCC(多版本并发控制)实现的,提交读和可重复读可以通过MVCC实现,串行化可以通过锁机制实现
6.❤什么是MVCC?
MVCC(多版本并发控制)是一种控制并发的方法,MVCC的作用就是在避免加锁的情况下最大限度解决读写并发冲突的问题,它可以实现提交读和可重复读两个隔离级别
在了解MVCC机制之前需要介绍几个概念:
-
ReadView(快照读):数据库中某一个时刻所有未提交事务的快照。
- 几个重要参数
- m_ids:表示生成ReadView时,当前系统正在活跃的读写事务的事务ID列表,数组里最小的id为min_id
- max_id:表示生成ReadView时,当前已创建的最大事务id
-
隐藏列
- 在InnoDB存储引擎中,它的聚簇索引记录中都包含两个必要的隐藏列,trx_id(事务id),roll_pointer(回滚指针)
-
undo日志
- MVCC使用到的快照会存储到Undo日志中,该日志通过回滚指针将一个一个数据行的所有快照连接起来。
对比规则:
1.如果落在绿色部分(trx_id < min_id),表示这个版本是已提交的事务生成的,这个数据是可见的
2.如果落在红色部分(trx_id>max_id),表示这个版本是有将来启动是事务生成的,是肯定不可见的
3.如果落在黄色(min_id <= trx_id <=max_id),分成两种情况
- 若row的trx_id在数组中,表示这个版本是由还没提交的事务生成的,不可见
- 若row的trx_id不在数组中,表示这个版本是已经提交了的事务生成的,可见
4.对于删除的情况可以认为是update的特殊情况,会将版本链上最新的数据复制一份,然后将trx_id修改成删除操作的trx_id,同时在该条记录的头信息里的(deleted_flag)标记为写上true,来表示当前记录已经被删除,在查询时按照上面的规则查到对应的记录若果delete_flag标记位为true,意味着已被删除,则不返回数据
RC隔离级别的事务在每次查询开始时都会生成一个独立的 ReadView。
RR隔离级别的事务在第一次读取数据时生成ReadView,之后的查询都不会再生成,所以一个事务的查询结果每次都是一样的。
7.❤既然用了MVCC,为什么还会出现幻读
mvcc本身是通过trx_id(事务隐藏列)来实现的版本维护,不能读取到ReadView开启时还没提交的事务的记录。
mysql里面实际上有两种读,
一种是“快照读”,比如我们使用select进行查询,就是快照读。在快照读的情况下不会产生幻读的问题。
另一种读则是“当前读”,例如delete,update,insert等语句,都需要满足直接忽略事务号读取最新数据的要求。
在快照读模式下可以解决幻读问题,但在当前读读模式下,仅仅依靠MVCC不能解决幻读问题,因为当前读必须获取最新数据