1.什么是MYSQL日志
MySQL日志是指 MySQL 数据库系统中记录的重要事件、查询、错误和性能信息的文件。 日志是数据库管理和诊断的重要工具,能够帮助管理员监控、排查问题、优化性能、以及进行故障恢复。
2.MYSQL的日志文件分类
①错误日志(Error Log):记录 MySQL 服务器启动、运行或停止时出现的问题。
②慢查询日志(Slow Query Log):记录执行时间超过long_query_time值的所有SQL语句。这个时间值是可配置的,默认情况下,慢查询日志功能是关闭的。可以用来识别和优化慢SQL。
③一般查询日志(General Query Log):记录所有 MySQL 服务器的连接信息及所有的 SQL 语句,不论这些语句是否修改了数据。
④二进制日志(Binary Log):记录了所有修改数据库状态的 SQL 语句,以及每个语句的执行时间,如 INSERT、UPDATE、DELETE 等,但不包括 SELECT 和 SHOW 这类的操作。
以及两个 InnoDB 存储引擎特有的日志文件:
⑤重做日志(Redo Log):记录了对于 InnoDB 表的每个写操作,不是 SQL 级别的,而是物理级别的,主要用于崩溃恢复。
⑥回滚日志(Undo Log,或者叫事务日志):记录数据被修改前的值,用于事务的回滚。
支持事务回滚,可以用来实现 MVCC,即多版本并发控制。
3.binlog
3.1.什么是binlog
binlog是一种物理日志,会在磁盘上记录下数据库的所有修改操作,以便进行数据恢复和主从复制。
当发生数据丢失时,binlog 可以将数据库恢复到特定的时间点。
主服务器(master)上的二进制日志可以被从服务器(slave)读取,从而实现数据同步。
默认没启动,要启动需要去配置文件配置参数。
3.2.binlog和redolog的区别
1)bin log会记录所有与数据库有关的日志记录,包括InnoDB、MyISAM等存储引擎的日志,而redo log只记InnoDB存储引擎的日志。
2)记录的内容不同,bin log记录的是关于一个事务的具体操作内容,即该日志是逻辑日志。而redo log记录的是关于每个页(Page)的更改的物理情况。
3)写入的时间不同,bin log仅在事务提交前进行提交,也就是只写磁盘一次。而在事务进行的过程中,却不断有 redo ertry 被写入redo log中。
4)写入的方式也不相同,redo log是循环写入和擦除,bin log是追加写入,不会覆盖已经写的文件。
4.更新语句的执行操作
4.1.执行流程
1)执行器先找引擎获取 ID=2 这一行。ID 是主键,存储引擎检索数据,找到这一行。如果 ID=2这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。
2)执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。
3)引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务。
4)执行器生成这个操作的 binlog,并把 binlog 写入磁盘。
5)执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。
4.2.为什么要两段提交
1)先写入 redo log,后写入 binlog:
在写完 redo log 之后,数据此时具有crash-safe能力(数据库崩溃后仍保持数据安全),因此系统崩溃,数据会恢复成事务开始之前的状态。但是,若在 redo log 写完时候,binlog 写入之前,系统发生了宕机。此时binlog没有对上面的更新语句进行保存,导致当使用 binlog 进行数据库的备份或者恢复时,就少了上述的更新语句。从而使得id=2这一行的数据没有被更新。
2)先写入 binlog,后写入 redo log:
写完 binlog 之后,所有的语句都被保存,所以通过 binlog 复制或恢复出来的数据库中 id=2 这一行的数据会被更新为 a=1。但是如果在 redo log 写入之前,系统崩溃,那么 redo log 中记录的这个事务会无效,导致实际数据库中id=2这一行的数据并没有更新。
4.3.redo.log
redo log是一种物理日志,记录了对数据页的物理更改。当事务进行写操作时,InnoDB 首先会写入 redo log,并不会立即修改数据文件。这种写入方式被称为“write-ahead logging”(先写日志)。
当 redo log 填满或在某些其他情况下,InnoDB 会异步将这些更改刷新到数据文件中。
系统崩溃时,由于数据可能还没有被真正写入数据文件,但已经在 redo log 中,因此系统可以在启动时使用这些日志来重新执行或“重做”这些更改,确保数据的持久性。
即使数据库在事务提交后立即崩溃,由于事务的更改已经记录在 redo log 中,这些更改在数据库恢复时仍然是安全的。
4.4.redolog刷入磁盘
redo log的写入不是直接落到磁盘,而是在内存中设置了一片称之为redo log buffer的连续内存空间,也就是redo 日志缓冲区。
什么时候会刷入磁盘?
在如下的一些情况中,log buffer 的数据会刷入磁盘:
1)log buffer 空间不足时
log buffer的大小是有限的,如果不停的往这个有限大小的 log buffer 里塞入日志,很快它就会被填满。如果当前写入 log buffer 的 redo 日志量已经占满了 log buffer 总容量的大约一半左右,就需要把这些日志刷新到磁盘上。
2)事务提交时
在事务提交时,为了保证持久性,会把 log buffer 中的日志全部刷到磁盘。注意,这时候,除了本事务的,可能还会刷入其它事务的日志。
3)后台线程输入
有一个后台线程,大约每秒都会刷新一次log buffer中的redo log到磁盘。
4)正常关闭服务器时
5)触发 checkpoint 规则
4.5.check point规则
重做日志缓存、重做日志文件都是以块(block)的方式进行保存的,称之为重做日志块(redo log block),块的大小是固定的 512 字节。我们的 redo log 它是固定大小的,可以看作是一个逻辑上的 log group,由一定数量的log block 组成。
它的写入方式是从头到尾开始写,写到末尾又回到开头循环写。
其中有两个标记位置:
write pos是当前记录的位置,一边写一边后移,写到第 3 号文件末尾后就回到 0 号文件开头。checkpoint是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到磁盘。
当write_pos追上checkpoint时,表示 redo log 日志已经写满。这时候就不能接着往里写数据了,需要执行checkpoint规则腾出可写空间。
所谓的checkpoint 规则,就是checkpoint触发后,将buffer中日志页都刷到磁盘。