核心逻辑就三个步骤

  1. 主库和从库同步数据,保证完全一致
  2. 配置主库和从库的数据库参数,从库设置只读
  3. 找到主库同步位点,启动同步流程

前言

很多人觉得 MySQL 主从复制、读写分离配置复杂、坑多,实则理清核心逻辑后,整体流程非常标准化。本文基于云服务器 + BT面板 + MySQL8.0 真实实操整理,全程落地可用,同时汇总所有高频踩坑点,零基础也能顺利搭建主从备份、读写分离架构。

核心逻辑就三个步骤

MySQL主从搭建、读写分离落地,归根结底只有三步,所有配置、命令、优化都是围绕这三点展开:

  1. 主库和从库同步数据,保证完全一致:初始化全量数据对齐,为增量同步打下基础

  2. 配置主库和从库的数据库参数,从库设置只读:区分主从身份、开启日志、优化环境,保障同步稳定

  3. 找到主库同步位点,启动同步流程:绑定主从链路,开启实时增量同步


一、第一步:主从数据初始化对齐(核心基础)

主从同步的前提是初始数据完全一致,否则启动同步后会出现主键冲突、表不存在等报错,直接导致同步中断。

1.1 主库一致性锁表(防止位点和数据变动)

首次搭建主从、全量数据同步时,需要锁定主库,避免导出数据期间主库产生新写入,造成数据不一致。

1
2
3
4
5
-- 锁定全局表,禁止写入,固定同步位点
FLUSH TABLES WITH READ LOCK;

-- 查看主库当前二进制日志位点(关键参数,后续从库需要用到)
SHOW MASTER STATUS;

执行完 SHOW MASTER STATUS 后,务必记录对应的 File(日志文件名)Position(位点值),这是主从同步的精准起点。

1.2 全量数据备份与导入

InnoDB引擎生产环境推荐无锁备份,不阻塞业务读写,实现数据快照一致性:

1
2
mysqldump -uroot -p --all-databases --master-data=2 --single-transaction > full_backup.sql

将导出的备份文件上传至从库服务器,导入从库数据库,完成主从初始数据完全对齐。数据导入完成后,解锁主库,恢复正常业务读写:

1
UNLOCK TABLES;

1.3 创建主从同步专属账号(仅主库操作)

主从同步需要独立的复制账号,仅授予复制权限,遵循最小权限原则。同时适配MySQL8.0加密规则,解决握手失败问题:

1
2
3
4
5
6
7
8
9
10
-- 清理旧冲突账号
DROP USER IF EXISTS 'repl'@'%';
DROP USER IF EXISTS 'repl'@'从库IP';

-- 创建兼容8.0的同步账号
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY '自定义密码';
-- 授予复制专属权限
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;

重点说明:同步账号 repl 只需在主库创建,主从库账号密码可以不一致,从库无需创建该账号,不影响同步链路。


二、第二步:主从参数配置,从库开启只读限制

数据对齐后,核心是修改 my.cnf 配置文件,区分主从身份、开启日志功能、优化云服务器环境,同时给从库配置只读,杜绝数据乱写入。

2.1 核心配置约束(必遵守)

  • server-id 全局唯一:主库、从库ID不能重复,主库默认1,从库默认2

  • 主从 sql-mode、字符集、表名大小写规则必须完全一致,避免同步报错

  • 云服务器必须开启 skip_name_resolve = 1,关闭DNS反向解析,解决公网握手超时、连接被拦截问题

2.2 主库完整 my.cnf 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
[client]
port = 3306
socket = /tmp/mysql.sock

[mysqld]
port = 3306
socket = /tmp/mysql.sock
connect_timeout = 120
datadir = /www/server/data
default_storage_engine = InnoDB
key_buffer_size = 32M
max_allowed_packet = 1G
table_open_cache = 1024
max_heap_table_size = 64M
sort_buffer_size = 768K
net_buffer_length = 4K
read_buffer_size = 768K
read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 8M
thread_cache_size = 16
tmp_table_size = 32M
lower_case_table_names = 1
default_authentication_plugin = mysql_native_password
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

explicit_defaults_for_timestamp = true
skip_name_resolve = 1
max_connections = 100
max_connect_errors = 10000
open_files_limit = 65535

# 主库核心binlog配置
log-bin=mysql-bin
binlog_format=ROW
server-id = 1
binlog_expire_logs_seconds = 600000

slow_query_log=1
slow-query-log-file=/www/server/data/mysql-slow.log
long_query_time=3
early-plugin-load = ""

# InnoDB优化配置
innodb_data_home_dir = /www/server/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /www/server/data
innodb_buffer_pool_size = 512M
innodb_log_file_size = 256M
innodb_log_buffer_size = 16M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
innodb_max_dirty_pages_pct = 90
innodb_read_io_threads = 2
innodb_write_io_threads = 2

[mysqldump]
quick
max_allowed_packet = 500M

[mysql]
no-auto-rehash

[myisamchk]
key_buffer_size = 32M
sort_buffer_size = 768K
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout

# 半同步主库配置(可选,提升数据一致性)
plugin-load-add=rpl_semi_sync_master.so
rpl_semi_sync_master=ON
rpl_semi_sync_master_wait_for_slave_count=1
rpl_semi_sync_master_wait_point=AFTER_SYNC

2.3 从库完整 my.cnf 配置(核心只读)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
[client]
port = 3306
socket = /tmp/mysql.sock

[mysqld]
port = 3306
socket = /tmp/mysql.sock
datadir = /www/server/data
default_storage_engine = InnoDB
key_buffer_size = 32M
max_allowed_packet = 1G
table_open_cache = 2048
sort_buffer_size = 768K
net_buffer_length = 4K
read_buffer_size = 768K
read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 8M
tmp_table_size = 64M
max_heap_table_size = 64M
lower_case_table_names = 1
default_authentication_plugin = mysql_native_password
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

explicit_defaults_for_timestamp = true
skip-name-resolve
max_connections = 500
max_connect_errors = 10000
open_files_limit = 65535

# 从库核心主从配置
server-id = 2
relay_log = relay-bin
log_bin = OFF
log_replica_updates = 0
# 双只读配置,彻底禁止写入(读写分离核心)
read_only = ON
super_read_only = ON
# 忽略系统库同步,减少资源消耗
replicate_ignore_db=mysql
replicate_ignore_db=information_schema
replicate_ignore_db=performance_schema
replicate_ignore_db=sys
# 仅同步业务库,自行替换为自己的业务库名
replicate_wild_do_table=hn_db.%

slow_query_log=1
slow-query-log-file=/www/server/data/mysql-slow.log
long_query_time=3
early-plugin-load = ""

# InnoDB优化配置
innodb_data_home_dir = /www/server/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /www/server/data
innodb_buffer_pool_size = 256M
innodb_log_file_size = 512M
innodb_log_buffer_size = 16M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
innodb_max_dirty_pages_pct = 90
innodb_read_io_threads = 2
innodb_write_io_threads = 2

[mysqldump]
quick
max_allowed_packet = 500M

[mysql]
no-auto-rehash

[myisamchk]
key_buffer_size = 32M
sort_buffer_size = 768K
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout

配置修改完成后,重启主从MySQL服务,让所有参数生效。


三、第三步:配置同步位点,启动主从同步

数据对齐、参数配置完成后,最后一步就是绑定主库信息、填写之前记录的同步位点,启动实时同步。

3.1 从库重置并配置同步链路

清空从库旧的同步记录,避免配置冲突,绑定主库IP、端口、同步账号和精准位点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 停止同步、清空历史同步信息
STOP SLAVE;
RESET SLAVE ALL;

-- 绑定主库同步信息(位点替换为自己主库 SHOW MASTER STATUS 查询的值)
CHANGE MASTER TO
MASTER_HOST='主库公网IP',
MASTER_PORT=3306,
MASTER_USER='repl',
MASTER_PASSWORD='同步账号密码',
MASTER_LOG_FILE='mysql-bin.000011',
MASTER_LOG_POS=11532;

-- 启动同步线程
START SLAVE;

3.2 同步状态校验(关键)

通过命令查看完整同步状态,排查异常:

1
2
SHOW SLAVE STATUS\G

正常同步标准

  • Slave_IO_Running: Yes(成功拉取主库binlog日志)

  • Slave_SQL_Running: Yes(成功执行日志、同步数据)

  • Slave_IO_State: Waiting for source to send event(实时监听主库新数据)

异常快速判断

  • IO线程异常:网络、安全组、账号密码、DNS解析问题

  • SQL线程异常:主从数据不一致、表结构差异、主键冲突


四、关键实操注意事项(避坑汇总)

4.1 同步重启恢复规则

MySQL8.0 默认将同步位点持久化到系统表,从库重启后,同步位点不会丢失。但通过 CHANGE MASTER TO 配置的主库连接信息为临时内存配置,重启MySQL后会失效,如需永久生效,可写入配置文件。

4.2 单条数据报错同步逻辑

若某一行数据同步出错,仅会暂停当前数据表的后续同步,其他数据表不受影响。生产环境禁止跳过报错,否则会造成永久数据不一致,需手动对齐主从数据后重启同步。

4.3 主库读写权限说明

仅首次全量初始化需要锁表,日常同步故障、重启从库、重新绑定位点,无需锁定主库,主库可正常读写业务数据,同步恢复后会自动追平断开期间的所有增量数据。

4.4 binlog日志过期风险

主库binlog日志会自动过期清理,若从库断开同步时间过久,主库清理了旧日志,增量同步会彻底失效,此时需要重新全量备份对齐数据,重建同步链路。

4.5 主从账号权限差异说明

同步专用repl账号主从密码、权限可不一致;但业务账号、root账号建议仅在主库操作,不要手动修改从库账号密码和权限,避免同步覆盖导致报错。


五、总结

MySQL主从备份、读写分离架构,核心始终围绕数据对齐、参数配置、位点同步三大步骤。看似坑多,实则所有报错和问题,基本都是参数不统一、网络拦截、数据初始不一致、账号授权异常导致。

按照本文标准化流程配置,搭配云服务器专属优化参数,可完美实现MySQL实时主从备份、读写分离,兼顾数据安全和业务查询性能。

修改后的主库完整配置参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
[client]
#password = your_password
port = 3306
socket = /tmp/mysql.sock

[mysqld]
port = 3306
socket = /tmp/mysql.sock
# 延长握手超时时间,默认10秒太短
connect_timeout = 120
datadir = /www/server/data
default_storage_engine = InnoDB
#skip-external-locking //因主从复制需要注释
key_buffer_size = 32M
max_allowed_packet = 1G
table_open_cache = 1024
max_heap_table_size = 64M
sort_buffer_size = 768K
net_buffer_length = 4K
read_buffer_size = 768K
read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 8M
thread_cache_size = 16
tmp_table_size = 32M
lower_case_table_names = 1
default_authentication_plugin = mysql_native_password
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

explicit_defaults_for_timestamp = true
#skip_name_resolve(云服务器必开 = 1)
skip_name_resolve = 1
max_connections = 100
max_connect_errors = 10000 #防止网络波动导致从库 IP 被主库拉黑断开同步
open_files_limit = 65535

log-bin=mysql-bin
binlog_format=ROW
server-id = 1
binlog_expire_logs_seconds = 600000
slow_query_log=1
slow-query-log-file=/www/server/data/mysql-slow.log
long_query_time=3
#log_queries_not_using_indexes=on
early-plugin-load = ""


innodb_data_home_dir = /www/server/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /www/server/data
innodb_buffer_pool_size = 512M
innodb_log_file_size = 256M
innodb_log_buffer_size = 16M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
innodb_max_dirty_pages_pct = 90
innodb_read_io_threads = 2
innodb_write_io_threads = 2

[mysqldump]
quick
max_allowed_packet = 500M

[mysql]
no-auto-rehash

[myisamchk]
key_buffer_size = 32M
sort_buffer_size = 768K
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout

# 半同步主库
plugin-load-add=rpl_semi_sync_master.so
rpl_semi_sync_master=ON
rpl_semi_sync_master_wait_for_slave_count=1
rpl_semi_sync_master_wait_point=AFTER_SYNC

修改后的从库完整配置参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
[client]
#password = your_password
port = 3306
socket = /tmp/mysql.sock

[mysqld]
port = 3306
socket = /tmp/mysql.sock
datadir = /www/server/data
default_storage_engine = InnoDB
#skip-external-locking
key_buffer_size = 32M
max_allowed_packet = 1G
table_open_cache = 2048
sort_buffer_size = 768K
net_buffer_length = 4K
read_buffer_size = 768K
read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 8M
#thread_cache_size = 16
tmp_table_size = 64M
max_heap_table_size = 64M
lower_case_table_names = 1
default_authentication_plugin = mysql_native_password
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

explicit_defaults_for_timestamp = true
skip-name-resolve
max_connections = 500
max_connect_errors = 10000
open_files_limit = 65535

# 从库核心复制配置
server-id = 2
relay_log = relay-bin
log_bin = OFF
log_replica_updates = 0
read_only = ON
super_read_only = ON
replicate_ignore_db=mysql
replicate_ignore_db=information_schema
replicate_ignore_db=performance_schema
replicate_ignore_db=sys
# 替换成你的业务库名
replicate_wild_do_table=hn_db.%

slow_query_log=1
slow-query-log-file=/www/server/data/mysql-slow.log
long_query_time=3
#log_queries_not_using_indexes=on
early-plugin-load = ""

innodb_data_home_dir = /www/server/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /www/server/data
innodb_buffer_pool_size = 256M
innodb_log_file_size = 512M
innodb_log_buffer_size = 16M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
innodb_max_dirty_pages_pct = 90
innodb_read_io_threads = 2
innodb_write_io_threads = 2

[mysqldump]
quick
max_allowed_packet = 500M

[mysql]
no-auto-rehash

[myisamchk]
key_buffer_size = 32M
sort_buffer_size = 768K
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout