文章目录
- @[toc]
- 啰嗦一下
- mysql 的 AB 复制和 gtid 复制的优缺点
- AB 复制(Asynchronous Replication)
- GTID 复制(Global Transaction Identifier Replication)
- mysql gtid 并行复制和半同步复制的优缺点
- 并行复制(Parallel Replication)
- 半同步复制(Semi-Synchronous Replication)
- 好戏开场
- 部署 mysql
- 创建 mysql 启动的用户
- 创建 mysql 安装包存放路径
- 创建主库 mysql 配置文件
- 创建从库 mysql 配置文件
- mysql 初始化
- 创建 systemcl 管理
- 修改 root 用户密码
- 配置互为主从
- 从库配置主从关系
- 主库配置互为主从关系
- 验证主从复制
- 模拟主库故障
- @[toc]
- 啰嗦一下
- mysql 的 AB 复制和 gtid 复制的优缺点
- AB 复制(Asynchronous Replication)
- GTID 复制(Global Transaction Identifier Replication)
- mysql gtid 并行复制和半同步复制的优缺点
- 并行复制(Parallel Replication)
- 半同步复制(Semi-Synchronous Replication)
- 好戏开场
- 部署 mysql
- 创建 mysql 启动的用户
- 创建 mysql 安装包存放路径
- 创建主库 mysql 配置文件
- 创建从库 mysql 配置文件
- mysql 初始化
- 创建 systemcl 管理
- 修改 root 用户密码
- 配置互为主从
- 从库配置主从关系
- 主库配置互为主从关系
- 验证主从复制
- 模拟主库故障
- 麒麟镜像可以去下面的地方下载,需要自己注册一个账号
- 麒麟软件生态
- Mysql 二进制文件下载地址
啰嗦一下
- 老生常谈的问题(这些问题都会影响部署的排查)
- 关掉 firewalld
- 关掉 selinux (银河麒麟默认会关闭 selinux)
我下载的海光 x86 版本的麒麟
NAME="Kylin Linux Advanced Server"VERSION="V10 (Lance)"ID="kylin"VERSION_ID="V10"PRETTY_NAME="Kylin Linux Advanced Server V10 (Lance)"ANSI_COLOR="0;31"
mysql 的 AB 复制和 gtid 复制的优缺点
抄自 opengpt 3.5
在 MySQL 中,有两种常见的复制方式:AB 复制(Asynchronous Replication)和 GTID 复制(Global Transaction Identifier Replication)。
AB 复制(Asynchronous Replication)
优点
:
简单易用
:AB 复制是 MySQL 复制的最基本形式,设置相对简单,适合初学者或简单复制场景。性能
:因为是异步复制,主数据库不需要等待从数据库的确认,所以主库的写操作可以更快地完成,提高了主库的性能。容错
:在出现网络故障或从库延迟时,主库不会受到影响,继续提供服务。
缺点:
数据延迟
:因为是异步复制,从库的数据可能会有一定的延迟,这意味着在主库上提交的事务不会立即在从库上可见。数据一致性
:由于延迟,主从之间的数据可能会出现不一致的情况,这需要开发者自行处理。单点故障
:如果主库故障,需要手动切换到备库,造成一定的停机时间。
GTID 复制(Global Transaction Identifier Replication)
优点:
数据一致性
:使用 GTID,每个事务都有全局唯一的标识符,确保主从之间的数据一致性,避免数据冲突。简化拓扑结构
:GTID 复制使得添加或删除节点更加容易,不需要像传统复制那样配置复杂的 master-host 和 master-log-position。自动故障转移
:GTID 复制可以更容易地实现自动故障转移,当主库发生故障时,可以自动切换到从库。
缺点:
性能
:由于 GTID 需要维护全局唯一标识符,可能会对性能产生一定的影响,尤其在高负载的情况下。配置复杂性
:相比 AB 复制,GTID 复制的配置较为复杂,特别是在现有的非 GTID 复制架构迁移到 GTID 复制时,需要谨慎处理。兼容性
:GTID 复制要求 MySQL 版本在 5.6 以上,如果要使用较旧的 MySQL 版本,可能不支持 GTID。
- 综合考虑
- AB 复制适合简单的数据复制和备份需求,对数据一致性和高可用性要求不高的场景。
- GTID 复制适合对数据一致性和高可用性要求较高的复制架构,尤其在复杂的拓扑结构和自动故障转移场景中更加有优势。选择哪种复制方式取决于应用程序的需求和系统的复杂性。
mysql gtid 并行复制和半同步复制的优缺点
在 MySQL GTID 主从复制中,还有两种复制模式:并行复制和半同步复制。这两种模式可以进一步提高复制的性能和数据一致性。让我们来看一下它们的优缺点和利弊:
并行复制(Parallel Replication)
优点:
提高复制性能
:并行复制允许在从库上同时执行多个线程来处理不同的事务,从而提高了复制的性能和吞吐量。减少延迟
:通过并行执行事务,从库可以更快地赶上主库,从而减少数据复制的延迟。多核利用
:现代服务器通常有多个核心,使用并行复制可以更好地利用这些多核心,加快数据复制。
缺点:
复杂性增加
:并行复制的配置和管理相对复杂,可能需要更多的系统资源和监控,不适合所有环境。并发控制
:并行复制可能导致数据在不同线程之间的冲突和竞争,需要开发者正确处理并发控制问题。
半同步复制(Semi-Synchronous Replication)
优点:
数据安全性
:半同步复制确保至少一个从库已经确认接收并写入主库的事务,从而提高数据的安全性和一致性。高可用性
:在主库发生故障时,由于至少有一个从库已经复制了主库的数据,可以更快地将从库提升为新的主库,减少停机时间。监控机制
:半同步复制提供了可以监控从库复制进度的机制,使得管理员可以更好地了解复制的状态和延迟情况。
缺点:
性能影响
:由于需要等待至少一个从库确认写入,半同步复制可能对主库的性能产生一定的影响,特别是在写入负载较高的情况下。单点故障
:如果配置了多个从库,并且至少一个从库确认写入的要求,那么当所有从库都不可用时,主库的写入将会受阻。
- 综合考虑
- 并行复制适用于高负载环境,可以显著提高复制性能和减少复制延迟,但配置和管理相对较复杂。
- 半同步复制适用于对数据安全性和高可用性要求较高的场景,但可能会对主库的性能产生一定的影响。选择哪种模式取决于具体的应用需求和系统性能情况。
准备两台虚拟机,我们启航
好戏开场
部署 mysql
- 下面的操作,都是使用的 root 用户,但是 mysql 使用的是普通用户
- 部署 mysql 是两台虚拟机都需要安排的
创建 mysql 启动的用户
创建的 mysql 用户就分配一个 nologin 的 shell,不给登录机器的
useradd mysql -s /sbin/nologin
创建 mysql 安装包存放路径
mkdir -p /data/software/mysql
上传或者下载 mysql 二进制文件到
/data/software/mysql
下后进行解压,这里就不体现步骤了下面的命令给 mysql 二进制文件修改用户权限,让 mysql 用户有权限可以读取
chown -R mysql /data/software/mysql/mysql-5.7.29-linux-glibc2.12-x86_64
创建主库 mysql 配置文件
我这边就用了 GTID 的半同步模式
- 创建对应的目录 [
两台机器都需要创建
]
mkdir -p /data/mysql/{mysql_data,logs,config}
- 在 mysql 主库上创建配置文件
cat << EOF > /data/mysql/config/my.cnf[mysqld]pid-file=/data/mysql/mysqld.pidsocket=/data/mysql/mysqld.sockdatadir=/data/mysql/mysql_datalog-error=/data/mysql/logs/error.logport=13306# MySQL 在运行时需要 errmsg.sys 文件来显示和报告错误消息lc-messages-dir=/data/software/mysql/mysql-5.7.29-linux-glibc2.12-x86_64/share/english# GTID## 每个 mysql 的 server_id 不能重复server_id=135# 新事务和复制事务都必须是 GTID 事务gtid_mode=on# 不允许任何事务违反 GTID 一致性enforce_gtid_consistency=on# MySQL 在启动时会跳过启动从服务器的复制线程,从而暂时禁止从服务器执行复制任务skip_slave_start=1# binlog# binlog 文件的名称log_bin=mysql-bin# 设置每个二进制日志文件的最大大小max_binlog_size=100m# 设置用于缓存二进制日志事件的缓冲区大小binlog_cache_size=4m# 设置 binlog 缓存的最大大小max_binlog_cache_size=512m# binlog 类型binlog_format=ROW# binlog 过期时间expire_logs_days=7# binlog 记录忽略的数据库binlog-ignore-db=sys,mysql,performance_schema,information_schema# 从服务器将主服务器的更新记录到自己的 binlog 里面log-slave-updates=ON# 每次提交事务时,等待将日志写入磁盘并返回成功后才继续执行sync_binlog=1# 配置半同步复制使用的插件plugin-load="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"# 开启半同步复制rpl_semi_sync_master_enabled=ONrpl_semi_sync_slave_enabled=ONbind-address=0.0.0.0# 是否允许在数据库目录下使用符号链接## symbolic-links=0:表示不允许使用符号链接。如果设置为 0,MySQL 服务器在启动时将不会使用数据库目录下的符号链接,并且可能会在符号链接存在时报错。## symbolic-links=1:表示允许使用符号链接。如果设置为 1,MySQL 服务器在启动时将允许使用数据库目录下的符号链接,但仅限于特定目录或文件(根据权限设置)。## symbolic-links=2:表示允许使用符号链接,且没有限制。如果设置为 2,MySQL 服务器在启动时将允许使用数据库目录下的任意符号链接,包括对任意文件或目录的链接。symbolic-links=0# mysql 最大连接数max_connections=1000# 默认存储引擎default_storage_engine=innodb# 禁用外部锁定,MySQL 将使用内部锁定来代替外部锁定skip_external_locking# 0:表名存储为原始大小写,区分大小写;# 1:表名存储为小写,不区分大小写;# 2:表名存储为小写,但会在文件系统上进行名称比较,因此会区分大小写。lower_case_table_names=1# 禁用主机缓存,每次都要重新解析域名skip_host_cache# 开启主机名解析skip_name_resolve# 设置服务器的默认字符集character_set_server=utf8# 客户端与服务器之间允许的最大数据包大小max_allowed_packet=12M# 控制 SQL 的执行模式## STRICT_TRANS_TABLES:启用严格模式,对于事务表,如果有非法数据插入或更新,将会引发错误## NO_ZERO_IN_DATE:禁止在日期中使用 "0000-00-00" 这样的零值,否则会被转换为 NULL 值## ERROR_FOR_DIVISION_BY_ZERO:当除零错误发生时,产生错误而不是返回 NULL 值## NO_AUTO_CREATE_USER:禁止 GRANT 语句自动创建新用户,必须手动创建## NO_ENGINE_SUBSTITUTION:如果指定的存储引擎不可用或不存在,不要自动替换为其他可用的存储引擎,而应该返回错误sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'[client]# 设置 MySQL 客户端连接的默认字符集character-set-client=utf8EOF
创建从库 mysql 配置文件
- 在 mysql 从库上创建配置文件
- 注意 service_id 要和主库的不一样
cat << EOF > /data/mysql/config/my.cnf[mysqld]pid-file=/data/mysql/mysqld.pidsocket=/data/mysql/mysqld.sockdatadir=/data/mysql/mysql_datalog-error=/data/mysql/logs/error.logport=13306lc-messages-dir=/data/software/mysql/mysql-5.7.29-linux-glibc2.12-x86_64/share/englishserver_id=136gtid_mode=onenforce_gtid_consistency=onskip_slave_start=1log_bin=mysql-binmax_binlog_size=100mbinlog_cache_size=4mmax_binlog_cache_size=512mbinlog_format=ROWexpire_logs_days=7binlog-ignore-db=sys,mysql,performance_schema,information_schemalog-slave-updates=ONsync_binlog=1plugin-load="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"rpl_semi_sync_master_enabled=ONrpl_semi_sync_slave_enabled=ONbind-address=0.0.0.0symbolic-links=0max_connections=1000default_storage_engine=innodbskip_external_lockinglower_case_table_names=1skip_host_cacheskip_name_resolvecharacter_set_server=utf8max_allowed_packet=12Msql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'[client]character-set-client=utf8EOF
修改文件和目录的用户权限
chown -R mysql /data/mysqlchown -R mysql /data/software/mysql/mysql-5.7.29-linux-glibc2.12-x86_64
更新 PATH 变量
echo 'MYSQL_HOME="/data/software/mysql/mysql-5.7.29-linux-glibc2.12-x86_64"' >> /etc/profileecho 'PATH=${PATH}:${MYSQL_HOME}/bin' >> /etc/profilesource /etc/profile
mysql 初始化
mysqld --initialize-insecure \--user=mysql \--basedir=/data/software/mysql/mysql-5.7.29-linux-glibc2.12-x86_64 \--datadir=/data/mysql/mysql_data
创建 systemcl 管理
cat << EOF > /usr/lib/systemd/system/mysqld.service[Unit]After=network.targetAfter=syslog.target[Install]WantedBy=multi-user.target[Service]User=mysqlType=forkingTimeoutSec=0PermissionsStartOnly=trueExecStart=/data/software/mysql/mysql-5.7.29-linux-glibc2.12-x86_64/bin/mysqld \\--defaults-file=/data/mysql/config/my.cnf --daemonize \\--plugin-dir=/data/software/mysql/mysql-5.7.29-linux-glibc2.12-x86_64/lib/pluginLimitNOFILE=5000Restart=on-failureRestartPreventExitStatus=1PrivateTmp=falseEOF
启动 mysql
systemctl daemon-reloadsystemctl enable mysqldsystemctl start mysqld
进入 mysql 验证
初始化的时候没有带密码,进入 mysql 不需要密码,直接回车就可以了
mysql -uroot -p -S /data/mysql/mysqld.sock
- 以下的操作没有特殊提示,均在 mysql 内操作
修改 root 用户密码
SET PASSWORD FOR root@localhost = PASSWORD ('abc123');
配置互为主从
从库配置主从关系
主库创建复制用户
CREATE USER 'rpldb'@'%' IDENTIFIED BY 'rpldb007';GRANT REPLICATION SLAVE ON *.* TO 'rpldb'@'%';
主库查看 binlog 名称和 Position 信息
SHOW MASTER STATUS\G
获取到类似如下的信息
*************************** 1. row *************************** File: mysql-bin.000001 Position: 841 Binlog_Do_DB: Binlog_Ignore_DB: sys,mysql,performance_schema,information_schemaExecuted_Gtid_Set: c5b4fcf9-3699-11ee-845e-000c29db9ce6:1-3
从库配置主从,下面的 ip 和用户名,密码,binlog 文件名称和 Position 都要替换成自己实际的信息
CHANGE MASTER TO MASTER_HOST='172.72.0.135', MASTER_PORT=13306, MASTER_USER='rpldb', MASTER_PASSWORD='rpldb007', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=841;
启动复制
START SLAVE;
查看 slave 情况
SHOW SLAVE STATUS\G
看到这两个都是 yes,表示主从复制已经建立成功了
Slave_IO_Running: YesSlave_SQL_Running: Yes
主库配置互为主从关系
从库创建复制用户
CREATE USER 'rpldb'@'%' IDENTIFIED BY 'rpldb007';GRANT REPLICATION SLAVE ON *.* TO 'rpldb'@'%';
从库查看 binlog 名称和 Position 信息
SHOW MASTER STATUS\G
获取到类似如下的信息
*************************** 1. row *************************** File: mysql-bin.000001 Position: 841 Binlog_Do_DB: Binlog_Ignore_DB: sys,mysql,performance_schema,information_schemaExecuted_Gtid_Set: 1d31ccb1-369d-11ee-bff2-000c29cd48ee:1-3
主库配置互为主从,下面的 ip 和用户名,密码,binlog 文件名称和 Position 都要替换成自己实际的信息
CHANGE MASTER TO MASTER_HOST='172.72.0.136', MASTER_PORT=13306, MASTER_USER='rpldb', MASTER_PASSWORD='rpldb007', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=841;
启动复制
START SLAVE;
查看 slave 情况
SHOW SLAVE STATUS\G
看到这两个都是 yes,表示主从复制已经建立成功了
Slave_IO_Running: YesSlave_SQL_Running: Yes
验证主从复制
主库创建一个测试数据
-- 建库CREATE DATABASE replication_test;-- 进入到库里USE replication_test;-- 建表CREATE TABLE replication_test.slt(num int auto_increment primary key,name char(10),job char(10),age int,salary int,descrip char(128)not null default '')charset=utf8;-- 插入数据INSERT INTO replication_test.slt(name, job, age, salary,descrip) VALUES('Tom','teacher',30,20000,'level2'),('frank','teacher',31,21000,'level2'),('jack','teacher',32,22000,'level2'),('jhon','asistant',23,8000,'level3'),('hugo','manager',45,30000,'level4'),('jinhisan','teacher',26,9000,'level1');
主库查看一下数据
SELECT * FROM replication_test.slt WHERE name='Tom';
获取到如下的信息
+-----+------+---------+------+--------+---------+| num | name | job | age| salary | descrip |+-----+------+---------+------+--------+---------+| 1 | Tom| teacher | 30 |20000 | level2|+-----+------+---------+------+--------+---------+
可以在从库看一下,同样可以获取到一样的信息
模拟主库故障
通过停止主库的服务来模拟出现故障,然后在从库继续写入数据,验证主库修复后,是否会建立数据同步
systemctl stop mysqld
在从库内看同步情况,可以看到
Slave_IO_Running
变成了Connecting
状态
在从库内继续写入数据
INSERT INTO replication_test.slt(name, job, age, salary,descrip) VALUES('Rose','teacher',30,20000,'level1'),('Maybe','manager',28,30000,'level4');
重新启动宕机的 mysql 服务
systemctl start mysqld
启动宕机 mysql 的复制
START SLAVE;
查看 slave 情况,看到
Slave_IO_Running
和Slave_SQL_Running
都是yes
即可
SHOW SLAVE STATUS\G
宕机恢复的节点进行数据查看,验证数据是否同步
SELECT * from replication_test.slt WHERE name='Maybe';
可以正常获取到数据,证明互为主从没毛病
+-----+-------+---------+------+--------+---------+| num | name| job | age| salary | descrip |+-----+-------+---------+------+--------+---------+| 8 | Maybe | manager | 28 |30000 | level4|+-----+-------+---------+------+--------+---------+