事务的特性——原子性(实现原理)
事务的原子性是指一个事务中的所有操作是不可分割的,必须是一个逻辑单元,只能是全部执行成功或者全部执行失败。(典型例子:转账)。那么事务的原子性是如何保证的?在此之前我们先需要说一下MySQL中的WAL机制。
WAL机制
WAL全称为Write-Ahead Logging,预写日志系统。其主要是指MySQL在执行写操作的时候并不是立刻更新到磁盘上,而是先记录在日志中,之后在合适的时间更新到磁盘中。日志主要分为undo log、redo log、binlog。
事务原子性是如何保证的?
MySQL事务的原子性是通过undo log来实现的。磁盘存数据采用的是随机存储的方式,这就使得在存放数据的时候不仅需要记录下存放的数据值,还需要记录存放数据的地址,存储速度相对比较慢。而日志存储是连续存储,因此在存数据的时候只需要记录下首地址即可,其余数据记录偏移量,可以进一步提高性能。
每一个写事务,都会修改BufferPool,从而产生相应的Redo/Undo日志,这些日志信息会被记录到日志文件中。在MySQL中,任何BufferPool中的页被刷新到磁盘之前,都会先写入到日志文件中,如果BufferPool中的数据提交,此时数据库挂了,那么在数据库再次启动之后,就可以通过Redo日志来将其恢复出来,以此来保证写的数据不会丢失。如果数据没有提交,此时数据库挂了,就需要通过Undo日志来实现。
每一条数据变更(insert/update/delete)操作都伴随一条undo log的生成,并且回滚日志必须先于数据持久化到磁盘上。所谓的回滚就是根据回滚日志做逆向操作,比如delete的逆向操作为insert,insert的逆向操作为delete,update的逆向为update等。