复制与高可用
大约 13 分钟约 4006 字
复制与高可用
简介
数据库复制是构建高可用、高性能数据库架构的基础技术,通过将数据从一个数据库服务器复制到其他服务器,实现数据冗余、读写分离和故障转移。本文将介绍主从复制的原理与配置、读写分离的实现方式、故障转移策略,以及 MySQL 和 SQL Server 的具体实现方案。
特点
主从复制
MySQL 主从复制
-- MySQL 主从复制基于 Binlog 实现
-- 复制流程:主库写 Binlog -> 从库 IO 线程拉取 -> 写 Relay Log -> SQL 线程重放
-- 主库配置(my.cnf)
-- [mysqld]
-- server-id = 1
-- log-bin = mysql-bin
-- binlog-format = ROW -- 推荐使用 ROW 格式
-- binlog-do-db = myapp -- 需要复制的数据库
-- expire_logs_days = 7 -- Binlog 保留天数
-- max_binlog_size = 100M
-- sync_binlog = 1 -- 每次事务提交都刷盘
-- innodb_flush_log_at_trx_commit = 1
-- 从库配置(my.cnf)
-- [mysqld]
-- server-id = 2
-- relay-log = relay-bin
-- read-only = ON -- 从库设为只读
-- log-slave-updates = ON -- 级联复制时需要
-- 主库创建复制用户
CREATE USER 'repl'@'%' IDENTIFIED BY 'Repl@123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
-- 查看主库状态
SHOW MASTER STATUS;
-- 记录 File 和 Position 值
-- 从库配置复制
CHANGE MASTER TO
MASTER_HOST = '192.168.1.100',
MASTER_PORT = 3306,
MASTER_USER = 'repl',
MASTER_PASSWORD = 'Repl@123456',
MASTER_LOG_FILE = 'mysql-bin.000001',
MASTER_LOG_POS = 154;
-- 启动复制
START SLAVE;
-- 查看复制状态
SHOW SLAVE STATUS\G
-- 关键字段:
-- Slave_IO_Running: Yes
-- Slave_SQL_Running: Yes
-- Seconds_Behind_Master: 0 -- 复制延迟秒数MySQL GTID 复制
-- GTID(Global Transaction Identifier)复制
-- 每个事务有全局唯一标识,简化复制管理
-- 主库配置
-- [mysqld]
-- gtid_mode = ON
-- enforce_gtid_consistency = ON
-- log-bin = mysql-bin
-- server-id = 1
-- 从库配置
-- [mysqld]
-- gtid_mode = ON
-- enforce_gtid_consistency = ON
-- log-bin = mysql-bin
-- server-id = 2
-- 从库配置 GTID 复制
CHANGE MASTER TO
MASTER_HOST = '192.168.1.100',
MASTER_PORT = 3306,
MASTER_USER = 'repl',
MASTER_PASSWORD = 'Repl@123456',
MASTER_AUTO_POSITION = 1; -- 使用 GTID 自动定位
START SLAVE;
SHOW SLAVE STATUS\G
-- GTID 优势
-- 1. 自动定位复制位点,无需手动指定 File 和 Position
-- 2. 主从切换更简单
-- 3. 可以方便地验证主从数据一致性半同步复制
-- 半同步复制:主库事务提交后,至少等待一个从库确认收到 Binlog
-- 比异步复制更安全,比全同步复制性能更好
-- 主库安装插件
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
SET GLOBAL rpl_semi_sync_master_enabled = ON;
SET GLOBAL rpl_semi_sync_master_timeout = 5000; -- 超时 5 秒降级为异步
-- 从库安装插件
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_slave_enabled = ON;
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;
-- 查看半同步状态
SHOW STATUS LIKE 'Rpl_semi_sync_master%';
-- Rpl_semi_sync_master_status: ON
-- Rpl_semi_sync_master_clients: 1 -- 半同步从库数量
-- Rpl_semi_sync_master_yes_tx: 100 -- 半同步成功的事务数
-- Rpl_semi_sync_master_no_tx: 0 -- 降级为异步的事务数读写分离
读写分离架构
-- 读写分离架构说明
-- | 角色 | 职责 | 连接方式 |
-- |-------|--------------------|-----------------------|
-- | 主库 | 处理所有写操作 | 写连接池 |
-- | 从库1 | 处理读操作 | 读连接池 |
-- | 从库2 | 处理读操作 | 读连接池 |
-- | 从库3 | 处理读操作 | 读连接池 |
-- C# 读写分离实现示例
-- 使用 DbContext 实现读写分离
/*
public class ReadWriteDbContext : DbContext
{
private readonly string _writeConnectionString;
private readonly string _readConnectionString;
public ReadWriteDbContext(
string writeConnectionString,
string readConnectionString)
{
_writeConnectionString = writeConnectionString;
_readConnectionString = readConnectionString;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
// 根据当前操作类型选择连接
var connectionString = IsWriteOperation()
? _writeConnectionString
: _readConnectionString;
options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
}
private bool IsWriteOperation()
{
// 通过判断当前命令类型决定读写
return Database.CurrentTransaction != null;
}
}
*/
-- MySQL 代理层读写分离(使用 MySQL Router 或 ProxySQL)
-- ProxySQL 配置示例
-- INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight)
-- VALUES (0, '192.168.1.100', 3306, 1); -- 写组
-- INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight)
-- VALUES (1, '192.168.1.101', 3306, 1); -- 读组
-- INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight)
-- VALUES (1, '192.168.1.102', 3306, 1); -- 读组
-- 配置读写路由规则
-- INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply)
-- VALUES (1, 1, '^SELECT.*FOR UPDATE', 0, 1); -- SELECT FOR UPDATE 走主库
-- INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply)
-- VALUES (2, 1, '^SELECT', 1, 1); -- 普通 SELECT 走从库复制延迟处理
-- 主从延迟是读写分离最大的挑战
-- 查看从库延迟
SHOW SLAVE STATUS\G
-- Seconds_Behind_Master 字段表示延迟秒数
-- 常见延迟原因和解决方案
-- 1. 大事务导致延迟
-- 避免:不要在一个事务中处理大量数据
-- 不好的做法
BEGIN;
DELETE FROM logs WHERE created_at < '2025-01-01'; -- 可能删除百万行
COMMIT;
-- 好的做法:分批处理
DELETE FROM logs WHERE created_at < '2025-01-01' LIMIT 1000;
-- 循环执行直到影响行数为 0
-- 2. 从库硬件不足
-- 确保从库的硬件配置至少与主库相当
-- 特别是磁盘 I/O 性能
-- 3. 多线程复制(MySQL 5.7+)
-- 从库配置
-- [mysqld]
-- slave_parallel_type = LOGICAL_CLOCK
-- slave_parallel_workers = 4 -- 并行工作线程数
-- slave_preserve_commit_order = ON
STOP SLAVE;
SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';
SET GLOBAL slave_parallel_workers = 4;
SET GLOBAL slave_preserve_commit_order = ON;
START SLAVE;
-- 4. 强制走主库读取(对一致性要求高的场景)
-- 在 SQL 中使用提示
-- /*# MASTER */ SELECT * FROM orders WHERE id = 100;故障转移
MySQL MHA 高可用
# MHA(Master High Availability)是 MySQL 最成熟的高可用方案
# MHA 架构
# | 组件 | 说明 |
# |--------------|-------------------------------|
# | MHA Manager | 管理节点,监控主库并执行故障转移 |
# | MHA Node | 数据节点,运行在每个 MySQL 服务器上 |
# 安装 MHA Node(所有 MySQL 服务器)
yum install mha4mysql-node
# 安装 MHA Manager(管理服务器)
yum install mha4mysql-manager
# MHA 配置文件(/etc/mha/app1.cnf)
# [server default]
# manager_workdir=/var/log/mha/app1
# manager_log=/var/log/mha/app1/manager.log
# user=mha_monitor
# password=Mha@123456
# repl_user=repl
# repl_password=Repl@123456
# ssh_user=root
# [server1]
# hostname=192.168.1.100
# port=3306
# candidate_master=1
# [server2]
# hostname=192.168.1.101
# port=3306
# candidate_master=1
# [server3]
# hostname=192.168.1.102
# port=3306
# candidate_master=1
# 检查 SSH 连通性
masterha_check_ssh --conf=/etc/mha/app1.cnf
# 检查复制状态
masterha_check_repl --conf=/etc/mha/app1.cnf
# 启动 MHA Manager
masterha_manager --conf=/etc/mha/app1.cnf &MySQL 组复制(Group Replication)
-- MySQL Group Replication 是基于 Paxos 协议的高可用方案
-- 支持单主模式和多主模式
-- 配置 Group Replication
-- [mysqld]
-- server-id = 1
-- gtid_mode = ON
-- enforce_gtid_consistency = ON
-- log-bin = mysql-bin
-- binlog-format = ROW
-- plugin-load = group_replication.so
-- group_replication_group_name = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
-- group_replication_start_on_boot = OFF
-- group_replication_local_address = "192.168.1.100:33061"
-- group_replication_group_seeds = "192.168.1.100:33061,192.168.1.101:33061,192.168.1.102:33061"
-- group_replication_bootstrap_group = OFF
-- 引导组(仅在第一个节点执行)
SET GLOBAL group_replication_bootstrap_group = ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group = OFF;
-- 其他节点加入组
START GROUP_REPLICATION;
-- 查看组成员
SELECT * FROM performance_schema.replication_group_members;
-- | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
-- |--------------|----------------|-------------|-------------|
-- | uuid-1 | 192.168.1.100 | 3306 | ONLINE |
-- | uuid-2 | 192.168.1.101 | 3306 | ONLINE |
-- | uuid-3 | 192.168.1.102 | 3306 | ONLINE |
-- 查看主节点
SELECT MEMBER_HOST AS primary_node
FROM performance_schema.replication_group_members
WHERE MEMBER_ROLE = 'PRIMARY';SQL Server 高可用方案
Always On 可用性组
-- SQL Server Always On 可用性组
-- 企业级高可用和灾难恢复方案
-- 前提条件:Windows Server Failover Cluster (WSFC)
-- 创建可用性组
CREATE AVAILABILITY GROUP [AG_MyApp]
FOR
DATABASE myapp_db
REPLICA ON
N'SQL-NODE1' WITH (
ENDPOINT_URL = 'TCP://SQL-NODE1:5022',
AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
FAILOVER_MODE = AUTOMATIC,
SECONDARY_ROLE(ALLOW_CONNECTIONS = READ_ONLY)
),
N'SQL-NODE2' WITH (
ENDPOINT_URL = 'TCP://SQL-NODE2:5022',
AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
FAILOVER_MODE = AUTOMATIC,
SECONDARY_ROLE(ALLOW_CONNECTIONS = READ_ONLY)
),
N'SQL-NODE3' WITH (
ENDPOINT_URL = 'TCP://SQL-NODE3:5022',
AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT,
FAILOVER_MODE = MANUAL,
SECONDARY_ROLE(ALLOW_CONNECTIONS = READ_ONLY)
);
-- 查看可用性组状态
SELECT
ag.name AS availability_group,
ar.replica_server_name,
ar.availability_mode_desc,
ar.failover_mode_desc,
drs.synchronization_state_desc,
drs.synchronization_health_desc
FROM sys.availability_groups ag
JOIN sys.availability_replicas ar ON ag.group_id = ar.group_id
JOIN sys.dm_hadr_database_replica_states drs
ON ar.replica_id = drs.replica_id;
-- 手动故障转移
ALTER AVAILABILITY GROUP [AG_MyApp] FAILOVER;
-- 只读路由配置(自动将读请求路由到辅助副本)
ALTER AVAILABILITY GROUP [AG_MyApp]
MODIFY REPLICA ON N'SQL-NODE1' WITH (
SECONDARY_ROLE(READ_ONLY_ROUTING_URL = 'TCP://SQL-NODE1:1433')
);
ALTER AVAILABILITY GROUP [AG_MyApp]
MODIFY REPLICA ON N'SQL-NODE2' WITH (
SECONDARY_ROLE(READ_ONLY_ROUTING_URL = 'TCP://SQL-NODE2:1433')
);
-- 配置只读路由列表
ALTER AVAILABILITY GROUP [AG_MyApp]
MODIFY REPLICA ON N'SQL-NODE1' WITH (
PRIMARY_ROLE(READ_ONLY_ROUTING_LIST = (N'SQL-NODE2', N'SQL-NODE3'))
);数据库镜像
-- SQL Server 数据库镜像(较老的高可用方案)
-- | 模式 | 说明 | 安全性 | 性能 |
-- |-----------|--------------------------|-------|------|
-- | 高安全性 | 同步提交,自动故障转移 | 高 | 较低 |
-- | 高性能 | 异步提交,手动故障转移 | 较低 | 高 |
-- 主体服务器配置
-- 确保数据库处于完整恢复模式
ALTER DATABASE myapp_db SET RECOVERY FULL;
-- 创建端点
CREATE ENDPOINT [Mirroring]
STATE = STARTED
AS TCP (LISTENER_PORT = 5022)
FOR DATABASE_MIRRORING (ROLE = PARTNER, ENCRYPTION = REQUIRED);
-- 配置镜像伙伴
ALTER DATABASE myapp_db SET PARTNER = 'TCP://SQL-MIRROR:5022';
-- 配置见证服务器(用于自动故障转移)
ALTER DATABASE myapp_db SET WITNESS = 'TCP://SQL-WITNESS:5022';
-- 查看镜像状态
SELECT
DB_NAME(database_id) AS database_name,
mirroring_state_desc,
mirroring_role_desc,
mirroring_safety_level_desc,
mirroring_partner_name
FROM sys.database_mirroring;优点
缺点
总结
数据库复制与高可用是构建生产级数据库架构的关键技术。MySQL 的主从复制基于 Binlog 实现,支持异步、半同步和组复制等多种模式。读写分离通过将读请求分散到从库来提升吞吐量,但需要关注复制延迟问题。故障转移机制(如 MHA、Group Replication、Always On)可以在主库故障时自动切换,保证服务的持续可用。在实际应用中,需要根据业务对数据一致性、可用性和性能的要求来选择合适的方案。
关键知识点
- 数据库主题一定要同时看数据模型、读写模式和执行代价。
- 很多性能问题不是 SQL 语法问题,而是索引、统计信息、事务和数据分布问题。
- 高可用、备份、迁移和治理与查询优化同样重要。
- 先把数据模型、访问模式和执行代价绑定起来理解。
项目落地视角
- 所有优化前后都保留执行计划、样本 SQL 和关键指标对比。
- 上线前准备回滚脚本、备份点和校验方案。
- 把连接池、锁等待、慢查询和容量增长纳入日常巡检。
- 保留执行计划、样本 SQL、索引定义和优化前后指标。
常见误区
- 脱离真实数据分布讨论索引或分片。
- 只看单条 SQL,不看整条业务链路的事务和锁。
- 把测试环境结论直接等同于生产环境结论。
- 脱离真实数据分布设计索引。
进阶路线
- 继续向执行计划、存储引擎、复制机制和数据治理层深入。
- 把主题与 ORM、缓存、消息队列和归档策略联动起来思考。
- 沉淀成数据库设计规范、SQL 审核规则和变更流程。
- 继续深入存储引擎、复制机制、归档与冷热分层治理。
适用场景
- 当你准备把《复制与高可用》真正落到项目里时,最适合先在一个独立模块或最小样例里验证关键路径。
- 适合数据建模、查询优化、事务控制、高可用和迁移治理。
- 当系统开始遇到慢查询、锁冲突、热点数据或容量增长时,这类主题价值最高。
落地建议
- 先分析真实查询模式、数据量级和写入特征,再决定索引或分片策略。
- 所有优化结论都结合执行计划、样本数据和监控指标验证。
- 高风险操作前准备备份、回滚脚本与校验 SQL。
排错清单
- 先确认瓶颈在 CPU、I/O、锁等待、网络还是 SQL 本身。
- 检查执行计划是否走错索引、是否发生排序或全表扫描。
- 排查长事务、隐式类型转换、统计信息过期和参数嗅探。
复盘问题
- 如果把《复制与高可用》放进你的当前项目,最先要验证的输入、输出和失败路径分别是什么?
- 《复制与高可用》最容易在什么规模、什么边界条件下暴露问题?你会用什么指标或日志去确认?
- 相比默认实现或替代方案,采用《复制与高可用》最大的收益和代价分别是什么?
复制监控与告警
MySQL 复制监控
-- ========== 复制健康检查脚本 ==========
-- 检查从库状态
SELECT
NOW() AS check_time,
@@hostname AS host_name,
Slave_IO_Running AS io_running,
Slave_SQL_Running AS sql_running,
Seconds_Behind_Master AS delay_seconds,
Master_Host,
Master_Port,
Master_Log_File,
Read_Master_Log_Pos,
Relay_Master_Log_File,
Exec_Master_Log_Pos,
Last_Error,
Last_IO_Error,
Last_SQL_Error,
Replicate_Do_DB,
Replicate_Ignore_DB
FROM (
SHOW SLAVE STATUS
) AS slave_status;
-- 检查 GTID 执行情况(GTID 模式)
SELECT
@@global.gtid_executed AS executed_gtids,
@@global.gtid_purged AS purged_gtids,
@@global.gtid_mode AS gtid_mode;
-- 检查从库延迟(更精确的方法)
-- 使用 heartbeat 表
CREATE TABLE IF NOT EXISTS mysql.heartbeat (
server_id INT PRIMARY KEY,
ts TIMESTAMP(6) NOT NULL
);
-- 主库定时更新 heartbeat
INSERT INTO mysql.heartbeat (server_id, ts)
VALUES (1, NOW(6))
ON DUPLICATE KEY UPDATE ts = NOW(6);
-- 从库计算精确延迟
SELECT
TIMESTAMPDIFF(MICROSECOND, ts, NOW(6)) / 1000000 AS delay_seconds
FROM mysql.heartbeat
WHERE server_id = 1;复制延迟告警阈值
-- 复制延迟告警策略
-- | 延迟时间 | 级别 | 处理方式 |
-- |-----------|--------|---------------------|
-- | < 1秒 | 正常 | 无需处理 |
-- | 1-10秒 | 警告 | 关注,检查负载 |
-- | 10-60秒 | 严重 | 检查大事务和从库性能 |
-- | > 60秒 | 紧急 | 将读请求切回主库 |
-- 检查是否有大事务阻塞复制
SELECT
trx_id,
trx_state,
trx_started,
TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS duration_seconds,
trx_query,
trx_tables_locked,
trx_rows_locked
FROM information_schema.innodb_trx
ORDER BY trx_started;
-- 检查 Binlog 大小和增长
SHOW BINARY LOGS;
-- 如果 Binlog 增长过快,可能是大事务或批量操作复制故障自动切换脚本
#!/bin/bash
# mysql_failover.sh — MySQL 主从故障切换脚本
MASTER_HOST="192.168.1.100"
CANDIDATE_HOST="192.168.1.101"
REPL_USER="repl"
REPL_PASS="Repl@123456"
MAX_DELAY=10
# 检查主库是否可达
check_master() {
mysqladmin ping -h "$MASTER_HOST" -u root -p"$ROOT_PASS" --connect_timeout=5 > /dev/null 2>&1
return $?
}
# 检查从库延迟
check_slave_delay() {
local host=$1
local delay=$(mysql -h "$host" -u root -p"$ROOT_PASS" -e "SHOW SLAVE STATUS\G" 2>/dev/null | grep "Seconds_Behind_Master" | awk '{print $2}')
echo "${delay:-9999}"
}
# 执行故障切换
do_failover() {
echo "[$(date)] 开始故障切换..."
# 1. 确认候选从库延迟最小
delay=$(check_slave_delay "$CANDIDATE_HOST")
echo "[$(date)] 候选从库延迟: ${delay}秒"
if [ "$delay" -gt "$MAX_DELAY" ]; then
echo "[$(date)] 候选从库延迟过大 (${delay}s),终止切换"
exit 1
fi
# 2. 停止候选从库的复制
mysql -h "$CANDIDATE_HOST" -u root -p"$ROOT_PASS" -e "STOP SLAVE; RESET SLAVE ALL;"
echo "[$(date)] 候选从库已停止复制"
# 3. 设置新主库读写
mysql -h "$CANDIDATE_HOST" -u root -p"$ROOT_PASS" -e "SET GLOBAL read_only=OFF; SET GLOBAL super_read_only=OFF;"
echo "[$(date)] 新主库已设置为可读写"
# 4. 更新 VIP(如果有)
# ip addr add 192.168.1.200/24 dev eth0
echo "[$(date)] 故障切换完成,新主库: $CANDIDATE_HOST"
}
# 主逻辑
if ! check_master; then
echo "[$(date)] 主库 $MASTER_HOST 不可达"
do_failover
else
echo "[$(date)] 主库正常"
fiSQL Server Always On 进阶
只读路由配置
-- 完整的只读路由配置
-- 1. 为每个副本配置只读路由 URL
ALTER AVAILABILITY GROUP [AG_MyApp]
MODIFY REPLICA ON N'SQL-NODE1' WITH (
SECONDARY_ROLE(READ_ONLY_ROUTING_URL = 'TCP://SQL-NODE1.company.com:1433')
);
ALTER AVAILABILITY GROUP [AG_MyApp]
MODIFY REPLICA ON N'SQL-NODE2' WITH (
SECONDARY_ROLE(READ_ONLY_ROUTING_URL = 'TCP://SQL-NODE2.company.com:1433')
);
-- 2. 配置路由列表(主副本角色)
ALTER AVAILABILITY GROUP [AG_MyApp]
MODIFY REPLICA ON N'SQL-NODE1' WITH (
PRIMARY_ROLE(READ_ONLY_ROUTING_LIST = (N'SQL-NODE2', N'SQL-NODE3'))
);
ALTER AVAILABILITY GROUP [AG_MyApp]
MODIFY REPLICA ON N'SQL-NODE2' WITH (
PRIMARY_ROLE(READ_ONLY_ROUTING_LIST = (N'SQL-NODE1', N'SQL-NODE3'))
);
-- 3. 连接字符串配置
-- ApplicationIntent=ReadOnly 会自动路由到辅助副本
-- Server=AG_MyApp_Listener;Database=myapp;Integrated Security=SSPI;ApplicationIntent=ReadOnly
-- 监控同步状态
SELECT
ag.name AS ag_name,
ar.replica_server_name,
drs.synchronization_state_desc,
drs.synchronization_health_desc,
drs.is_suspended,
drs.suspend_reason_desc,
drs.last_sent_time,
drs.last_received_time,
drs.last_hardened_time,
drs.last_redone_time,
LOG_send_rate_KB = drs.log_send_rate,
Redo_rate_KB = drs.redo_rate
FROM sys.dm_hadr_database_replica_states drs
JOIN sys.availability_replicas ar ON drs.replica_id = ar.replica_id
JOIN sys.availability_groups ag ON ar.group_id = ag.group_id;分布式可用性组
-- SQL Server 2016+ 支持跨集群的分布式可用性组
-- 场景:主数据中心和灾备数据中心
-- 在主集群上创建
CREATE AVAILABILITY GROUP [AG_Distributed]
WITH (DISTRIBUTED)
ON
'AG_Primary_DC' WITH (
LISTENER_URL = 'TCP://AG-Primary-Listener:5022',
AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT,
FAILOVER_MODE = MANUAL,
SEEDING_MODE = AUTOMATIC
),
'AG_Secondary_DC' WITH (
LISTENER_URL = 'TCP://AG-Secondary-Listener:5022',
AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT,
FAILOVER_MODE = MANUAL,
SEEDING_MODE = AUTOMATIC
);
-- 灾备集群上加入
ALTER AVAILABILITY GROUP [AG_Distributed]
GRANT CREATE ANY DATABASE;MySQL InnoDB Cluster(官方高可用方案)
-- MySQL 8.0+ InnoDB Cluster 是官方推荐的高可用方案
-- 基于 MySQL Shell + Group Replication + MySQL Router
-- 1. 使用 MySQL Shell 创建集群
-- \connect root@192.168.1.100:3306
-- var cluster = dba.createCluster('MyCluster', {gtidSetIsComplete: true});
-- 2. 添加实例
-- cluster.addInstance('root@192.168.1.101:3306', {recoveryMethod: 'clone'});
-- cluster.addInstance('root@192.168.1.102:3306', {recoveryMethod: 'clone'});
-- 3. 查看集群状态
-- cluster.status()
-- 4. 配置 MySQL Router(自动路由读写)
-- mysqlrouter --bootstrap root@192.168.1.100:3306 --user=mysqlrouter
-- MySQL Router 会自动提供:
-- 读写端口 (6446) — 路由到主库
-- 只读端口 (6447) — 路由到从库
-- 5. 应用连接 MySQL Router
-- 读写: mysql -h 127.0.0.1 -P 6446 -u app -p
-- 只读: mysql -h 127.0.0.1 -P 6447 -u app -p
-- 常见运维操作
-- cluster.removeInstance('root@192.168.1.102:3306') -- 移除实例
-- cluster.rejoinInstance('root@192.168.1.102:3306') -- 重新加入
-- cluster.setPrimaryInstance('root@192.168.1.101:3306') -- 切换主库
-- cluster.switchToMultiPrimaryMode() -- 切换为多主模式
-- cluster.switchToSinglePrimaryMode('root@192.168.1.100:3306') -- 切回单主