MySQL事务
ACID
原子性:事物是一个不可分割的工作单位,事物中的操作要么都发生,要么都不发生
一致性:数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性
隔离性:多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果
持久性:事务一旦提交,则持久化保存在数据库中,不会被回滚
脏读,不可重复读,幻读
脏读:
(读取了未提交的新事物,然后被回滚了)
不可重复读:指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了
(读取了提交的新事物,指更新操作)
幻读:在事务A多次读取构成中,事务B对数据进行了新增操作,导致事务A多次读取的数据不一致。
(也是读取了提交的新事物,指增删操作)
两类事物丢失
第一类事物丢失(回滚丢失)
A和B同时在执行一个数据,然后B事物已经提交了,然后A事物回滚了,这样B事物的操作就因A事物回滚而丢失了
第二类事物丢失(提交覆盖丢失)
A和B一起执行一个数据,两个同时取到一个数据,然后B事物首先提交,但是A事物加下来又提交,这样就覆盖了B事物
隔离级别
读未提交
写操作加写锁,读操作不加锁。禁止第一类丢失更新,但是会出现所有其他数据并发问题
读已提交
写操作加写锁,读操作加读锁。禁止第一类丢失更新和脏读。已经开始读了数据,然后一个事物开始写,然后写的事物不提交的话,是不能进行读的事物,避免了脏读
可重复读
对于读操作加读锁到事务结束,其他事务的更新操作只能等到事务结束之后进行。和提交 读的区别在于,提交读的读操作是加读锁到本次读操作结束,可重复读的锁粒度更大。禁止两类丢失更新,禁止脏读和不可 重复度,但是可能出现幻读
序列化
对表级读写加锁, 读操作加表级读锁至事务结束。可以禁止幻读
MVCC
MVCC通过保存数据的历史版本,根据比较版本号来处理数据的是否显示,从而达到读取数据的时候不需要加锁就可以保证事务隔离性的效果
事务版本号
每次事务开启前都会从数据库获得一个自增长的事务ID,可以从事务ID判断事务的执行先后顺序
表格的隐藏列
DB_TRX_ID: 记录操作该数据事务的事务ID
DB_ROLL_PTR:指向上一个版本数据在undo log 里的位置指针
DB_ROW_ID: 隐藏ID ,当创建表没有合适的索引作为聚集索引时,会用该隐藏ID创建聚集索引
Undo log
Undo log 主要用于记录数据被修改之前的日志,在表信息修改之前先会把数据拷贝到undo log 里,当事务进行回滚时可以通过undo log 里的日志进行数据还原
- 保证事务进行rollback时的原子性和一致性,当事务进行回滚的时候可以用undo log的数据进行恢复
- 用于MVCC快照读的数据,在MVCC多版本控制中,通过读取undo log的历史版本数据可以实现不同事务版本号都拥有自己独立的快照数据版本
Read view
在innodb 中每个SQL语句执行前都会得到一个read_view。副本主要保存了当前数据库系统中正处于活跃(没有commit)的事务的ID号,其实简单的说这个副本中保存的是系统中当前不应该被本事务看到的其他事务id列表
快照读和当前读
快照读
快照读是指读取数据时不是读取最新版本的数据,而是基于历史版本读取的一个快照信息(mysql读取undo log历史版本) ,快照读可以使普通的SELECT 读取数据时不用对表数据进行加锁,从而解决了因为对数据库表的加锁而导致的两个如下问题
1. 解决了因加锁导致的修改数据时无法对数据读取问题
2. 解决了因加锁导致读取数据时无法对数据进行修改的问题
当前读
当前读是读取的数据库最新的数据,当前读和快照读不同,因为要读取最新的数据而且要保证事务的隔离性,所以当前读是需要对数据进行加锁的(Update delete insert select ....lock in share mode select for update 为当前读)