日志
详细分析MySQL事务日志(redo log和undo log)
redo 和 undo
为了提高系统性能,减少随机I/O次数,每个事务记录的临时账
事务执行的阶段
- 写undo日志到log buffer
- 执行事务,并写redo日志到log buffer
- 如果innodb_flush_log_at_trx_commit=1,则将redo日志写到log file,并刷新落盘
- 提交事务
redo log
redo log : 数据前滚操作,保存在文件ib_logfile0
,循环写入,将checkPoint点推进,数据刷盘
redo log buffer是全局共享
mysql> show global variables like "%innodb_log%";
+-----------------------------+----------------------+
| Variable_name | Value |
+-----------------------------+----------------------+
| innodb_log_buffer_size | 8388608 | #默认 8M
| innodb_log_file_size | 134217728 | #默认 1G
| innodb_log_files_in_group | 2 | #文件个数2
| innodb_log_group_home_dir | /usr/local/mysql/var |
| innodb_flush_log_at_trx_commit | 1 | #日志何时刷盘 0:只更新buffer 1:fsync刷盘 2:write(page cache)
+-----------------------------+----------------------+
redo log和change buffer
- change buffer:更新数据缓存起来,不必每次访问磁盘,解决的是随机读磁盘的io消耗,如果修改的是唯一索引,不使用change buffer
- redo log:解决的是随机写磁盘的io消耗
- merge: 将change buffer的操作应用到数据页的过程称为 merge。除了访问数据页会触发 merge 外;系统后台有线程会定期 merge;数据库正常关闭的过程中也会触发 merge 操作
redo log的写入机制
除了后台每秒一次的轮询操作外,还有2种场景会让一个没有提交的事务redo log写入到磁盘
- redo log buffer 占用的空间即将达到一半,后台线程会主动write,不fsync
- 并行事务提交的时候,顺带write
undo log
数据回滚操作,也叫回滚段,每个回滚段中有1024个undo log segment,默认保存在共享表空间ibdata1
,如果设置innodb_file_per_table
,将放在每个表的.ibd文件中
# 默认配置
mysql> show global variables like "%undo%";
+--------------------------+------------+
| Variable_name | Value |
+--------------------------+------------+
| innodb_max_undo_log_size | 1073741824 |
| innodb_undo_directory | ./ |
| innodb_undo_log_truncate | OFF |
| innodb_undo_logs | 128 |
| innodb_undo_tablespaces | 0 |
+--------------------------+------------+
binlog
binlog写入机制
一个事务的binlog,不能拆开,系统为每个mysql线程分配一片内存 binlog cache
,超过限制就暂存到磁盘,由参数binlog_cache_size=32768
设置
写入顺序: binlog cache->write(page cache)->fsync(磁盘)
#每次提交事务,不同参数影响
sync_binlog=0 #只写write,不fsync
sync_binlog=1 #fsync
sync_binlog=N(N>1) #每次事务都write,但累计N个事务才fsync
binlog_group_commit_sync_delay=0 #binlog 延迟组提交
binlog_group_commit_sync_no_delay_count=0 #binlog 达到多少数量
cash-safe保证
redo log 和binlog 基于二阶段提交协议
#1. 预处理阶段
redo log prepare(write)->fsync
binlog (write)->fsync
#2. 提交
redo log commit
checkpoint(检查点)
checkpoint是为了定期将db buffer的内容刷新到data file。当遇到内存不足、db buffer已满等情况时,需要将db buffer中的内容/部分内容(特别是脏数据)转储到data file中。在转储时,会记录checkpoint发生的”时刻“。 在故障恢复时候,只需要redo/undo最近的一次checkpoint之后的操作
根据binlog主从同步过程
性能损耗:1%
- master开启bin-log功能,日志文件用于记录数据库的读写增删,开启I/O线程
- slave开启I/O线程,SQL线程
- slave通过I/O线程连接master,请求bin-log,position之后的内容
- master收到请求,返给slave数据
- slave收到数据,将bin-log写入relay-log中继日志
- 开启SQL线程,执行relay-log中的日志
主从复制延迟
- 架构:
- 从库数量(3-5),如果过多,复制延迟就高。
- 5.7之后的版本采用多线程复制(一个组提交的事务都是可以并行回放 ),写并发大,来不及传送到从节点。
- 增加cache层,降低主从库压力。
- 硬件:
- 如果从节点硬件不好,升级配置
- 代码:
- insert 和 update后sleep几秒(小系统)
- 不要写慢sql