MySql8.4单节点、主从、双主的构建方法
摘要
- MySql单节点、主从、双主的构建过程,及其配置文件的说明
- 本文基于
mysql-8.4.11 LTS,下载地址 https://dev.mysql.com/downloads/mysql/8.4.html - 8.0 版本的做法见 MySql单节点、主从、双主的构建方法,两篇的命令不通用,8.4 删除了一批主从语句和配置项,下面第 0 节先讲差异
常见面试题
0.从 8.0 到 8.4,哪些东西变了
8.4 是 8.x 系列的第二个 LTS。它把 8.0 里那些「已废弃很久」的东西真正删掉了,所以按 8.0 的笔记照抄会直接报语法错误。动手前先看这一节。
主从 SQL 语句全部改名(旧名已删除,不是别名)
| 8.0 写法 | 8.4 写法 |
|---|---|
SHOW MASTER STATUS |
SHOW BINARY LOG STATUS |
SHOW MASTER LOGS |
SHOW BINARY LOGS |
PURGE MASTER LOGS |
PURGE BINARY LOGS |
RESET MASTER |
RESET BINARY LOGS AND GTIDS |
CHANGE MASTER TO |
CHANGE REPLICATION SOURCE TO |
START SLAVE / STOP SLAVE |
START REPLICA / STOP REPLICA |
RESET SLAVE |
RESET REPLICA |
SHOW SLAVE STATUS |
SHOW REPLICA STATUS |
SHOW SLAVE HOSTS |
SHOW REPLICAS |
CHANGE 的选项名也删了
只改语句名不够,MASTER_HOST 这类选项在 8.4 同样不认:
MASTER_HOST → SOURCE_HOST,MASTER_PORT → SOURCE_PORT,MASTER_USER → SOURCE_USER,MASTER_PASSWORD → SOURCE_PASSWORD,MASTER_LOG_FILE → SOURCE_LOG_FILE,MASTER_LOG_POS → SOURCE_LOG_POS,MASTER_AUTO_POSITION → SOURCE_AUTO_POSITION,MASTER_CONNECT_RETRY → SOURCE_CONNECT_RETRY,MASTER_RETRY_COUNT → SOURCE_RETRY_COUNT。
SHOW REPLICA STATUS 的列名跟着变
排查主从时看的列不再是 Slave_IO_Running:
Slave_IO_State → Replica_IO_State,Master_Host → Source_Host,Master_Log_File → Source_Log_File,Read_Master_Log_Pos → Read_Source_Log_Pos,Relay_Master_Log_File → Relay_Source_Log_File,Slave_IO_Running → Replica_IO_Running,Slave_SQL_Running → Replica_SQL_Running,Seconds_Behind_Master → Seconds_Behind_Source。
配置项与默认值
| 项 | 变化 |
|---|---|
default_authentication_plugin |
8.4.0 已删除,配了服务起不来,改用 authentication_policy |
mysql_native_password |
默认关闭,要用得显式 mysql_native_password=ON;9.0 已彻底删除 |
expire_logs_days |
8.2 已删除,用 binlog_expire_logs_seconds(默认 2592000,即 30 天) |
log_slave_updates |
改名 log_replica_updates,默认 ON |
master_info_repository、relay_log_info_repository、master-info-file、relay-log-info-file |
8.3 已删除,复制元数据只存表(crash-safe) |
innodb_log_file_size、innodb_log_files_in_group |
已废弃,用 innodb_redo_log_capacity(默认 100MB) |
binlog_format |
8.0.34 起废弃,默认就是 ROW,新系统不要再配 |
replica_parallel_workers |
默认 4(8.0 是 0),从库默认就是多线程复制 |
rpl_semi_sync_master_* / semisync_master.so |
改用 rpl_semi_sync_source_* / semisync_source.so,从库侧是 replica 那一套 |
InnoDB 还有一批默认值在 8.4 被调好了,不用再手动配:innodb_log_buffer_size 16M→64M、innodb_io_capacity 200→10000、innodb_flush_method 改成 O_DIRECT(支持时)、innodb_adaptive_hash_index 改成 OFF、innodb_change_buffering 改成 none、innodb_buffer_pool_instances 改成按内存和 CPU 自动算。
警告⚠️
innodb_buffer_pool_size 默认仍是 128M,8.4 不会自动按机器内存放大。独占机器可以开 innodb_dedicated_server=ON,让 InnoDB 按物理内存算 buffer pool、按 CPU 数算 redo 容量。
高可用方案也得换
MySql单节点、主从、双主的构建方法 文末提到的 MHA、MMM 都是 Perl 老工具,内部发的就是 `CHANGE MASTER TO`、`SHOW SLAVE STATUS`,**在 8.4 上跑不起来**(详见 MySql-MHA的构建方法 里的说明)。8.4 要做自动选主,用官方的 **InnoDB Cluster**(Group Replication + MySQL Shell + MySQL Router),本文最后一节给出选型。1.单节点
安装
-
参考官方文档
1 | # 1.下载mysql,从mysql官网下载:https://dev.mysql.com/downloads/mysql/8.4.html |
警告⚠️
默认情况下,mysql按照下面的文件顺序加载配置,后面的配置会覆盖前面的配置
/etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf ~/.my.cnf
建议将配置文件创建到/etc/my.cnf,这样所有用户都可以使用,特殊配置可以创建在当前用户的~/.my.cnf中。
本文以下内容除特殊指定配置文件路径外,都是基于/etc/my.cnf的默认配置文件
配置
配置段说明
- [mysql] 和 [client] 都是针对客户端的配置,后面的配置会覆盖前面的相同配置
- [mysql] 只针对
mysql命令,可以通过mysql --help查看配置项及其缺省值 - [client] 针对
mysql、mysqldump、mysqlimport、mysqladmin, 等等,所有的客户端命令 - [mysqld] 只是针对服务器端的配置,针对
mysqld命令,可以通过mysqld --verbose --help查看配置项及其缺省值
-
配置文件示例
1 | vim my.cnf |
数据库初始化
1 | # 说明:--initialize-insecure 初始化时无密码 |
警告⚠️
lower_case_table_names 必须在初始化之前写进配置文件,初始化完成后再改会导致启动失败。
启动数据库
1 | # 后台启动 |
注意:
mysqld_safe在通用二进制包(tar.xz)里仍然提供;但用 RPM/DEB 安装时不会安装它,那种情况直接用 systemd 管理。
开机启动+启动关闭mysql命令
方法1[推荐]:使用mysql提供的脚本
-
开机自启动
1 | cd /usr/local/soft/mysql8.4/support-files/ |
-
启动关闭
1 | # 启动mysql,start/stop/status/reload/restart |
方法2:自己写命令
-
开机自启动
1 | sudo chmod +x /etc/rc.d/rc.local |
-
启动关闭
1 | # 也可以指定配置文件的位置 |
检查mysql是否启动成功
1 | # 查看进程 |
登录
1 | # 无密码登录,第一次登录没有密码,所以使用这种方式登录 |
-
遇到的问题:8.4 的账号默认用
caching_sha2_password,该插件要求加密连接或基于 RSA 公钥交换密码。自带的mysql客户端默认会协商 TLS,一般不用管;老客户端或部分驱动可能报认证失败。
1 | # 方式一:让客户端向服务端索取RSA公钥(未启用TLS时) |
修改密码
1 | # 8.4默认插件就是caching_sha2_password,直接改密码即可 |
授予root用户system_user权限
1 | mysql> grant system_user on *.* to 'root'@'localhost'; |
开启远程访问
1 | # 允许远程访问 |
警告⚠️
非常不建议开启root用户的远程访问权限,建议新创建一个用户,并仅授予必要的权限
1 | # 创建新用户,8.4默认就是caching_sha2_password |
关闭mysql
1 | sudo mysqladmin -uroot -p shutdown |
2.主从
-
参照单节点的构建方式搭建好两台mysql,主从计划如下:
1 | master: 10.250.0.243 |
-
master和slave的
server-id不能相同 -
master必须开启binlog功能
-
slave必须开启中继日志
-
在云环境中,如果slave是通过master的镜像创建的,要修改slave的
datadir中auto.cnf文件中的uuid的值,master和salve是不能相同的。
auto.cnf
1 | [auto] |
master配置文件
1 | # 主从或集群中要保证唯一性 |
slave配置文件
1 | # 主从或集群中要保证唯一性 |
警告⚠️
master_info_repository、relay_log_info_repository、master-info-file、relay-log-info-file 这四个参数在 8.3 已被删除。8.4 的复制元数据只存在 mysql.slave_master_info、mysql.slave_relay_log_info 表里(crash-safe),配置文件里写这些参数会导致启动失败。
主库创建同步帐号
1 | # '10.250.%.%' 表示只能局域网段内的ip才能访问,如果不限制ip,可以配置为'%' |
8.4 建复制账号的坑
复制账号用 caching_sha2_password 时,如果主从之间没有启用 TLS,从库必须拿到主库的 RSA 公钥才能完成认证,否则 START REPLICA 之后 Replica_IO_Running 一直是 No,报认证失败。两种解法:
- 在下面的
CHANGE REPLICATION SOURCE TO里加GET_SOURCE_PUBLIC_KEY=1(本文采用) - 或者加
SOURCE_PUBLIC_KEY_PATH='/path/to/public_key.pem'指定公钥文件
如果主从走加密连接(SOURCE_SSL=1 并配好证书),就不需要这两个参数。
如果此时主库已经有数据,则需要先将主库数据导入到从库后再开启主从复制
1 | # 主库执行导出数据 |
从节点设置同步
1 | # 【8.4变化】查看主节点binlog状态,记录File和Position两个信息 |
【8.4变化】判断主从是否正常,看的是
Replica_IO_Running和Replica_SQL_Running都为Yes;老的Slave_IO_Running/Slave_SQL_Running这两个列名在8.4已经不存在了。
Read_Source_Log_Pos和Exec_Source_Log_Pos的差值表示已收到但还没应用完的量,配合Seconds_Behind_Source看延迟。
此时在master中执行
SHOW PROCESSLIST;可以查看到同步信息
1 | mysql> SHOW PROCESSLIST; |
【8.4变化】在主库上查看挂了哪些从库,老命令是
SHOW SLAVE HOSTS
1 | mysql> SHOW REPLICAS; |
主从架构,从库应该是禁止写操作的,否则有可能会导致主从同步失败(如主键冲突),所以为了保证数据的一致性,应该禁止从库写操作。
1 | # 从库的配置文件增加如下内容,并重启从库 |
开启GTID(全局事务ID)主从复制模式,8.4 推荐直接用 GTID,不用再手工记 File/Position
1 | # master和slave的my.cnf中分别加入,并重启mysql服务 |
主从架构,一个master可以配置多个slave。
重建主从时的清理命令
1 | # 【8.4变化】从库清空复制信息,老命令 RESET SLAVE ALL |
主从模式高可用架构
8.0 时代常见的做法是套 MHA 做自动选主,但 MHA 在 8.4 上不可用:它最后一个版本是 2018 年的 0.58,内部发的是 CHANGE MASTER TO、SHOW SLAVE STATUS 这些已被删除的语句。详见 MySql-MHA的构建方法。
8.4 要做自动故障转移,选型见本文最后一节。如果只是想让从库在主库连不上时自动改连另一个源,8.4 自带的 Asynchronous Connection Failover 可以做到(注意它只切换复制连接,不做主库提升):
1 | # 需要GTID + 自动定位 |
3.双主
-
双主模式就是两个mysql互为主从
-
两个master都不能设置只读
-
以上面主从为例,我们继续搭建双主架构
从库关闭只读并开启binlog
1 | # 开启普通用户只读 |
主库也要开启中继日志
1 | # 主从或集群中要保证唯一性 |
从库上创建同步帐号
1 | # '10.250.%.%' 表示只能局域网段内的ip才能访问,如果不限制ip,可以配置为'%' |
查看从库的binlog状态
1 | mysql> SHOW BINARY LOG STATUS; |
主库上配置主从信息
1 | mysql> CHANGE REPLICATION SOURCE TO |
此时双主架构搭建完成。
双主架构下,每个master还可以配置多个slave用于数据备份。
双主架构自增主键冲突问题解决方法
1 | # master1 |
8.0 笔记里提到的双主高可用工具 MMM 同样是 Perl 老项目,早已停更,不要在 8.4 上使用。双主想做 VIP 漂移,用 Keepalived 之类自己控,或者直接上 InnoDB Cluster。
4.半同步复制
1 | 无论是主从复制还是双主复制,默认数据同步都是异步进行,主服务在向客户端反馈执行结果时,是不知道binlog是否同步成功了的。 |
安装半同步复制插件
1 | # 【8.4变化】插件和库文件都换成了source/replica命名 |
如果是双主架构,则两边都需要安装这两个插件
警告⚠️
新旧插件不能共存。从 8.0 升级上来的实例如果之前装过 rpl_semi_sync_master / rpl_semi_sync_slave,会在错误日志里看到:
Cannot install the rpl_semi_sync_source plugin when the rpl_semi_sync_master plugin is installed.
处理办法是先卸载旧插件、清掉配置文件里的旧变量、重启,再装新插件:
1 | mysql> UNINSTALL PLUGIN rpl_semi_sync_master; |
开启配置
1 | # 【8.4变化】变量名同步改成 source/replica |
重启mysql后查看是否配置成功
1 | mysql> show global variables like 'rpl_semi%'; |
注意:
rpl_semi_sync_master_*这套旧变量在装了新插件之后是看不到的,两套变量不会同时存在。
5.MySql8.4 的高可用怎么选
主从/双主 + 半同步只解决「少丢数据」,不解决自动选主。8.4 上的可选方案:
| 方案 | 说明 | 适合 |
|---|---|---|
| InnoDB Cluster | 官方方案,Group Replication + MySQL Shell(AdminAPI) + MySQL Router,至少3节点,自动选主并自动把写流量路由到新Primary | 新部署首选 |
| InnoDB ClusterSet | 多个 InnoDB Cluster 跨机房,主集群不可用时由管理员触发切换 | 跨机房容灾 |
| Percona XtraDB Cluster 8.4 | Galera 准同步,强调数据一致性,前端配 ProxySQL / HAProxy | 对一致性要求更高 |
| 本文的主从/双主 + 半同步 | 不自动选主,主库挂了要人工切或自己写脚本 | 读写分离、备份、容量扩展 |
| 云数据库多可用区 | RDS / Aurora / 云厂商托管,平台负责选主和地址漂移 | 能上云优先 |
需要注意的两点:
-
ProxySQL、HAProxy、Keepalived 只做连接路由或 VIP,不会安全地把某个从库提升成新主,它们必须配合一个真正的选主组件。
-
前面提到的 Asynchronous Connection Failover 只是让从库换源,不做主库提升。
主从会丢数据吗?双主自增怎么防冲突?
场景:单机改一主一从读写分离,并评估是否上双主。以下命令均为 8.4 写法。
1. 搭主从时主库、从库至少要配对什么?
-
两边:
server-id必须不同;若从库是主库镜像克隆的,还要改datadir/auto.cnf里的server-uuid,uuid 也不能相同。 -
主库:必须开 binlog(
log-bin),复制账号要有REPLICATION SLAVE;已有数据时先mysqldump导入从库,再按SHOW BINARY LOG STATUS的 File/Position 做CHANGE REPLICATION SOURCE TO(开了 GTID 就用SOURCE_AUTO_POSITION=1)。 -
从库:必须开中继日志(
relay-log);START REPLICA后Replica_IO_Running与Replica_SQL_Running都为Yes才算通。log_replica_updates在 8.4 默认就是 ON,级联复制不用额外开。 -
写保护:从库应
read_only/super_read_only,禁止业务写入,避免主键冲突把复制打挂。 -
8.4 特有:复制账号默认
caching_sha2_password,非加密连接下必须给GET_SOURCE_PUBLIC_KEY=1或SOURCE_PUBLIC_KEY_PATH,否则 IO 线程起不来。
2. 默认异步复制会丢数据吗?
-
会。 异步复制下,主库本地事务提交成功就会给客户端返回「成功」,不等 binlog 传到从库。
-
若返回成功后主库立刻宕机,而这条 binlog 还没到从库(甚至没 flush 完),切换到从库后这条提交就没了——客户端以为成功,从库上却看不到。
-
主库
SHOW PROCESSLIST里能看到Binlog Dump线程,那只说明「在推」;默认链路不保证「推到了才对客户端 ack」。
3. 半同步解决哪一步?等到什么?等不到怎样?
-
半同步卡的是**「主库已提交 → 客户端收到成功」之间:至少等一个从库收到 binlog 并写入 relay log** 后,主库才返回客户端。
-
注意:等到的是「写进中继日志」,不保证从库 SQL 线程已经应用完。所以是「至少进了从库磁盘侧的中继日志」,不是全同步。
-
默认超时约 10 秒(
rpl_semi_sync_source_timeout=10000)。超时收不到 ack,会降级成异步复制,之后又回到可能丢数的模式,直到半同步重新建立。 -
代价:提交延迟上升,换的是宕机时少丢已向客户端确认的事务。8.4 要装的是
rpl_semi_sync_source/rpl_semi_sync_replica,且不能和 8.0 的 master/slave 版插件共存。
4. 双主自增冲突怎么防?解决的是什么?
-
两边都能写时,默认两边自增都从 1,2,3… 长,很容易主键冲突,复制中断。
-
配法(文中示例):
- master1:
auto_increment_offset=1,auto_increment_increment=2→ 1,3,5,7… - master2:
auto_increment_offset=2,auto_increment_increment=2→ 2,4,6,8…
- master1:
-
只解决自增主键撞号,不是强一致:双主仍是复制(默认异步/半同步),两边并发改同一行仍可能冲突;也解决不了业务唯一键、无自增主键的冲突。很多团队双主实际当主备,同一时刻只让一个节点接写。
5. 8.4 和 8.0 在这块有什么不一样?
-
主从语句和
CHANGE选项全部改名,旧名已删除而非别名,8.0 的脚本必须改。 -
判定列变成
Replica_IO_Running/Replica_SQL_Running。 -
认证默认
caching_sha2_password,default_authentication_plugin已删除。 -
半同步插件换成 source/replica 版。
-
MHA / MMM 这类老工具不可用,自动选主要走 InnoDB Cluster。
面试可背:主从要不同
server-id/uuid,主开 binlog、从开 relay,从库只读;异步提交先返回可能丢数;半同步等到 relay log 再返回,超时降级异步;双主用奇偶自增防撞号,不是分布式强一致;8.4 起主从语句全面改名、认证默认 caching_sha2_password、MHA 不可用。