MySQL日志
# MySQL日志
MySQL 常见日志:bin log、redo log、undo log
MySQL日志包括:误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。其中比较重要的日志为以下三个:
bin log
:二进制日志(归档日志),属于MySQL Server层redo log
:事务日志(重做日志),属于 InnoDB 存储引擎层undo log
:回滚日志,属于 InnoDB 存储引擎层
# redo log
⭐ Buffer Pool 缓冲池
MySQL中数据以页为单位,你查询一条记录,会从硬盘中读取出一页的数据,加载出来的数据叫数据页,会放到 Buffer Pool 中。后续的查询都是先从Buffer Pool中找,没有命中再去硬盘加载,减少硬盘IO开销,提升性能。
更新表数据的时候,也是如此,发现Buffer Pool里存在要更新的数据,就直接在 Buffer Pool 里更新。
然后再把「在某个数据页上做了什么修改」记录到重做日志缓存(redo log buffer)里,接着刷盘到redo log文件里。
理想情况,事务提交就会进行刷盘操作,但实际上,刷盘的实际是根据策略来进行的。
redo log的刷盘策略有三种,可通过innodb_flush_log_at_trx_commit
参数进行设置:
- 0:每次事务提交时不进行刷盘操作
- 1:每次事务提交时都进性刷盘操作(默认值)
- 2:每次事务提交时都只把redo log buffer内容写进page cache
⭐ redo log 重做日志
InnoDB 存储引擎以页(16KB)为单位来存储管理空间,真正访问页面之前,需要先把磁盘中的数据加载到内存的 Buffer Pool 之中才可以访问。如果我门只在内存的 Buffer Pool 中修改页面并提交事务,如果此时出现故障导致宕机,数据库中的数据将会丢失。但是,当我们每次提交事物后,都将数据页刷新到磁盘是非常低效的。因为:
- 刷新一个完整的数据页太浪费,因为即使只修改一个字节也要刷新 16KB 的数据到磁盘;
- 随机 I/O 刷新起来比较慢,一个事务包含很多语句,且这些语句对应的数据页不相邻,需要多次随机 I/O。
因此,我们不需要在每次提交事务时就把该事务在内存中修改过的全部数据刷新到磁盘,只需把修改的内存记录一下就好如:
将第 0 号表空间第 100 号页面中偏移量为 1000 处的值更新为 2
在系统崩溃而重启时需要按照上述所记录的步骤重新更新数据页,redo 日志的好处有:
- redo 日志占用用空间小
- redo 日志是顺序写入磁盘的:在执行事务的过程中,每执行一条语句,就可能产生若干条 redo 日志,这些日志按顺序写入磁盘,也就是顺序 I/O
# undo log
⭐ 事务回滚
要想保证事务的原子性,就需要在异常发生时,对已经执行的操作进行回滚,在 MySQL 中,恢复机制时通过回滚日志实现的。所有事务进行的修改都会先记录到整个回滚日志中,然后再执行相关的操作。如果执行过程中遇到异常的话,就直接利用回滚日志中的信息将数据回滚到修改之前的样子即可。并且回滚日志会优先于数据持久化。这样就保证了即使遇到数据库突然宕机等情况,当用户再次启动数据库的时候,数据库还能够通过查询回滚日志来回滚之前未完成的事务。
⭐ MVCC 实现
MVCC 的实现依赖于:隐藏字段、Read View、undo log。InnoDB 通过数据行的 DB_TRX_ID 和 Read View 来判断数据的可见性,如不可见,则通过数据行的 DB_ROLL_PTR 找到 undo log 中的历史版本。
# bin log
bin log
是二进制日志文件,是 MySQL 中比较重要的日志,和运维息息相关。它记录了所有更新数据库的语句(如DDL
和 DML
语句)并以二进制的形式保存在磁盘中,但是不包含没有修改任何数据的语句(如数据查询语句 select、show 等)。
redo log 它是物理日志,记录内容是“在某个数据页上做了什么修改”,属于 InnoDB 存储引擎。
bin log 是逻辑日志,记录内容是语句的原始逻辑,类似于「给 ID=2 这一行的 c 字段加 1」,属于 MySQL Server 层。
不管用什么存储引擎,只要发生了表数据更新,都会产生 bin log 日志。
# 主要作用
- 数据恢复:MySQ L可以通过
bin log
恢复某一时刻的误操作的数据,是 DBA 常打交道的日志。 - 数据复制:MySQL 的数据备份、集群高可用、读写分离都是基于
bin log
的重放实现的。
binlog 会记录所有涉及更新数据的逻辑操作,并且是顺序写。
# 写入时机
事务执行过程中,会先把日志写到binlog cache
中去,事务提交时,才把binglog cache
写到binlog
文件中去(刷盘)。binlog cache
是为了保证一个事务的所有操作能够一次性写入bin log
不被拆开而设置的缓存,binlog cache
大小受binlog_cache_size
参数控制。
上图binlog cache
写到bin log
日志文件的过程包含了write
和fsync
两步操作:
write
是把日志写到文件系统缓存中,这一步是系统为了提高文件IO效率;fsync
是把数据持久化到日志文件中去。
写入策略受 sync_binlog
参数控制,默认 0
sync_binlog = 0
:表示每次提交事务都只write
,由操作系统自行判断什么时候执行fsync
。- 优点:性能提升;
- 缺点:但是如果机器宕机,
page cache
里的bin log
会丢失。
sync_binlog = N
:表示每次提交事务都只write
,积攒 N 个事务后才执行fsync
。- 优点:机器宕机只丢失 N 个事务的
bin log
; - 缺点:如果 N 设置的很小可能会出现IO瓶颈,需要适当调整 N 的大小。
- 优点:机器宕机只丢失 N 个事务的
参考