MySQL 8.4 LTS 单节点、主从、双主搭建:8.0 旧命令在 8.4 会直接报语法错误
本文基于 mysql-8.4.11 LTS,下载地址:MySQL 8.4 下载页。
操作系统使用 Amazon Linux 2023(x86_64);其它发行版的用户、服务、软件包和配置文件路径可能不同。
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_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 |
配置项与默认值变化
| 旧配置/行为 | 8.4 配置/行为 | 说明 |
|---|---|---|
default_authentication_plugin | authentication_policy | 8.4.0 已删除,配了服务起不来 |
mysql_native_password | 默认关闭 | 要用得显式 mysql_native_password=ON;9.0 已彻底删除 |
expire_logs_days | binlog_expire_logs_seconds | 8.2 已删除,默认 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 | 默认就是 ROW | 8.0.34 起废弃,新系统不要再配 |
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 容量。
高可用方案也得换:MHA、MMM 都是 Perl 老工具,内部发的就是 CHANGE MASTER TO、SHOW SLAVE STATUS,在 8.4 上跑不起来。8.4 要做自动选主,用官方的 InnoDB Cluster(Group Replication + MySQL Shell + MySQL Router)。
1. 单节点
安装
# 1.下载mysql,从mysql官网下载:https://dev.mysql.com/downloads/mysql/8.4.html
# 注意8.4的通用二进制包是glibc2.28,比8.0的glibc2.12要新,老系统(如CentOS7)装不上
wget https://cdn.mysql.com/Downloads/MySQL-8.4/mysql-8.4.11-linux-glibc2.28-x86_64.tar.xz
tar -Jxvf mysql-8.4.11-linux-glibc2.28-x86_64.tar.xz
mv mysql-8.4.11-linux-glibc2.28-x86_64 mysql8.4
sudo su
groupadd mysql
useradd -r -g mysql -s /bin/false mysql
cd mysql8.4
mkdir -p datas/mysql
chown -R mysql:mysql datas
chmod -R 750 datas
vim /etc/bashrc
export PATH=$PATH:/usr/local/soft/mysql8.4/bin
touch my.cnf
# 默认加载顺序:/etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf ~/.my.cnf,后面的覆盖前面的;建议放 /etc/my.cnf
配置:my.cnf 示例
[client]
port = 3306
socket = /tmp/mysql.sock
[mysqld]
skip-name-resolve
secure_file_priv=""
local_infile=ON
# 【8.4变化】default_authentication_plugin 在8.4.0已被删除,配置了会导致mysql启动失败
# 8.4改用 authentication_policy 管理认证因子,默认值就是 '*,,'
authentication_policy='*,,'
# 【8.4变化】mysql_native_password 默认已关闭,只有老客户端/老驱动连不上时才临时打开
# mysql_native_password=ON
port = 3306
server-id = 1001
user = mysql
socket = /tmp/mysql.sock
basedir = /usr/local/soft/mysql8.4
datadir = /usr/local/soft/mysql8.4/datas/mysql
log-bin = mysql-bin
# 【8.4变化】binlog_format 从8.0.34起已废弃,8.4默认就是ROW
# 【8.4变化】binlog过期时间,单位秒,8.4默认2592000(30天)
# 老参数 expire_logs_days 在8.2已被删除
binlog_expire_logs_seconds = 864000
sync-binlog=0
innodb_data_home_dir = ./
# 【8.4变化】redo日志固定放在 datadir 下的 #innodb_redo 目录,共32个文件
innodb_log_group_home_dir = ./
log-error = mysql.log
pid-file = mysql.pid
character-set-server=utf8mb4
lower_case_table_names=1
autocommit =1
slow_query_log=1
slow_query_log_file=db_slow.log
long_query_time=5
log_output=FILE
log_queries_not_using_indexes=1
skip-external-locking
key_buffer_size = 256M
max_allowed_packet = 64M
table_open_cache = 1024
sort_buffer_size = 4M
thread_cache_size = 64
tmp_table_size = 128M
explicit_defaults_for_timestamp = true
max_connections = 500
max_connect_errors = 100
open_files_limit = 65535
default_storage_engine = InnoDB
innodb_data_file_path = ibdata1:10M:autoextend
innodb_buffer_pool_size = 1024M
# 【8.4变化】redo日志总容量,替代已废弃的 innodb_log_file_size / innodb_log_files_in_group
innodb_redo_log_capacity = 1G
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
# 独占机器时建议打开
# innodb_dedicated_server=ON
数据库初始化
sudo mysqld --user=mysql --initialize-insecure
# 或指定配置文件,--defaults-file要放在第一个参数位置
sudo mysqld --defaults-file=/usr/local/soft/mysql8.4/my.cnf --user=mysql --initialize-insecure
# 警告:lower_case_table_names 必须在初始化之前写进配置文件,初始化完成后再改会导致启动失败。
启动数据库
sudo mysqld_safe --user=mysql &
ps -ef|grep mysql
# 注意:mysqld_safe 在通用二进制包里仍提供;RPM/DEB 安装不会装它,那种情况直接用 systemd。
开机启动(方法1,推荐)
cd /usr/local/soft/mysql8.4/support-files/
sudo cp mysql.server /etc/init.d/mysqld
sudo systemctl enable mysqld
chkconfig --list
sudo systemctl disable mysqld
sudo systemctl start mysqld
sudo systemctl stop mysqld
登录
mysql -uroot --skip-password
# 8.4 账号默认用 caching_sha2_password,要求加密连接或基于 RSA 公钥交换密码
mysql -uroot -p -hxxx.xxx.xxx.xxx -P3306 --get-server-public-key
mysql -uroot -p -hxxx.xxx.xxx.xxx -P3306 --server-public-key-path=/path/to/public_key.pem
修改密码
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';
# 不要再用 mysql_native_password,默认插件未加载,执行会报:
# ERROR 1524 (HY000): Plugin 'mysql_native_password' is not loaded
mysql> FLUSH PRIVILEGES;
授予 root 用户 system_user 权限
mysql> grant system_user on *.* to 'root'@'localhost';
mysql> flush privileges;
开启远程访问(不建议开 root 远程)
mysql> use mysql;
mysql> update user set user.Host='%' where user.User='root';
mysql> flush privileges;
# 更稳的做法:新建用户并只授必要权限
mysql> CREATE USER 'username'@'%' IDENTIFIED BY 'password';
mysql> CREATE DATABASE my_database CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
mysql> GRANT all privileges ON my_database.* TO 'username'@'%';
mysql> FLUSH PRIVILEGES;
mysql> show grants for 'username'@'%'\G
关闭
sudo mysqladmin -uroot -p shutdown
2. 主从
master: 10.250.0.243
slave: 10.250.0.82
master 和 slave 的 server-id 不能相同;master 必须开启 binlog;slave 必须开启中继日志。
云环境中如果 slave 由 master 镜像创建,要改 slave 的 datadir 中 auto.cnf 的 server-uuid,两者不能相同。
master 配置文件
server-id = 1001
log-bin = mysql-bin
slave 配置文件
server-id = 1002
relay-log-index=slave-relay-bin.index
relay-log=slave-relay-bin
relay_log_purge=1
# 【8.4变化】log_slave_updates 改名为 log_replica_updates,默认ON
log_replica_updates=ON
# 【8.4变化】从库默认就是多线程复制,replica_parallel_workers 默认4;replica_preserve_commit_order 默认ON
# replica_parallel_workers=4
# 警告:master_info_repository、relay_log_info_repository、master-info-file、relay-log-info-file 在 8.3 已被删除,
# 复制元数据只存在 mysql.slave_master_info、mysql.slave_relay_log_info 表里,配置里写这些参数会导致启动失败。
主库创建同步帐号
mysql> CREATE USER 'vagrant'@'10.250.%.%' IDENTIFIED BY 'vagrant';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'vagrant'@'10.250.%.%';
mysql> FLUSH PRIVILEGES;
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 并配好证书),就不需要这两个参数。
如果主库已有数据,先导入从库再开启复制
mysqldump -uroot --all-databases --triggers --routines --events -p > all_databases.sql
# 更推荐,一致性快照导出,文件头带位点
mysqldump -uroot -p --all-databases --triggers --routines --events --single-transaction --source-data=2 > all_databases.sql
mysql> FLUSH TABLES WITH READ LOCK;
mysql> UNLOCK TABLES;
mysql -uroot -p < all_databases.sql
从节点设置同步
# 【8.4变化】查看主节点binlog状态,老命令 SHOW MASTER STATUS 已被删除
mysql> SHOW BINARY LOG STATUS;
# File=mysql-bin.000008 Position=1140
mysql> CHANGE REPLICATION SOURCE TO
SOURCE_HOST='10.250.0.243',
SOURCE_PORT=3306,
SOURCE_USER='vagrant',
SOURCE_PASSWORD='vagrant',
SOURCE_LOG_FILE='mysql-bin.000008',
SOURCE_LOG_POS=1140,
GET_SOURCE_PUBLIC_KEY=1;
mysql> START REPLICA;
mysql> SHOW REPLICA STATUS \G
# 判断主从是否正常,看 Replica_IO_Running 和 Replica_SQL_Running 都为 Yes
# 老列名 Slave_IO_Running / Slave_SQL_Running 在8.4已不存在
# Read_Source_Log_Pos 和 Exec_Source_Log_Pos 的差值表示已收到但还没应用完的量
# 主库上查看挂了哪些从库,老命令是 SHOW SLAVE HOSTS
mysql> SHOW REPLICAS;
从库禁止写操作
read_only=1
super_read_only=1
开启 GTID 主从复制(8.4 推荐直接用 GTID)
# master和slave的my.cnf中分别加入,并重启
gtid_mode=on
enforce_gtid_consistency=on
mysql> STOP REPLICA;
mysql> CHANGE REPLICATION SOURCE TO
SOURCE_HOST='10.250.0.243',
SOURCE_PORT=3306,
SOURCE_USER='vagrant',
SOURCE_PASSWORD='vagrant',
SOURCE_AUTO_POSITION=1,
GET_SOURCE_PUBLIC_KEY=1;
mysql> START REPLICA;
mysql> SHOW BINARY LOG STATUS; # Executed_Gtid_Set 会随数据更新变化
mysql> SHOW VARIABLES like "%gtid%";
重建主从时的清理命令
# 【8.4变化】从库清空复制信息,老命令 RESET SLAVE ALL
mysql> STOP REPLICA;
mysql> RESET REPLICA ALL;
# 【8.4变化】主库清空binlog和GTID,老命令 RESET MASTER,生产慎用
mysql> RESET BINARY LOGS AND GTIDS;
mysql> SHOW BINARY LOGS;
mysql> PURGE BINARY LOGS TO 'mysql-bin.000010';
主从模式高可用架构
8.0 时代常见做法是套 MHA 做自动选主,但 MHA 在 8.4 上不可用(最后版本 2018 年的 0.58,内部发的是已删除的语句)。
8.4 要做自动故障转移可选 InnoDB Cluster。如果只是想让从库在主库连不上时自动改连另一个源,8.4 自带的 Asynchronous Connection Failover 可以做到(只切换复制连接,不做主库提升):
# 需要GTID + 自动定位
mysql> CHANGE REPLICATION SOURCE TO
SOURCE_AUTO_POSITION=1,
SOURCE_CONNECTION_AUTO_FAILOVER=1,
SOURCE_RETRY_COUNT=3,
SOURCE_CONNECT_RETRY=10;
# 注册备用源,权重越大越优先
mysql> SELECT asynchronous_connection_failover_add_source('', '10.250.0.82', 3306, '', 80);
3. 双主
双主模式就是两个 mysql 互为主从;两个 master 都不能设置只读。
操作:从库关闭只读并开启 binlog;主库也要开启中继日志;在从库上创建同步账号;查看从库的 binlog 状态;在主库上配置复制信息(步骤与主从相同,方向相反)。
双主架构自增主键冲突问题解决方法:两个主库各自设置不同的自增步长与偏移,避免同时插入时产生相同主键:
# master1
auto_increment_increment=2
auto_increment_offset=1
# master2
auto_increment_increment=2
auto_increment_offset=2
4. 半同步复制
安装半同步复制插件(8.4 是 source/replica 这一套):
# master
INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so';
SET GLOBAL rpl_semi_sync_source_enabled=ON;
# slave
INSTALL PLUGIN rpl_semi_sync_replica SONAME 'semisync_replica.so';
SET GLOBAL rpl_semi_sync_replica_enabled=ON;
# 默认超时约 10 秒(rpl_semi_sync_source_timeout=10000),超时收不到 ack 会降级成异步复制
# 注意:不能和 8.0 的 master/slave 版插件共存
5. MySQL 8.4 的高可用怎么选
- 搭主从时主库、从库至少要配对什么?
server-id唯一、master 开 binlog、slave 开 relay log、复制账号 +REPLICATION SLAVE权限。 - 默认异步复制会丢数据吗? 会。主库提交后 binlog 还没发到从库就宕机,会导致「已向客户端返回成功」的事务丢失。
- 半同步解决哪一步? 等从库 ack,超时(默认 10 秒)降级为异步。
- 双主自增冲突怎么防?
auto_increment_increment=2+ offset 不同。 - 8.4 和 8.0 在这块有什么不一样? 语句/参数全面改名,不再有 MASTER/SLAVE 命名;复制元数据只存表;半同步插件改成 source/replica;从库默认多线程复制;MHA/MMM 不可用,改用 InnoDB Cluster。