今天有个朋友突然问到我这个问题,当我们的update语句执行过程中,服务器突然断电了会发生什么?其实这个问题主要在于对mysql update生命周期的理解,以及了解mysql 的redolog和binlog这两个日志的作用。
上一篇文章讲到mysql update的执行过程,MySQL update生命周期 。执行过程主要分为server层和存储引擎层两步操作,server层主要是创建连接和SQL的解析优化,存储引擎层主要是事务的执行和提交的操作。这里就不细讲了可以查看之前的文章或者其他论坛文章。
redolog 也叫预写式日志WAL(write-ahead logging),它是innoDB存储引擎层特有的一种日志。redolog 空间大小固定,可循环写。
type redo日志的类型(mlog_1byte、mlog_2byte、mlog_4byte、mlog_8byte、mlog_write_string);
space ID表空间ID;
page number 页号;
offset 数据修改的位置;
data 该条日志得具体数据内容,redolog是物理日志所以data里记录的是物理操作(例如:某个事务ID将哪张表空间的第几页中的哪个数据做了什么样的修改)。
redolog最终也是写入在磁盘中的,它写入在磁盘中是顺序IO因此它的性能是非常高的。
写入log buffer
redo log在写入时也不是直接写入磁盘中的,它是被写入到 一个大小为512字节的 redo log block页中。它先写入到 redo 日志缓冲区 (log buffer) 的内存区域中,该区域在MySQL启动时就会向操作系统申请,这片区域被划分为若干个连续的 block,可以通过启动选项 innodb_log_buffer_size 指定 log buffer 的大小。
redo日志刷盘
写入到log buffer内存后,需要将数据刷到磁盘中刷盘的策略主要有:1.当log buffer空间不足;2.当前的事务完整提交;3. 固定每秒刷盘一次;4.正常关闭服务器;
binlog也叫做归档日志,它是mysql server层的日志。不区分存储引擎,所有存储引擎都可以使用。binlog 日志是逻辑日志,记录的是sql语句的原始逻辑,binlog日志是以追加的方式写入在文件中并不会覆盖之前的日志。
1. mysql主从时做数据复制同步使用,binlog日志是二进制的文件所以它的复制性能会高。
2. 做容灾的数据恢复。
写入binglog cache
mysql服务器系统给每个线程分配一个binlog cache的内存块,当事务在执行的过程中,会把操作的日志写到binlog cache中,同一个事务的binlog日志不会被分开写入都是一次性写入到binlog cache中。如果是支持事务的存储引擎,必须要事务提交后才会写入日志。
binlog日志刷盘
binlog日志刷盘取决于sync_binlog参数的设置,表示每sync_binlog次事务提交则将日志刷新到磁盘。如果设置为0,则完全由文件系统去控制它缓存的刷新。因此未保证数据的完整性最好将sync_binlog设置为1,每次事务提交都刷新,但会对性能有所影响。
1. 如果在断电时 redolog 还没有写入,那么重启后将没有任何的数据变化。
2. 如果redolog 已经写入了但状态还在prepare时,binlog日志还没有写入,那么重启后会将事务进行回滚,数据也没有任何变化。
3. 如果redolog 已经写入了,binlog也写入了,但redolog日志还没commit, 那么重启后会检查binlog是否完整,如果完整则提交事务,数据发生变化,如果不完整则回滚事务,数据也不发生变化。