learning_notes

学习笔记

View project on GitHub

日志

详细分析MySQL事务日志(redo log和undo log)

InnoDB并发如此高,原因竟然在这?

redo 和 undo

为了提高系统性能,减少随机I/O次数,每个事务记录的临时账

事务执行的阶段
  1. 写undo日志到log buffer
  2. 执行事务,并写redo日志到log buffer
  3. 如果innodb_flush_log_at_trx_commit=1,则将redo日志写到log file,并刷新落盘
  4. 提交事务

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写入到磁盘

  1. redo log buffer 占用的空间即将达到一半,后台线程会主动write,不fsync
  2. 并行事务提交的时候,顺带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

详细介绍mysqlbinlog

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%

  1. master开启bin-log功能,日志文件用于记录数据库的读写增删,开启I/O线程
  2. slave开启I/O线程,SQL线程
  3. slave通过I/O线程连接master,请求bin-log,position之后的内容
  4. master收到请求,返给slave数据
  5. slave收到数据,将bin-log写入relay-log中继日志
  6. 开启SQL线程,执行relay-log中的日志
主从复制延迟

主从复制延迟

  • 架构:
    • 从库数量(3-5),如果过多,复制延迟就高。
    • 5.7之后的版本采用多线程复制(一个组提交的事务都是可以并行回放 ),写并发大,来不及传送到从节点。
    • 增加cache层,降低主从库压力。
  • 硬件:
    • 如果从节点硬件不好,升级配置
  • 代码:
    • insert 和 update后sleep几秒(小系统)
    • 不要写慢sql