mysql_0">什么是mysql事务?
事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
mysql_4">mysql事务特性
- 原子性:事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
- 一致性:事务完成时,必须使所有的数据都保持一致状态。
- 隔离性:数据库提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
- 持久性:事务一旦提交或回滚,它对数据库的改变就是永久的。
对于这ACID四大特性,其实分为两个部分,其中的原子性,一致性和持久化实际上是由InnoDB中的两份日志来保证的,一份是redo log日志。而隔离性是通过数据库的锁,加上MVCC来保证的。
redo log
重做日志,记录的是事务提交是数据页的物理修改,是用来实现事务的持久性。
该日志文件由两部分组成,重做日志缓冲(redo log buffer)以及重做日志文件(redo log file),前者是在内存中,后者在磁盘中,当事务提交之后会把所有修改信息都存到日志文件里,用于在刷新脏页到磁盘,发生错误时,进行数据恢复使用。
如果没有redo log,可能会发生的问题:
在InnoDB引擎中的内存结构中,主要的内存区域就是缓冲池,在缓冲池里缓存了很多数据页。在一个事务里,当执行多个增删改操作时,InnoDB会先操作缓冲池里的数据,如果缓冲区没有对应的数据,会先通过后台线程将磁盘中的数据加载出来,存放到缓冲区后,再对缓冲区里的数据进行增删改,修改之后的数据页称为脏页。而脏页会在一定的时机,通过后台线程刷新到磁盘里,从而保证缓冲区和磁盘里的数据一致。而缓冲区的数据不是实时刷新的,而是一段时间后刷新。假设**刷新到磁盘过程出错了,而提示给用户事务提交成功,**数据却没有持久化下来,这就没有保证事务的持久性。
引入redo log之后
对缓冲区的数据进行增删改之后,会先将操作的数据页的变化记录在redo log buffer中,在事务提交时将redo log buffer里的数据刷新到redo log磁盘文件里。过一段时间后,如果刷新到磁盘里的脏页出现错误,就可以借助redo log文件进行恢复,保证了事务的持久性。如果脏页刷新到磁盘或涉及到的数据已经落盘,redo log没有用之后,就可以进行删除了,所以存在两个redo log是循环写的。
为什么每一次提交事务,刷新到磁盘是redo log文件,而不是缓冲池里的脏页?
在业务操作中,操作数据一般都是随机读写磁盘的,而不是顺序读写磁盘。而redo log在往磁盘文件中写入数据,由于是日志文件,顺序写的,效率远大于随机写。这种先写日志的方式,称之为WAL。
undo log
回滚日志,用于记录数据被修改前的信息
作用(2个)
提供回滚(保证事务的原子性)和MVCC(多版本并发控制)。
undo log和redo log不一样,它是逻辑日志,当delete一条记录时,undo log中会记录一条与它相反的insert记录,当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容进行回滚。
- undo log销毁:undo log在事务执行时产生,事务提交时,并不会立即删除undo log,因为这些日志可能还会用于MVCC。
- undo log存储:采用段的方式进行管理和记录,存放在rollback segment回滚段中,内部包括1024个undo log
segment。
MVCC
(1)当前读:
读取的是记录的最新版本,读取时还保证其他并发事务不能修改当前记录,会对当前读取的记录进行加锁,例如:select … lock in share mode(共享锁),select … for update、update、insert、delete(排他锁)都是一种当前读。
(2)快照读:
简单的select(不加锁)就是快照读,读取的是记录数据的可见版本,可能是历史数据,不加锁,是非阻塞读。
- RC:每次select,都生成一个快照读。
- RR:开启事务后的第一个select才是快照读的地方。
- 串行化:快照读后退化为当前读。
(3)MVCC
多版本并发控制,指维护一个数据的多个版本,使得读写操作没有冲突,快照读为mysql实现mvcc提供了一个非阻塞读功能,mvcc的具体实现,还需要依赖于数据库记录中的三个隐藏字段,undo log日志,readView.
隐藏字段
创建表时,InnoDB会自动为我们添加三个隐藏字段
undo log日志
回滚日志,在insert,update,delete时产生的便于数据回滚的日志。
当insert时,产生的undo log日志只在回滚时需要,事务提交后自动删除。
而update,delete时,产生的回滚日志不仅在回滚时需要,在快照读时也需要,不会立即被删除。
readView
读视图是sql执行时mvcc提取数据的依据,记录并维护系统当前活跃的事务(未提交)id