MYSQL中的事务日志
MYSQL日志
分类:
- redo log
- undo log
- binlog
redo log
- redolog是持久化在磁盘上的日志文件,记录的是对物理磁盘上数据的修改。
- 当数据发生修改时,innodb引擎会将记录写到redo log文件中,并更新内存,此时更新就算完成了,同时innodb引擎会在合适的时机记录操作到磁盘中。
- redo log 是固定大小的,是循环写过程。
- 有了redo log之后,innodb 就可以保证数据库即使宕机、发生异常,之前的记录也不会丢失。
- 用来保证事务的持久性
为什么要引入redo log日志?
MySQL支持用户自定义在commit时如何将log buffer中的日志刷log file中。这种控制通过变量 innodb_flush_log_at_trx_commit 的值来决定。该变量有3种值:0、1、2,默认为1。但注意,这个变量只是控制commit动作是否刷新log buffer到磁盘。
- 当设置为1的时候,事务每次提交都会将log buffer中的日志写入os buffer并调用fsync()(同步写)刷到log file on disk中。这种方式即使系统崩溃也不会丢失任何数据,- 但是因为每次提交都会进行一次IO操作,IO性能较差,频繁调用IO太影响性能。
- 当设置为2的时候,每次提交都仅写入到os buffer,然后是每秒调用fsync()将os buffer中的日志写入到磁盘,当系统崩溃时,数据也只写入了os buffer,数据会丢失。
- 当设置为0的时候,事务提交时就将对应的操作写入redo log buffer(而redo log是持久化在磁盘上的),然后每秒调用fsync()(同步写)将数据刷新到磁盘上,这样即使系统崩溃,数据也不会丢失,数据仍保留在redo log中。
- 注意:当设置为0的时候秒级调用fsync()将数据写入磁盘,这时批量操作,而设置为1是,是每次数据修改都将数据写入磁盘,是单次操作。
疑问
既然redo log是将数据持久化到磁盘上,那么必然也对应一次IO操作,那么每次修改数据直接将其刷新到磁盘的话,也是一次IO操作,按道理说效率应该一样低下,那么为什么还要引入redo log?
事实上,redo log写入文件尾是顺序写过程,虽然也是一次IO操作但磁头不需要移动。而每次都将数据更新到磁盘其实是将 buffer pool中的数据缓存页写入磁盘的数据也中,其中涉及到要寻找数据页在哪的操作,这是一个随机写过程,需要移动磁头,磁盘的随机写过程更耗时,耗资源,因此引入redo log是很有必要的。
undo log
- undo log用来实现事务的原子性,在innnodb引擎中还用来实现事务的多版本并发控制
- 在操作数据库之前先将数据备份到一个地方,这个存储数据备份的地方就是undo log。然后再进行数据的修改,如果中途发生错误或者用户执行的rollback语句,系统利用undo log中的备份将数据回复到事务开始前的状态
- redo log 是逻辑日志,可以理解为
- 当delect一条语句时,undo log 中会记录一条对应的insert语句
- 当insert一条语句时,undo log 中会记录一条对应的delect语句
- 当update一条语句时,undo log 中会记录一条相反的update语句
binlog
- binlog是server层的日志,主要做mysql功能层的事情
- binlog会记录所有的逻辑,并采用追加写的方式
- 一般企业中数据库会有备份系统,可以定期执行备份
- 利用binlog进行数据恢复
- 找到最近一次的全量备份数据
- 从备份的时间点将binlog取出来,重放到要恢复的时刻
binlog与redolog 的区别
- redo log 是innodb引擎特有的,而binlog是所有存储引擎都可以使用的
- redo log是物理日志,记录的是某页上具体的做的修改。binlog是逻辑日志,记录的是这个语句的原始逻辑。
- redo log是循环写过程,空间有限,空间不够时会覆盖之前的信息。binlog是追加写过程不会覆盖之前的信息。