实践项目-数据库主从高可用(MySQL-MHA、ProxySQL、Backup)

news/2025/1/5 15:39:02/文章来源:https://www.cnblogs.com/mugetsukun/p/18648202

(250103)

实践目标

备份策略:定期全量备份和增量备份,备份文件异地存储。
恢复测试:定期在测试库上恢复备份,确保备份文件可用。
权限管理:严格控制数据库访问权限,避免误操作。
变更管理:所有数据库变更需经过审批,并在非高峰时段执行。
监控告警:实时监控数据库状态,设置告警机制,及时发现并处理问题。
同步延迟:监控主从同步延迟,确保数据一致性。
备份验证:定期验证备份文件的完整性和可恢复性。
安全防护:加强数据库安全防护,防止数据泄露和攻击。

环境

操作系统:Debian 12.8
节点规划:
主库:192.168.100.1
从库1:192.168.100.2
从库2:192.168.100.3
MHA 管理节点:192.168.100.4
读写分离中间件:192.168.100.5
备份服务器:192.168.100.6
测试库:192.168.100.7
(默认进行过ssh-copy-id)

MySQL安装

(所有的节点)

wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.40.tar.gztar -zxvf mysql-8.0.40.tar.gz -C /usr/local/
mv /usr/local/mysql-8.0.40 /usr/local/mysqlgroupadd mysql
useradd -r -g mysql -s /bin/false mysql/usr/local/mysql/bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data/usr/local/mysql/bin/mysqld_safe --user=mysql &

主从搭建

主库配置
my.cnf

[mysqld]
server-id=1
log-bin=mysql-bin
binlog-do-db=database_name
/usr/local/mysql/bin/mysqladmin -u root -p shutdown
/usr/local/mysql/bin/mysqld_safe --user=mysql &

从库配置
my.cnf

[mysqld]
server-id=2  # 从库1
server-id=3  # 从库2
relay-log=mysql-relay-bin
/usr/local/mysql/bin/mysqladmin -u root -p shutdown
/usr/local/mysql/bin/mysqld_safe --user=mysql &

主库授权

CREATE USER 'replica'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'replica'@'%';
FLUSH PRIVILEGES;

从库同步

CHANGE MASTER TO
MASTER_HOST='192.168.100.1',
MASTER_USER='replica',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=4;
START SLAVE;

检查同步

SHOW SLAVE STATUS\G;

确保Slave_IO_RunningSlave_SQL_Running都为 Yes。

Binlog 配置排错

检查 Binlog 配置
确保主库和从库的 my.cnf 文件中正确配置了 log-bin 和 server-id。
检查 Binlog 文件
在主库上检查 Binlog 文件是否存在:

ls /usr/local/mysql/data/mysql-bin.*

检查 Binlog 写入权限
确保 MySQL 用户对 Binlog 文件有写入权限:

ls -l /usr/local/mysql/data/mysql-bin.*

检查 Binlog 同步状态
在从库上检查 Binlog 同步状态,确保 Slave_IO_Running 和 Slave_SQL_Running 都为 Yes。

MHA主库-github
MHA从库-github

MHA 搭建

安装 MHA 依赖
(MHA管理节点)

sudo apt-get install perl libdbd-mysql-perl libconfig-tiny-perl liblog-dispatch-perl libparallel-forkmanager-perl

(从库)

sudo apt-get install perl libdbd-mysql-perl

下载并安装 MHA
(MHA管理节点)

wget https://github.com/yoshinorim/mha4mysql-manager/archive/refs/tags/v0.58.tar.gz
tar -zxvf v0.58.tar.gz
cd mha4mysql-manager-0.58
perl Makefile.PL
make
make install

(从库)

wget https://github.com/yoshinorim/mha4mysql-node/archive/refs/tags/v0.58.tar.gz
tar -xvf v0.58.tar.gz
cd mha4mysql-node-0.58
perl Makefile.PL
make
make install

配置 MHA
/etc/mha/app1.cnf

[server default]
manager_workdir=/var/log/mha/app1
manager_log=/var/log/mha/app1/manager.log
master_binlog_dir=/usr/local/mysql/data
user=root
password=password
ssh_user=root
repl_user=replica
repl_password=password
ping_interval=3[server1]
hostname=192.168.100.1
candidate_master=1[server2]
hostname=192.168.100.2
candidate_master=1[server3]
hostname=192.168.100.3
candidate_master=1[server default]
manager_workdir=/var/log/mha/app1
manager_log=/var/log/mha/app1/manager.log
master_binlog_dir=/usr/local/mysql/data
user=root
password=password
ssh_user=root
repl_user=replica
repl_password=password
ping_interval=3
master_ip_failover_script=/usr/local/bin/mha_failover.sh

启动 MHA

masterha_manager --conf=/etc/mha/app1.cnf

检查 MHA 状态

masterha_check_status --conf=/etc/mha/app1.cnf

读写分离

proxysql-github
安装依赖

apt-get update && apt-get install -y --no-install-recommends lsb-release wget apt-transport-https ca-certificates
wget -nv -O /etc/apt/trusted.gpg.d/proxysql-2.4.x-keyring.gpg 'https://repo.proxysql.com/ProxySQL/proxysql-2.4.x/repo_pub_key.gpg'
echo "deb https://repo.proxysql.com/ProxySQL/proxysql-2.4.x/$(lsb_release -sc)/ ./" | tee /etc/apt/sources.list.d/proxysql.list

安装ProxySQL

apt-get update
apt-get install proxysql OR apt-get install proxysql=version

配置 ProxySQL
/etc/proxysql.cnf

datadir="/var/lib/proxysql"
admin_variables=
{admin_credentials="admin:admin"mysql_ifaces="0.0.0.0:6032"
}mysql_variables=
{threads=4max_connections=2048default_query_delay=0default_query_timeout=36000000have_compress=truepoll_timeout=2000interfaces="0.0.0.0:6033"default_schema="information_schema"stacksize=1048576server_version="8.0.40"connect_timeout_server=10000
}mysql_servers =
({ address="192.168.100.1", port=3306, hostgroup=1 },  # 主库(写操作){ address="192.168.100.2", port=3306, hostgroup=2 },  # 从库1(读操作){ address="192.168.100.3", port=3306, hostgroup=2 }   # 从库2(读操作)
)mysql_users =
({ username = "root", password = "password", default_hostgroup = 1 }
)mysql_query_rules =
({rule_id=1active=1match_pattern="^SELECT"destination_hostgroup=2apply=1},{rule_id=2active=1match_pattern=".*"destination_hostgroup=1apply=1}
)

启动 ProxySQL

sudo systemctl start proxysql
sudo systemctl enable proxysql

测试读写分离

mysql -u root -p -h 192.168.100.5 -P 6033

执行以下 SQL 语句,验证读写分离是否生效
写操作(应路由到主库)

INSERT INTO test_table (name) VALUES ('test');

读操作(应路由到从库)

SELECT * FROM test_table;

MHA故障转移

/usr/local/bin/mha_failover.sh

#!/bin/bash
# MHA 故障转移脚本# 定义变量
MHA_CONF="/etc/mha/app1.cnf"
LOG_FILE="/var/log/mha/failover.log"
MAIL_TO="admin@example.com"
MAIL_SUBJECT="MHA Failover Notification"# 记录日志
log() {echo "$(date '+%Y-%m-%d %H:%M:%S') - \$1" >> $LOG_FILE
}# 发送邮件通知
send_mail() {echo "\$1" | mail -s "$MAIL_SUBJECT" "$MAIL_TO"
}# 主库故障检测
log "Starting MHA failover process..."# 提升从库为主库
log "Promoting new master..."
masterha_master_switch --conf=$MHA_CONF --master_state=dead --dead_master_host=192.168.100.1 --new_master_host=192.168.100.2 --interactive=0# 检查提升结果
if [ $? -eq 0 ]; thenlog "New master promoted successfully: 192.168.100.2"send_mail "MHA failover completed successfully. New master: 192.168.100.2"
elselog "Failed to promote new master."send_mail "MHA failover failed. Please check the logs."exit 1
fi# 重新配置其他从库
log "Reconfiguring other slaves..."
masterha_conf_host --command=apply --conf=$MHA_CONF --host=192.168.100.3# 检查重新配置结果
if [ $? -eq 0 ]; thenlog "Slave 192.168.100.3 reconfigured successfully."
elselog "Failed to reconfigure slave 192.168.100.3."send_mail "Failed to reconfigure slave 192.168.100.3. Please check the logs."exit 1
fi# 更新 ProxySQL 配置
log "Updating ProxySQL configuration..."
mysql -h 192.168.100.5 -P 6032 -u admin -padmin -e "
DELETE FROM mysql_servers WHERE hostgroup_id=1;
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (1, '192.168.100.2', 3306);
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
"if [ $? -eq 0 ]; thenlog "ProxySQL configuration updated successfully."
elselog "Failed to update ProxySQL configuration."send_mail "Failed to update ProxySQL configuration. Please check the logs."exit 1
filog "MHA failover process completed."

chmod +x /usr/local/bin/mha_failover.sh

脚本测试

手动停止主库的 MySQL 服务

/usr/local/mysql/bin/mysqladmin -u root -p shutdown

触发故障转移

masterha_master_switch --conf=/etc/mha/app1.cnf --master_state=dead --dead_master_host=192.168.100.1 --new_master_host=192.168.100.2 --interactive=0

检查日志
查看故障转移日志/var/log/mha/failover.log,确保脚本执行成功。

备份和恢复方案

使用mysqldump进行全量备份,并将备份文件推送到备份服务器。

创建备份脚本
/usr/local/bin/mysql_backup.sh:

#!/bin/bash
# MySQL 全量备份脚本# 定义变量
BACKUP_DIR="/backup/mysql"
BACKUP_FILE="$BACKUP_DIR/full_backup_$(date +%F).sql"
LOG_FILE="/var/log/mysql_backup.log"
MYSQL_USER="root"
MYSQL_PASSWORD="password"
BACKUP_SERVER="192.168.100.6"
BACKUP_SERVER_DIR="/backup/mysql"# 记录日志
log() {echo "$(date '+%Y-%m-%d %H:%M:%S') - \$1" >> $LOG_FILE
}# 创建备份目录
mkdir -p $BACKUP_DIR# 执行全量备份
log "Starting MySQL full backup..."
mysqldump -u $MYSQL_USER -p$MYSQL_PASSWORD --all-databases --single-transaction --master-data=2 > $BACKUP_FILE# 检查备份结果
if [ $? -eq 0 ]; thenlog "MySQL full backup completed successfully: $BACKUP_FILE"
elselog "MySQL full backup failed."exit 1
fi# 推送备份文件到备份服务器
log "Pushing backup file to backup server..."
scp $BACKUP_FILE $BACKUP_SERVER:$BACKUP_SERVER_DIR# 检查推送结果
if [ $? -eq 0 ]; thenlog "Backup file pushed to backup server successfully."
elselog "Failed to push backup file to backup server."exit 1
filog "MySQL backup process completed."
chmod +x /usr/local/bin/mysql_backup.shcrontab -e
0 2 * * * /usr/local/bin/mysql_backup.sh

增量备份
通过mysqlbinlog工具进行增量备份。

/usr/local/bin/mysql_incremental_backup.sh

#!/bin/bash
# MySQL 增量备份脚本# 定义变量
BACKUP_DIR="/backup/mysql"
BACKUP_FILE="$BACKUP_DIR/incremental_backup_$(date +%F).sql"
LOG_FILE="/var/log/mysql_incremental_backup.log"
MYSQL_BINLOG_DIR="/usr/local/mysql/data"
BACKUP_SERVER="192.168.100.6"
BACKUP_SERVER_DIR="/backup/mysql"# 记录日志
log() {echo "$(date '+%Y-%m-%d %H:%M:%S') - \$1" >> $LOG_FILE
}# 创建备份目录
mkdir -p $BACKUP_DIR# 执行增量备份
log "Starting MySQL incremental backup..."
mysqlbinlog --raw --read-from-remote-server --host=192.168.100.1 --user=root --password=password --result-file=$BACKUP_FILE $(ls -t $MYSQL_BINLOG_DIR/mysql-bin.* | head -n 1)# 检查备份结果
if [ $? -eq 0 ]; thenlog "MySQL incremental backup completed successfully: $BACKUP_FILE"
elselog "MySQL incremental backup failed."exit 1
fi# 推送备份文件到备份服务器
log "Pushing backup file to backup server..."
scp $BACKUP_FILE $BACKUP_SERVER:$BACKUP_SERVER_DIR# 检查推送结果
if [ $? -eq 0 ]; thenlog "Backup file pushed to backup server successfully."
elselog "Failed to push backup file to backup server."exit 1
filog "MySQL incremental backup process completed."
chmod +x /usr/local/bin/mysql_incremental_backup.shcrontab -e
0 * * * * /usr/local/bin/mysql_incremental_backup.sh

备份恢复

在需要恢复数据时,可以使用全量备份和增量备份文件进行恢复。

全量恢复
在目标 MySQL 实例上执行全量恢复:

mysql -u root -p < /backup/mysql/full_backup_{{date}}.sql

增量恢复
在目标 MySQL 实例上执行增量恢复:

mysqlbinlog /backup/mysql/incremental_backup_{{date}}.sql | mysql -u root -p

将备份数据定期恢复到测试库

恢复流程
创建测试库
在测试库节点(192.168.100.7)上安装 MySQL,并创建与生产环境相同的数据库结构。

恢复全量备份

mysql -u root -p < /backup/mysql/full_backup_2023-10-01.sql

恢复增量备份

mysqlbinlog /backup/mysql/incremental_backup_2023-10-01.sql | mysql -u root -p

验证恢复结果
在测试库上执行以下操作,验证数据恢复结果:

  • 检查数据完整性。
  • 运行开发测试用例,确保业务逻辑正常。

自动化恢复脚本

/usr/local/bin/mysql_restore_test.sh

#!/bin/bash
# MySQL 测试库恢复脚本# 定义变量
BACKUP_DIR="/backup/mysql"
TEST_DB_HOST="192.168.100.7"
TEST_DB_USER="root"
TEST_DB_PASSWORD="password"
LOG_FILE="/var/log/mysql_restore_test.log"# 记录日志
log() {echo "$(date '+%Y-%m-%d %H:%M:%S') - \$1" >> $LOG_FILE
}# 恢复全量备份
log "Starting MySQL full backup restore..."
mysql -h $TEST_DB_HOST -u $TEST_DB_USER -p$TEST_DB_PASSWORD < $BACKUP_DIR/full_backup_$(date +%F).sql# 检查恢复结果
if [ $? -eq 0 ]; thenlog "MySQL full backup restore completed successfully."
elselog "MySQL full backup restore failed."exit 1
fi# 恢复增量备份
log "Starting MySQL incremental backup restore..."
mysqlbinlog $BACKUP_DIR/incremental_backup_$(date +%F).sql | mysql -h $TEST_DB_HOST -u $TEST_DB_USER -p$TEST_DB_PASSWORD# 检查恢复结果
if [ $? -eq 0 ]; thenlog "MySQL incremental backup restore completed successfully."
elselog "MySQL incremental backup restore failed."exit 1
filog "MySQL test database restore process completed."
chmod +x /usr/local/bin/mysql_restore_test.shcrontab -e
0 3 * * * /usr/local/bin/mysql_restore_test.sh

人工更新数据库的流程及制度

更新流程

更新申请
申请人:开发人员或运维人员。
申请内容:包括更新的 SQL 语句、更新原因、更新时间等。
申请方式:通过工单系统或邮件提交申请。

更新审批
审批人:数据库管理员(DBA)或相关负责人。
审批内容:审核 SQL 语句的正确性、更新对系统的影响等。
审批方式:通过工单系统或邮件进行审批。

更新执行
执行人:数据库管理员(DBA)或授权人员。
执行步骤:
备份数据:在执行更新前,先对相关表或数据库进行备份。
执行更新:在非高峰时段执行更新操作。
验证更新:检查更新结果,确保数据一致性和业务正常运行。
记录日志:记录更新操作的详细信息,包括执行时间、执行人、更新内容等。
更新回滚
回滚条件:如果更新导致数据不一致或业务异常,立即执行回滚操作。

回滚步骤:

  • 停止更新:立即停止所有相关操作。
  • 恢复数据:使用备份文件恢复数据。
  • 验证恢复:检查数据恢复结果,确保业务正常运行。
  • 记录日志:记录回滚操作的详细信息,包括回滚时间、回滚人、回滚内容等。

更新制度

更新权限
权限分配:只有经过授权的数据库管理员(DBA)或相关人员才能执行更新操作。
权限管理:定期审查和更新权限分配,确保权限最小化。
更新时间
非高峰时段:更新操作应在非高峰时段进行,避免影响业务正常运行。
紧急更新:对于紧急更新,需经过特别审批,并在执行前通知相关人员。
更新记录
记录内容:每次更新操作都需详细记录,包括更新内容、执行时间、执行人、审批人等。
记录保存:更新记录应长期保存,便于后续审计和查询。
更新培训
培训内容:定期对相关人员进行数据库更新操作的培训,确保操作规范和安全。
培训记录:记录培训内容和参与人员,确保培训效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/863333.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.Net程序员机会来了,微软官方新推出一个面向Windows开发者本地运行AI模型的开源工具

想要开发AI产品的.Net程序员机会来了,这个项目应该好好研究。 虽然说大模型基本都有提供网络API,但肯定没有直接使用本地模型速度快。 最近微软官方新推出AI Dev Gallery开源项目,可以帮助Windows开发人员学习如何将具有本地模型和API的AI添加到Windows应用程序中。01 项目简…

ABB工业机器人SIB-V板维修细节分享

要判断ABB机器人SIB-v板是否需要更换,可以从以下几个方面进行评估: - 检查SIB-v板的状态:查看SIB-v板是否有明显的物理损坏,如烧焦、裂纹或其他损坏迹象。 - 检查连接情况:确保SIB-v板与其他组件的连接牢固,没有松动或腐蚀。 - 检查电池状态:如果SIB-v板上有…

KUKA机械臂驱动器600-20 1X64 UL故障维修细节

库卡机器人作为工业自动化的重要设备,其稳定性和可靠性对于生产线的正常运转至关重要。然而,在使用过程中,KUKA机械臂驱动器故障是不可避免的问题之一。 一、常见KUKA机械手驱动器故障及原因分析 1. 过热故障 过热是常见的库卡工业机器人驱动器600-20 1X64 UL故障之一。这通…

PostgreSQL技术大讲堂 - 第77讲:DB4AI 搭建PG向量数据库AI机器人

PostgreSQL技术大讲堂 - 第77讲,主题:DB4AI 搭建PG向量数据库AI机器人 讲课内容: 1、 向量搜索引擎(PGVector)介绍 2、 向量与Embeddings的定义 3、 向量间的相似度计算方法演示 4、检索增强生成模型(RAG)介绍 5、PG向量数据库+通义千问大模型实现AI机器人 目前主流的关系型…

ABAP excel上传时,数字带文本逗号 转ABAP数量QUAN金额CURR 格式

主要使用 函数MOVE_CHAR_TO_NUM 或者 UNITS_STRING_CONVERT 第二个需要限制客户SU3 参数配置X 或者函数入参默认X, excel导出默认时X格式, 样例参考代码*&---------------------------------------------------------------------* *& Report YWWZ_TEST57 *&…

11 个必备 Docker 工具

​ 1. LazyDocker命令行下的 Docker 管理利器LazyDocker 是一个为命令行用户设计的友好型终端工具,用于管理 Docker 容器、镜像和存储卷。它适合那些习惯于命令行操作但又希望拥有直观界面的用户。 通过 LazyDocker,你可以一站式查看容器的状态、资源消耗、日志等详细信息,并…

大语言模型提示技巧(三)-迭代式提示

大语言模型还没有达到能够准确猜测人类意图的程度,此时它不能立即反馈出令人满意的答复,我们需要做的是对大语言模型进行迭代式提示,反复推进,直至大语言模型给出了令人满意的答案。我们与大语言模型交互时,往往给出的提示过于简略,而大语言模型还没有达到能够准确猜测你…

spring 中 Bean 的生命周期

spring 中 Bean 的生命周期是怎样的?原文 连环18问 https://mp.weixin.qq.com/s/liWn2Dn91cmuiqHSxVO_fASpringBean 生命周期大致分为4个阶段:1.「实例化」,实例化该 Bean 对象2.「填充属性」,给该 Bean 赋值3.「初始化」如果实现了 Aware 接口,会通过其接口获取容器资源如…

一步一步构建RAG智能问答系统

一步一步基于LangChain构建智能问答系统(Construct intelligent question answering system based on LangChain)虽然LLM(大语言模型)非常强大,但它们对于它们未经训练的信息一无所知。如果想使用LLM来回答它未经训练的文档相关问题,我们需要向其提供这些文档的信息。最常…

VSCode开发uni-app环境搭建

为什么选择VS Code?1, HbuilderX对TS类型支持暂不完善2, 前端程序员最熟悉的编辑器3, 支持各种AI插件(比如国内的阿里云通义灵码、百度comate、豆包MarsCode等,国外的也有很多)。安装uni-aap插件(快速创建页面、uni-app代码提示、鼠标悬停查看文档)1, uni-create-vie…

函子

函子在C#中,函数式编程的函子(Functor)是一种实现特定接口或模式的结构,它能够将函数应用于数据结构中的值。函子的核心概念源自数学中的范畴理论,但在编程中更倾向于实际操作。 函子的特点包装一个值:函子是一个容器,能够存储某种类型的值。 提供一个方法来应用函数:它…