Mysql主从复制之skip-slave-start,slave-parallel-type,slave-parallel-workers参数详解和测试

参数1)skip-slave-start = 0

参数详解:禁用skip-slave-start,slave进程会随着mysql启动而启动。skip-slave-start=1为开启

测试:当前slave的查不到该参数,且/etc/my.cnf也没有配置该文件,重启服务后,发现slave进程自动启动,且停服务期间master插入的数据也复制过来了,看了这个参数默认是skip-slave-start = 0

root@localhost:mytest1\]\>show global variables like '%slave-start%'; Empty set (0.01 sec) \[mysql@t3-dtpoc-dtpoc-web05 bin\]$ service mysql stop Shutting down MySQL.. SUCCESS! \[mysql@t3-dtpoc-dtpoc-web05 bin\]$ service mysql start Starting MySQL. SUCCESS! \[root@localhost:mytest1\]\>show slave status\\G; Slave_IO_Running: Yes Slave_SQL_Running: Yes \[root@localhost:mytest1\]\>select \* from t1; +------+------+ \| id \| name \| +------+------+ \| 8888 \| tsss \| \| 9999 \| jjjj \| +------+------+ 2 rows in set (0.00 sec) 我们在/etc/my.cnf写入这个参数skip-slave-start=1,然后重启服务,发现slave进程没有自动启动,停服务期间master端插入的数据也没有复制过来,说明参数生效了,看起来这个参数好像没有什么用,因为我们总是希望备机重启时自动启动slave。但是如果因为主库一个没有主键的大表整表update或者delete,从库追平日志需要一个月时间,这个时候停掉slave没有任何反应,因为slave会把当前事务复制完才会停下来,类似于CDC的停复制停不下来需要强制停掉。这个时候重启数据库服务也无法停止,只能Kill -9 杀掉mysql进程,重启服务后发现slave又从头开始复制了,这个时候你怎么办?可以skip-slave-start=1,让slave不自动启动 \[root@localhost:mytest1\]\>show slave status\\G; Slave_IO_Running: No Slave_SQL_Running: No \[root@localhost:mytest1\]\>select \* from t1; +------+------+ \| id \| name \| +------+------+ \| 8888 \| tsss \| \| 9999 \| jjjj \| +------+------+ 2 rows in set (0.00 sec) 参数2)slave-parallel-type = LOGICAL_CLOCK slave-parallel-workers = 16 参数详解:mysql在5.7中加入了slave_parallel_type,默认值是database,需要改成基于时钟逻辑的LOGICAL_CLOCK。slave_parallel_workers数,默认为0,按需修改,可以根据服务器的配置来开启相应的并行度。将slave_parallel_type设置为'LOGICAL_CLOCK',slave_parallel_workers设置为大于0的值,即算是开启了并行复制 当前使用的是默认值: \[root@localhost:mytest1\]\>show variables like '%slave_parallel%'; +------------------------+----------+ \| Variable_name \| Value \| +------------------------+----------+ \| slave_parallel_type \| DATABASE \| \| slave_parallel_workers \| 0 \| +------------------------+----------+ 2 rows in set (0.00 sec) 我们在/etc/my.cnf写入这个参数slave-parallel-type = LOGICAL_CLOCK,slave-parallel-workers = 16然后重启服务,发现已经有16个复制线程了 注意将这个database修改为logical_clock,在此之前,需要先关闭sql_thread stop slave sql_thread; set global slave_parallel_type='LOGICAL_CLOCK'; start slave sql_thread; select \* from performance_schema.replication_applier_status_by_worker; \[root@localhost:mytest1\]\>select \* from performance_schema.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 \| 27 \| ON \| ANONYMOUS \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 2 \| 28 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 3 \| 29 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 4 \| 30 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 5 \| 31 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 6 \| 32 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 7 \| 33 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 8 \| 34 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 9 \| 35 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 10 \| 36 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 11 \| 39 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 12 \| 40 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 13 \| 41 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 14 \| 42 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 15 \| 43 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 16 \| 44 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| +--------------+-----------+-----------+---------------+-----------------------+-------------------+--------------------+----------------------+ 16 rows in set (0.00 sec) 我们来测试下,对于没有主键的单表的全表更新有没有性能提升?我们之前做过测试对于Log_test的更新,可以看到5分钟的时间,从库更新了不到10000行数据(28300-8962=19338行)。 而开启并发以后发现5分钟的时间,从库更新了31228-14650=16578行,性能并没有提升。可以分析是因为对于一个事务只能有一个线程执行,所有并没有触发并发 \[root@localhost:mytest1\]\>set transaction_isolation='READ-UNCOMMITTED'; Query OK, 0 rows affected (0.00 sec) \[root@localhost:mytest1\]\>select now(); +---------------------+ \| now() \| +---------------------+ \| 2023-09-12 10:34:24 \| +---------------------+ 1 row in set (0.00 sec) \[root@localhost:mytest1\]\>select count(\*) from log_test where id\>80000000; +----------+ \| count(\*) \| +----------+ \| 14650 \| +----------+ 1 row in set (2.18 sec) \[root@localhost:mytest1\]\>select now(); +---------------------+ \| now() \| +---------------------+ \| 2023-09-12 10:39:24 \| +---------------------+ 1 row in set (0.00 sec) \[root@localhost:mytest1\]\>select count(\*) from log_test where id\>80000000; +----------+ \| count(\*) \| +----------+ \| 31228 \| +----------+ 1 row in set (3.04 sec) 我们来测试下,对于没有主键的两个表的全表更新,从库会不会两张表并发复制?复制效率怎么样? 主端插入log_test400W行数据,然后创建表log_test1,再插入log_test1 400W行,发现从库只有把log_test400W行数据全复制完后才会创建log_test1然后再插入,说明并发复制并不会并发事务 \[root@localhost:mytest1\]\>select count(\*) from log_test1; ERROR 1146 (42S02): Table 'mytest1.log_test1' doesn't exist \[root@localhost:mytest1\]\>select count(\*) from log_test; +----------+ \| count(\*) \| +----------+ \| 8000000 \| +----------+ 1 row in set (5.26 sec) \[root@localhost:mytest1\]\>select count(\*) from log_test1; +----------+ \| count(\*) \| +----------+ \| 299012 \| +----------+ 1 row in set (0.13 sec) 再次确认并发是打开的,主库更新两张表后,从库一直在更新一张表,说明事务并没有并发,这和预期不符啊,这算什么并发啊。 \[root@localhost:mytest1\]\>select \* from performance_schema.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 \| 31 \| ON \| ANONYMOUS \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 2 \| 32 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 3 \| 33 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 4 \| 34 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 5 \| 35 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 6 \| 36 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 7 \| 37 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 8 \| 38 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 9 \| 39 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 10 \| 40 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 11 \| 41 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 12 \| 42 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 13 \| 43 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 14 \| 44 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 15 \| 45 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 16 \| 46 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| +--------------+-----------+-----------+---------------+-----------------------+-------------------+--------------------+----------------------+ 16 rows in set (0.00 sec) \[root@localhost:mytest1\]\>select count(\*) from log_test where id\>80000000; +----------+ \| count(\*) \| +----------+ \| 20970 \| +----------+ 1 row in set (4.55 sec) \[root@localhost:mytest1\]\>select count(\*) from log_test1 where id\>80000000; +----------+ \| count(\*) \| +----------+ \| 0 \| +----------+ 1 row in set (2.29 sec) 我们注意到只有第一个线程的LAST_ERROR_NUMBER不为空是ANONYMOUS,有可能是gtid_mode是OFF导致不能并发,接下来继续测试 \[root@localhost:mytest1\]\>show variables like '%gtid_mode%'; +---------------+-------+ \| Variable_name \| Value \| +---------------+-------+ \| gtid_mode \| OFF \| +---------------+-------+ 1 row in set (0.00 sec) 在主库和从库的/etc/my.cnf都写入GTID的设置,然后重启服务,测试无主键的单表全表更新发现还是单线程在复制该事务,5分钟的时间,从库更新了28767-5280=23487行 #GTID相关 enforce_gtid_consistency = 1 gtid_mode = on \[root@localhost:mytest1\]\>show variables like '%gtid_mode%'; +---------------+-------+ \| Variable_name \| Value \| +---------------+-------+ \| gtid_mode \| ON \| +---------------+-------+ 1 row in set (0.01 sec) \[root@localhost:mytest1\]\>select now(); +---------------------+ \| now() \| +---------------------+ \| 2023-09-12 14:07:39 \| +---------------------+ 1 row in set (0.00 sec) \[root@localhost:mytest1\]\>select count(\*) from log_test where id\>80000000; +----------+ \| count(\*) \| +----------+ \| 5280 \| +----------+ 1 row in set (2.44 sec) \[root@localhost:mytest1\]\>select now(); +---------------------+ \| now() \| +---------------------+ \| 2023-09-12 14:12:39 \| +---------------------+ 1 row in set (0.00 sec) \[root@localhost:mytest1\]\>select count(\*) from log_test where id\>80000000; +----------+ \| count(\*) \| +----------+ \| 28767 \| +----------+ 1 row in set (2.30 sec) \[root@localhost:mytest1\]\>select \* from performance_schema.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 \| 6797f03c-2122-11ee-842b-00505695c6d5:8 \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 2 \| 33 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 3 \| 34 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 4 \| 35 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 5 \| 36 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 6 \| 37 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 7 \| 38 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 8 \| 39 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 9 \| 40 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 10 \| 41 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 11 \| 42 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 12 \| 43 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 13 \| 44 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 14 \| 45 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 15 \| 46 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 16 \| 47 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| +--------------+-----------+-----------+---------------+----------------------------------------+-------------------+--------------------+----------------------+ 16 rows in set (0.00 sec) 我们来测试下,对于没有主键的两个表的全表更新,发现还是单线程在工作,执行完插入log_test的事务才开始执行插入Log_test1的事务,并没有并发。 \[root@localhost:mytest1\]\>select \* from performance_schema.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 \| 6797f03c-2122-11ee-842b-00505695c6d5:11 \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 2 \| 33 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 3 \| 34 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 4 \| 35 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 5 \| 36 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 6 \| 37 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 7 \| 38 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 8 \| 39 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 9 \| 40 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 10 \| 41 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 11 \| 42 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 12 \| 43 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 13 \| 44 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 14 \| 45 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 15 \| 46 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| \| \| 16 \| 47 \| ON \| \| 0 \| \| 0000-00-00 00:00:00 \| +--------------+-----------+-----------+---------------+-----------------------------------------+-------------------+--------------------+----------------------+ 16 rows in set (0.00 sec) \[root@localhost:mytest1\]\>select count(\*) from log_test; +----------+ \| count(\*) \| +----------+ \| 872638 \| +----------+ 1 row in set (0.47 sec) \[root@localhost:mytest1\]\>select count(\*) from log_test1; +----------+ \| count(\*) \| +----------+ \| 0 \| +----------+ 1 row in set (0.00 sec)

相关推荐
深念Y15 小时前
中兴微随身WiFi 板号UZ901_v1.6 影腾Y1新版本 增加SIM卡槽 开启ADB 去云控 改串号教程 下
数据库·adb
yantaohk15 小时前
【2025亲测】中兴B860AV3.2M完美刷机包ATV版本安卓9-解决1G运存BUG,开ADB已ROOT
android·嵌入式硬件·adb·云计算
远方之巅15 小时前
ADB调试工具与GLM-4.6V-Flash-WEB移动端集成实战
adb· glm-4.6v-flash-web· 多模态模型
爱技术的小伙子20 小时前
【 Docker 快速部署 MySQL 8.0(2026最新实践)—— 一键启动 + 数据持久化 + 常见优化】
mysql·adb·docker
橘子1321 小时前
MySQL表的内外连接(九)
数据库·mysql·adb
betazhou2 天前
mysql备份脚本
android·mysql·adb·数据库备份
卿着飞翔2 天前
ubuntu上的mysql远程连不上root
mysql·ubuntu·adb
小句2 天前
MySQL慢查询日志详细使用指南
数据库·mysql·adb
L1624763 天前
KeepAlived 搭建 MySQL 双主模式高可用集群(详细安装配置教程)
数据库·mysql·adb
L1624763 天前
基于 Xenon 实现 MySQL 高可用集群(完整配置教程,含监控告警 + 定时备份)
android·mysql·adb