MySQL-5.7复制功能的默认设置改进

  • 1. 默认开启简化的GTID 恢复

      Binlog_gtid_simple_recovery=TURE(默认值)
      这个参数控制了当mysql启动或重启时,mysql在搜寻GTIDs时是如何迭代使用binlog文件的。

      这个选项设置为真,会提升mysql执行恢复的性能。因为这样mysql-server启动和binlog日志清理更快。该参数为真时,mysql-server只需打开最老的和最新的这2个binlog文件,gtid_purged参数的值和gtid_executed参数的值可以根据这些文件中的Previous_gtids_log_event 或者 Gtid_log_event计算得出。这确保了当mysql-server重启或清理binlog时,只需打开2个binlog文件。
       在MySQL-5.6中,调整这个选项设置也同样会提升性能,但是在一些特殊场景下,计算gtids值可能会出错。而保持这个选项值为false,能确保计算总是正确。
       在MySQL-5.7.7中,几乎不需要在速度和安全性之间做权限。设置该选项为TRUE总能得到正确的结果,除了以下2个极端场景:
       a. 最新的binlog是MySQL-5.7.5(或更老版本)产生的,并且gtid_mode对一些binlog设置为ON,但是对最新的binlog设置为OFF.
       b. GTID_PURGED的状态是MySQL-5.7.7之前的版本发布的,并且在当时激活清理的binlog在当前仍然没有清理完成。
       因此,开启这个选项几乎总是更好一些,所以这个选项默认开启。
       如果这个参数设置为off,在mysql恢复期间为了初始化gtid_executed,所有以最新文件开始的binlog都要被检查。并且为了初始化gtid_purged,所有的binlog都要被检查。这可能需要非常长的时间。

  • 2. 默认binlog格式调整为ROW格式

       Binlog-format=ROW(默认值)
       当开启binlog并且binlog格式设置为ROW模式时,每张表的行变动被写到binlog文件中,然后这些变动在从库端应用。这和使用statement格式binlog是不同的。在STATEMENT格式下,binlog会在从库端重新执行。
       所有的数据库变动都能被复制并且这是最安全的复制方式。同基于statement的复制相比,基于row的复制需要的行级锁定更少。在先前的默认statement格式下,不确定的状态可能会造成主从不一致的问题。

  • 3. 默认binlog错误后的操作调整为ABORT_SERVER

      Binlog_error_action=ABORT_SERVER
      Binlog_error_action参数控制当不能写binlog时,mysql-server将会采取什么行动。
      设置binlog_error_action=ABORT_SERVER会使mysql-server在写binlog遇到严重错误时退出,比如磁盘满了,文件系统不可写入了等。在ABORT_SERVER选项下,binlog和从库都是安全的,这是官方修改此默认值的原因。
      在先前的选项下(binlog_error_action=IGNORE_ERROR),如果一个错误发生,导致无法写入binlog,mysql-server会在错误日志中记录错误并强制关闭binlog功能。这会使mysql-server在不记录binlog的模式下继续运行,导致从库无法继续获取到主库的binlog。

  • 4. 默认开启mysql崩溃时的binlog安全

       MySQL崩溃时的binlog安全是sync_binlog参数控制的,这个参数的值代表了在把binlog刷新到磁盘前,提交的组的数量。
       当sync_binlog=1时,所有的事务都在提交前写入binlog。因此即使binlog事件遇到意外重启,一些在prepared状态的binlog会丢失。这导致服务器在恢复数据时自动回滚这些事务。这确保了从binlog不丢失事务,因此是最安全的选项。事实上,这增加了同步到磁盘的总次数。但是从MySQL5.6开始,已经支持组提交和合并同步了,这使得出现性能问题的可能性最小化了。
       当sync_binlog=0时,mysql-server并不把binlog同步到磁盘,而是依赖操作系统把binlog的内容同步到磁盘。因此,当出现掉电或操作系统崩溃时,很可能出现已经提交的事务没有被同步到磁盘的情况。因此mysql在自动恢复时无法恢复这些事务,他们从binlog中丢失了。

  • 5. 默认调低slave_net_timeout

      Slave_net_timeout定义了从库从主库获取数据等待的秒数,超过这个时间从库会主动退出读取,中断连接,并尝试重连。这个参数还影响了主从库之间心跳测试的频率,这个频率的默认值是slave_net_timeout除以2.
      Slave_net_timeout新的默认值是60,此前的默认值是3600秒。在老值下,长时间的复制延迟很可能是网络瞬断造成的。

  • 6. 取消会话级gtid_executed参数(@@session.gtid_executed)

    ‘@@global.gtid_executed’ 变量包括了所有记录在binlog中的事务的集合。
       当使用这个变量的会话级值时,他代表了写入事务缓存中的值。Session.gtid_executed只有在gtid_next是UUID:NUMBER并且至少一个DML语句已经被执行却没有提交时才同UUID:NUMBER的值相等。当GTID_NEXT 被设置为其他值是,session . GTID_EXECUTED包含一个空字符串。在MySQL5.7.7中如果使用这个会话级的变量会触发一个警告。对这个变量的全局级(@@global.gtid_executed)没有任何变化,因为这个参数使用频率更高并且当用户忘记提及global关键词时,他们会得到这个变量的会话级值,这个值很可能是不正确的。为了避免这个问题,我们取消了这个变量的会话级设置,同时也因为这个参数在应用中没有任何已知的价值。因此我们把他取消掉了。

  • 7. 基于组提交的并行复制(Enhanced Multi-threaded Slaves)   

      一般主从复制,有三个线程参与,都是单线程:Binlog Dump(主) ----->IO Thread (从) -----> SQL Thread(从)。复制出现延迟一般出在两个地方

      1)SQL线程忙不过来(可能需要应用数据量较大,可能和从库本身的一些操作有锁和资源的冲突;主库可以并发写,SQL线程不可以;主要原因)

      2)网络抖动导致IO线程复制延迟(次要原因)。

      MySQL从5.6开始有了SQL Thread多个的概念,可以并发还原数据,即并行复制技术。

  MySQL 5.6中,设置参数slave_parallel_workers = 4(>1),即可有4个SQL Thread(coordinator线程)来进行并行复制,其状态为:Waiting for an evant from Coordinator。

但是其并行只是基于Schema的,也就是基于库的。如果数据库实例中存在多个Schema,这样设置对于Slave复制的速度可以有比较大的提升。通常情况下单库多表是更常见的一种情形,

那基于库的并发就没有卵用。其核心思想是:不同schema下的表并发提交时的数据不会相互影响,即slave节点可以用对relay log中不同的schema各分配一个类似SQL功能的线程,

来重放relay log中主库已经提交的事务,保持数据与主库一致。

  在MySQL 5.7中,引入了基于组提交的并行复制(Enhanced Multi-threaded Slaves),设置参数slave_parallel_workers>0并且global.slave_parallel_type=‘LOGICAL_CLOCK’,

即可支持一个schema下,slave_parallel_workers个的worker线程并发执行relay log中主库提交的事务。其核心思想:一个组提交的事务都是可以并行回放(配合binary log group commit);slave机器的relay log中 last_committed相同的事务(sequence_num不同)可以并发执行。

  其中,变量slave-parallel-type可以有两个值:DATABASE 默认值,基于库的并行复制方式;LOGICAL_CLOCK:基于组提交的并行复制方式

      MySQL 5.7开启Enhanced Multi-Threaded Slave配置: 

# slave
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON

备库参数修改
# slave
slave_parallel-type=LOGICAL_CLOCK
#DATABASE 默认值,基于库的并行复制方式
#LOGICAL_CLOCK:基于组提交的并行复制方式

slave_parallel_workers=24
#并行的SQL线程数量,此参数只有设置 1<N的情况下才会才起N个线程进行SQL重做。
#经过测试对比发现, 如果主库的连接线程为M, 只有M < N的情况下, 备库的延迟才可以完全避免。
#否则,延迟一样的会存在,但是毕竟SQL重做线程从原来的一个,升级到现在的N个, 这个延迟在一定的主库TPS下会很短!

master_info_repository=TABLE
relay_log_info_repository=TABLE
#这两个参数会将master.info和relay.info保存在表中,默认是Myisam引擎,官方建议改为Innodb引擎,防止表损坏后自行修复。 
#alter table slave_master_info engine=innodb; 
#alter table slave_relay_log_info engine=innodb; 
#alter table slave_worker_info engine=innodb;

relay_log_recovery=ON
#当slave从库宕机后,假如relay-log损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的relay-log,并且重新从master上获取日志,这#样就保证了relay-log的完整性。默认情况下该功能是关闭的,将relay_log_recovery的值设置为 1时,可在slave从库上开启该功能,建议开启。

备库其他建议参数
提高备库的TPS,能够更好的缓解备库的延迟,有以下参数优化可以提高备库的性能:
2.1 关闭备库binlog
2.2 sync_binlog = 0 && innodb_flush_log_at_trx_commit=0
关闭备库的binlog校验。

        MTS可以实现更小粒度的并行复制,但需要将slave_parallel_type设置为LOGICAL_CLOCK,但仅仅设置为LOGICAL_CLOCK也会存在问题,因为此时在slave上应用事务的顺序是无序的,和relay log中记录的事务顺序不一样,这样数据一致性是无法保证的,为了保证事务是按照relay log中记录的顺序来回放,就需要开启参数slave_preserve_commit_order。

       开启该参数后,the executing thread waits until all previous transactions are committed before committing. While the slave thread is waiting for other workers to commit their transactions it reports its status as Waiting for preceding transaction to commit.

       所以虽然mysql5.7添加MTS后,虽然slave可以并行应用relay log,但commit部分仍然是顺序提交,其中可能会有等待的情况。

       当开启slave_preserve_commit_order参数后,slave_parallel_type只能是LOGICAL_CLOCK,如果你有使用级联复制,那LOGICAL_CLOCK可能会使离master越远的slave并行性越差。

       SHOW SLAVE STATUS适用于single sql thread,但在使用了MTS后,如果多个线程出现问题时,会不方便查看。在5.7的performance_schema数据库中,新加了一个监控replication的部分表: 

mysql> show tables like 'replication%';
+---------------------------------------------+
| Tables_in_performance_schema (replication%) |
+---------------------------------------------+
| replication_applier_configuration           |
| replication_applier_status                  |
| replication_applier_status_by_coordinator   |
| replication_applier_status_by_worker        |
| replication_connection_configuration        |
| replication_connection_status               |
| replication_group_member_stats              |
| replication_group_members                   |
+---------------------------------------------+
8 rows in set (0.00 sec)

       通过replication_applier_status_by_worker可以看到worker进程的工作情况:

mysql> select * from replication_applier_status_by_worker;
+--------------+-----------+-----------+---------------+--------------------------------------------+-------------------+--------------------+----------------------+
| CHANNEL_NAME | WORKER_ID | THREAD_ID | SERVICE_STATE | LAST_SEEN_TRANSACTION                      | LAST_ERROR_NUMBER | LAST_ERROR_MESSAGE | LAST_ERROR_TIMESTAMP |
+--------------+-----------+-----------+---------------+--------------------------------------------+-------------------+--------------------+----------------------+
|              |         1 |        32 | ON            | 0d8513d8-00a4-11e6-a510-f4ce46861268:96604 |                 0 |                    | 0000-00-00 00:00:00  |
|              |         2 |        33 | ON            | 0d8513d8-00a4-11e6-a510-f4ce46861268:97760 |                 0 |                    | 0000-00-00 00:00:00  |
+--------------+-----------+-----------+---------------+--------------------------------------------+-------------------+--------------------+----------------------+
2 rows in set (0.00 sec)

  

原文地址:https://www.cnblogs.com/vadim/p/7380471.html