Linux 实例中为MySQL创建应用一致性快照最佳实践

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS AI 助手,专业版
简介: Linux 实例中的MySQL在快照生成的某一时刻,应用一致性快照确保虚拟机内部正在进行的文件系统的写入IO、系统缓存及数据库事务完成提交。在系统恢复时刻具有更快的启动速度及更低的恢复时间RTO。

通过应用一致性快照回退云盘,数据不会损坏和丢失,可以避免数据库启动时日志回滚,确保应用(例如MySQL)处于一致性的启动状态。本文以MySQL数据库为例,介绍如何创建Linux实例的应用一致性快照,并验证应用一致性快照的数据备份效果。

前提条件

  • ECS实例的操作系统属于CentOS 7.6及以上版本、Ubuntu 18.04及以上版本或Alibaba Cloud Linux 2.1903 LTS 64位。
  • ECS实例中云盘必须是ESSD类型云盘,且文件系统为EXT3、EXT4、XFS或NTFS。同时,不支持网络文件系统和共享文件系统。
  • ECS实例已安装云助手客户端。具体操作,请参见安装云助手客户端
    说明 2017年12月01日之后使用公共镜像创建的ECS实例,已默认预装云助手客户端。

背景信息

关于应用一致性快照概念介绍,请参见通过控制台创建应用一致性快照

本文使用的验证环境信息如下所示。

环境 说明
ECS实例规格 ecs.g7.large
操作系统 CentOS 7.9 64位
云盘 ESSD云盘
应用 MySQL 5.7

说明 关于如何安装部署MySQL,请参见手动部署MySQL数据库(CentOS 7)

操作流程

  1. 步骤一:准备数据库验证环境
  2. 步骤二:创建应用冻结脚本和应用解冻脚本
  3. 步骤三:为ECS实例授予RAM角色
  4. 步骤四:在数据库中调用存储过程(TestPIT)
  5. 步骤五:通过控制台创建应用一致性快照
  6. 步骤六:验证是否成功创建应用一致性快照。
  7. 步骤七:验证通过应用一致性快照恢复数据的效果

步骤一:准备数据库验证环境

在操作之前,您已经安装好MySQL 5.7环境,此操作介绍如何准备数据库验证环境。

  1. 远程连接ECS实例。具体操作,请参见连接方式概述
  2. 创建测试脚本(/root/test.sql)。
  1. 创建并打开测试脚本(/root/test.sql)。
vi /root/test.sql
  1. 输入i,进入编辑模式。
  2. 编写验证的SQL脚本。SQL脚本中内容包含创建数据库表(PointInTime)及验证存储过程(TestPIT),具体内容如下所示。
USE AdventureWorks;
CREATE TABLE PointInTime(id int, t datetime);
DELIMITER $$
CREATE PROCEDURE `TestPIT`()
BEGIN
DECLARE i int;
SET i=1;
WHILE i < 180
DO
INSERT INTO PointInTime VALUES(i, now());
SELECT SLEEP(1);
SET i=i+1;
END WHILE;
END $$
DELIMITER ;
  1. Esc键,并输入:wq,按回车键,退出并保存内容。
  1. 登录MySQL数据库。输入以下命令,按回车键,并根据界面提示输入MySQL密码。
mysql -u <mysqlUserName> -p
  1. 其中<mysqlUserName>为您的MySQL用户名。
  2. 创建新的数据库AdventureWorks。
CREATE DATABASE AdventureWorks;
  1. 执行测试脚本。
source /root/test.sql

步骤二:创建应用冻结脚本和应用解冻脚本

此操作介绍如何为MySQL创建应用冻结脚本和应用解冻脚本,在创建应用一致性快照时需要使用到这两个脚本。

说明 本文中使用的应用冻结脚本和应用解冻脚本,脚本内容仅为验证示例使用。如果您需要为自己的业务应用创建应用一致性快照,需要根据业务场景编写对应的应用冻结脚本和应用解冻脚本。

  1. 创建应用冻结脚本(/tmp/prescript.sh)。
  1. 使用root用户创建/tmp/prescript.sh
vi /tmp/prescript.sh
  1. 输入i,进入编辑模式。
  2. 在脚本中根据应用自定义脚本内容。本文中使用以下脚本内容:
TIMESTAMP=`date +%s`
MYSQL_TEMP_FILE_NAME="/tmp/mysqlfreeze${TIMESTAMP}.tmp"
LOG_FILE_NAME="/tmp/mysqlfreeze${TIMESTAMP}.log"
# 设置您的MySQL用户名
export MYSQL_USER="$MYSQL_USER"
# 设置您的MySQL密码
export MYSQL_PWD="$MYSQL_PASSWORD"
function Log()
{
    echo "$1" 
    echo "$1" >> ${LOG_FILE_NAME}
}
function ExitWithResult()
{
    Log "[INFO]:mysql freeze result is $1."
    exit $1
}
function Main()
{
    Log "*********************************************************************"
    Log "[INFO]:Begin to freeze mysql."
    which mysql
    if [ $? -ne 0 ]
    then
        Log "[INFO]:mysql is not installed."
        ExitWithResult 0
    fi  
    systemctl status mysqld.service | grep "inactive (dead)"
    if [ $? -ne 1 ]
    then
        Log "[ERROR]:mysql is not running."
        ExitWithResult 0
    fi  
    mysql -u$MYSQL_USER  -e "show processlist;" > "${MYSQL_TEMP_FILE_NAME}" 2>&1
    if [ $? -ne 0 ]
    then
        cat ${MYSQL_TEMP_FILE_NAME} >>"${LOG_FILE_NAME}"
        [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
        Log "[ERROR]:Show process list failed."
        ExitWithResult 1
    fi
    process_id=`cat ${MYSQL_TEMP_FILE_NAME} | grep "select 1 and sleep(25)" | awk -F " " '{print $1}'`
    if [ "$process_id" != "" ]
    then
        cat ${MYSQL_TEMP_FILE_NAME} >>"${LOG_FILE_NAME}"
        [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
        Log "[ERROR]:MySQL already been freezed "
        ExitWithResult 1
    fi
    cat ${MYSQL_TEMP_FILE_NAME}
    Log "[INFO]:Try to execute flush tables command"
       echo "flush tables with read lock;select 1 and sleep(25);" | nohup mysql -u$MYSQL_USER   >> "${LOG_FILE_NAME}" 2>&1 &
    if [ $? -ne 0 ]
    then
        Log "[ERROR]:Freeze mysql failed."
        ExitWithResult 1
    fi  
    Log "[INFO]:Flush tables command execute success"
    checkTime=0
    while [ 1 ]
    do
        mysql -u$MYSQL_USER -e "show processlist;" > "${MYSQL_TEMP_FILE_NAME}" 2>&1
        if [ $? -ne 0 ]
        then
            cat ${MYSQL_TEMP_FILE_NAME} >>"${LOG_FILE_NAME}"
            [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
            Log "[ERROR]:Show process list failed."
            ExitWithResult 1
        fi
        cat ${MYSQL_TEMP_FILE_NAME}
        process_id=`cat ${MYSQL_TEMP_FILE_NAME} | grep "select 1 and sleep(25)" | awk -F " " '{print $1}'`
        if [ "$process_id" = "" ]
        then
            checkTime=`expr $checkTime + 1`
            Log "[INFO]:Mysql is not freeze. checkTime is ${checkTime}"
            sleep 1
        else
            Log "[INFO]:Found sleep command in processlist,freeze success"
            break
        fi
           if [ $checkTime -eq 10 ]
        then
            cat "${MYSQL_TEMP_FILE_NAME}" >>"${LOG_FILE_NAME}" 2>&1
            freeze_id=`cat ${MYSQL_TEMP_FILE_NAME} | grep "flush tables with read lock" | awk -F " " '{print $1}'`            
            mysql -u$MYSQL_USER -e "kill $freeze_id;" >> "${LOG_FILE_NAME}" 2>&1
            if [ $? -ne 0 ]
            then
                Log "[ERROR]:Thaw mysql failed."
            fi    
            [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
            Log "[ERROR]:Mysql is not freeze. Will return error"
            ExitWithResult 1
        fi
    done
       [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
    Log "[INFO]:Finish freeze mysql."
    ExitWithResult 0
}
Main
  1. 在脚本中,您需要修改以下参数信息:
  • $MYSQL_USER:修改为MySQL用户名。
  • $MYSQL_PASSWORD:修改为MySQL密码。
  1. Esc键,并输入:wq,按回车键,退出并保存内容。
  2. 为脚本设置仅root用户读、写和执行权限。
    说明 为了保证脚本的执行安全,请确保脚本仅root用户具有读、写及执行权限,即权限为700,否则执行脚本时会判断失败。
chmod 700 /tmp/prescript.sh
  1. 创建应用解冻脚本(/tmp/postscript.sh)。
  1. 使用root用户创建/tmp/postscript.sh
vi /tmp/postscript.sh
  1. 输入i,进入编辑模式。
  2. 在脚本中根据应用自定义脚本内容。本文中使用以下脚本内容:
TIMESTAMP=`date +%s`
MYSQL_TEMP_FILE_NAME="/tmp/mysqlthaw${TIMESTAMP}.tmp"
LOG_FILE_NAME="/tmp/mysqlthaw${TIMESTAMP}.log"
# 设置您的MySQL用户名
export MYSQL_USER="$MYSQL_USER"
# 设置您的MySQL密码
export MYSQL_PWD="$MYSQL_PASSWORD"
function Log()
{
    echo "$1" 
    echo "$1" >> ${LOG_FILE_NAME}
}
function ExitWithResult()
{
    Log "[INFO]:mysql unfreeze result is $1."
    exit $1
}
function Main()
{
    Log "*********************************************************************"
    Log "[INFO]:Begin to thaw mysql."   
    which mysql
    if [ $? -ne 0 ]
    then
        Log "[INFO]:mysql is not installed."
        ExitWithResult 0
    fi  
    systemctl status mysqld.service | grep "inactive (dead)"
    if [ $? -ne 1 ]
    then
        Log "[ERROR]:mysql is not running."
        ExitWithResult 0
    fi  
    mysql -u$MYSQL_USER  -e "show processlist;" > "${MYSQL_TEMP_FILE_NAME}" 2>&1
    if [ $? -ne 0 ]
    then
        cat ${MYSQL_TEMP_FILE_NAME} >>"${LOG_FILE_NAME}"
        [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
        Log "[ERROR]:show process list failed."
        ExitWithResult 1
    fi
    Log "[INFO]:show process list success."
    cat ${MYSQL_TEMP_FILE_NAME}
    process_ids=`cat ${MYSQL_TEMP_FILE_NAME} | grep "select 1 and sleep(25)" | awk -F " " '{print $1}'`
    if [ "$process_ids" = "" ]
    then
        [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
        Log "[ERROR]:Get freeze process_id failed."
        ExitWithResult 1
    fi
    cat ${MYSQL_TEMP_FILE_NAME} | grep "select 1 and sleep(25)" | awk -F " " '{print $1}'| while read pid
    do
        Log "[INFO]:Try to stop sql process ${pid}."
        mysql -u$MYSQL_USER  -e "kill $pid;" >> "${LOG_FILE_NAME}" 2>&1
        if [ $? -ne 0 ]
        then
            [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
            Log "[ERROR]:Thaw mysql failed.PIDs is ${process_ids}"
            ExitWithResult 1
        fi   
        Log "[INFO]:Stop sql process ${pid} success."
    done 
    [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
    Log "[INFO]:Finish thaw mysql."
    ExitWithResult 0
}
Main
  1. 在脚本中,您需要修改以下参数信息:
  • $MYSQL_USER:修改为MySQL用户名。
  • $MYSQL_PASSWORD:修改为MySQL密码。
  1. Esc键,并输入:wq,按回车键,退出并保存内容。
  2. 为脚本设置仅root用户读、写和执行权限。
    说明 为了保证脚本的执行安全,请确保脚本仅root用户具有读、写及执行权限,权限为700,否则执行脚本时会判断失败。
chmod 700 /tmp/postscript.sh

进入/tmp目录查看脚本权限是否正确。进入/tmp目录:

cd /tmp

查看脚本权限信息:

ls -l

结果如下所示。

image.png

步骤三:为ECS实例授予RAM角色

开启应用一致性快照前,必须先为ECS实例配置相关的RAM角色。

  1. 使用阿里云账号登录RAM控制台
  2. 创建应用一致性快照相关的RAM角色。具体操作,请参见创建可信实体为阿里云服务的RAM角色示例为创建一个AppSnapshotRoleName的RAM角色。

image.png

  1. 创建应用一致性快照相关权限策略。具体操作,请参见创建自定义策略

image.png

创建一个AppSnapshotPolicy权限策略,具有查询快照相关信息、创建快照、设置标签和查询云盘信息等相关权限。您可以直接使用以下策略内容。

{
    "Version": "1",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecs:DescribeSnapshot*",
                "ecs:CreateSnapshot*",
                "ecs:TagResources",
                "ecs:DescribeDisks"
            ],
            "Resource": [
                "*"
            ],
            "Condition": {}
        }
    ]
}
  1. 为RAM角色(AppSnapshotRoleName)设置自定义权限(AppSnapshotPolicy)。具体操作,请参见为RAM角色授权

image.png

  1. 为目标实例设置RAM角色(AppSnapshotRoleName)。具体操作,请参见授予实例RAM角色

image.png

步骤四:在数据库中调用存储过程(TestPIT)

此操作为创建快照前调用存储过程,方便后续操作时查看应用冻结效果和回滚数据后效果。

  1. 登录MySQL数据库。输入以下命令,按回车键,并根据界面提示输入MySQL密码。
mysql -u <mysqlUserName> -p
  1. 其中<mysqlUserName>为您的MySQL用户名。
  2. 切换到AdventureWorks数据库。
USE AdventureWorks;
  1. 调用存储过程(TestPIT)。
CALL TestPIT;

  1. 说明 在验证过程中,您需要在TestPIT运行完成前(大概3分钟左右)创建应用一致性快照,否则不好验证应用一致性快照的效果。

步骤五:通过控制台创建应用一致性快照

此操作介绍如何在控制台为MySQL数据库所在的Linux实例创建应用一致性快照。

  1. 进入ECS实例列表页面。
  1. 登录ECS管理控制台
  2. 在左侧导航栏,选择实例与镜像 > 实例
  3. 在顶部菜单栏处,选择目标ECS实例所在地域。
  1. 找到目标实例,在操作列中选择更多 > 云盘和镜像 > 创建实例快照
  2. 创建实例快照对话框中,设置实例快照参数并启用快照极速可用功能。
  1. 创建实例快照对话框中,设置应用一致性快照。选中启用应用一致性快照,并设置应用冻结脚本和应用解冻脚本的路径信息。脚本路径信息需要和前面步骤创建的脚本路径一致。具体脚本信息,请参见步骤二:创建应用冻结脚本和应用解冻脚本

image.png

  1. 单击确定创建后会返回云助手命令ID和命令执行ID,您可以根据命令执行ID查看创建结果。

image.png

步骤六:验证是否成功创建应用一致性快照。

此操作介绍如何在ECS管理控制台查看应用一致性快照创建结果,并在数据库中查看数据暂停提交的效果。

  1. 云助手页面,查看命令执行结果。
  1. 登录ECS管理控制台
  2. 在左侧导航栏,选择运维与监控 > 发送命令/文件(云助手)
  3. 单击命令执行结果页签。
  4. 单击目标命令执行ID,查看执行结果。

image.png

如上图所示,ExitCode返回值为0,表示云助手上创建应用一致性快照执行成功,此时回显信息中显示创建应用一致性快照和实例快照ID。

说明 如果ExitCode返回值不为0,请根据ExitCode错误码信息排查相关问题。更多信息,请参见错误码信息

  1. 在云助手的返回信息中,查看应用冻结时间。在返回信息中,找到应用冻结脚本开始时间和应用解冻脚本完成时间。
  • 应用冻结脚本开始执行时间为2021-08-03 18:58:41

image.png

  • 应用解冻脚本结束执行时间为2021-08-03 18:58:44

image.png

  1. 快照页面查看实例快照和云盘快照信息。
  1. 在左侧导航栏,选择存储与快照 > 快照
  2. 单击实例快照页签,查看已创建的实例快照。
  3. 单击云盘快照页签,根据快照的标签信息,检查是否成功创建应用一致性快照。示例中云盘快照的标签显示APPConsistent:True,表示创建的是应用一致性快照。

image.png

  1. 连接MySQL数据库,查看数据暂停提交时间。
  1. 远程连接ECS实例。
  2. 登录MySQL数据库。输入以下命令,按回车键,并根据界面提示输入MySQL密码。
mysql -u <mysqlUserName> -p
  1. 其中<mysqlUserName>为您的MySQL用户名。
  2. 查询数据库表PointInTime的内容。
SELECT * FROM PointInTime;
  1. 查询结果如下所示,在应用冻结脚本和应用解冻脚本执行过程中,数据库写入暂停提交。

image.png

步骤七:验证通过应用一致性快照恢复数据的效果

通过应用一致性快照恢复数据后,检查MySQL数据最后写入时间是在应用冻结脚本执行前,因此可以判断应用一致性快照的数据恢复有效果。

  1. 在ECS管理控制台,通过上面创建的实例快照回滚ECS实例。具体操作,请参见通过实例快照回滚云盘
  2. 登录MySQL并查询数据库表PointInTime的内容。
  1. 远程连接ECS实例。
  2. 登录MySQL数据库。输入以下命令,按回车键,并根据界面提示输入MySQL密码。
mysql -u <mysqlUserName> -p
  1. 其中<mysqlUserName>为您的MySQL用户名。
  2. 查询数据库表PointInTime的内容。
SELECT * FROM PointInTime;
  1. 查询结果如下所示。

image.png

数据库冻结成功之前会停止插入数据。使用应用一致性的实例快照恢复数据后,最后一条数据对应的时间为2021-08-03 18:58:40,早于步骤五中查询的冻结时间点2021-08-03 18:58:41。因此证明关于MySQL的应用一致性快照备份的结果是正确的。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
8月前
|
关系型数据库 MySQL 分布式数据库
安全可靠的PolarDB V2.0 (兼容MySQL)产品能力及应用场景
PolarDB分布式轻量版采用软件输出方式,能够部署在您的自主环境中。PolarDB分布式轻量版保留并承载了云原生数据库PolarDB分布式版技术团队深厚的内核优化成果,在保持高性能的同时,显著降低成本。
690 140
|
5月前
|
缓存 NoSQL 关系型数据库
MySQL 与 Redis 如何保证双写一致性?
我是小假 期待与你的下一次相遇 ~
617 7
|
6月前
|
SQL 监控 关系型数据库
MySQL事务处理:ACID特性与实战应用
本文深入解析了MySQL事务处理机制及ACID特性,通过银行转账、批量操作等实际案例展示了事务的应用技巧,并提供了性能优化方案。内容涵盖事务操作、一致性保障、并发控制、持久性机制、分布式事务及最佳实践,助力开发者构建高可靠数据库系统。
|
7月前
|
存储 关系型数据库 MySQL
MYSQL数据加密压缩函数应用实战指南。
总的来说,加密和压缩是维护MySQL数据库中数据安全性和效率的有效手段。使用时需权衡性能与安全,合理应用加密和压缩函数。在设计数据库架构时要考虑到加密字段的查询性能,因为加密可能使得一些索引失效。压缩数据能有效减少存储空间的占用,但在服务器负载较高时应避免实时压缩和解压,以免影响总体性能。
229 10
|
8月前
|
安全 应用服务中间件 网络安全
在Linux环境部署Flask应用并启用SSL/TLS安全协议
至此,你的Flask应用应该能够通过安全的HTTPS协议提供服务了。记得定期更新SSL证书,Certbot可以帮你自动更新证书。可以设定cronjob以实现这一点。
576 10
|
8月前
|
Java Linux 网络安全
Linux云端服务器上部署Spring Boot应用的教程。
此流程涉及Linux命令行操作、系统服务管理及网络安全知识,需要管理员权限以进行配置和服务管理。务必在一个测试环境中验证所有步骤,确保一切配置正确无误后,再将应用部署到生产环境中。也可以使用如Ansible、Chef等配置管理工具来自动化部署过程,提升效率和可靠性。
794 13
|
10月前
|
Java 关系型数据库 MySQL
在Linux平台上进行JDK、Tomcat、MySQL的安装并部署后端项目
现在,你可以通过访问http://Your_IP:Tomcat_Port/Your_Project访问你的项目了。如果一切顺利,你将看到那绚烂的胜利之光照耀在你的项目之上!
504 41
|
7月前
|
存储 数据采集 监控
ubuntu(linux)系统主要应用于哪些工业场景中?研维三防ubuntu系统的手持工业三防平板电脑在哪些行业中有实际应用
Ubuntu 系统凭借其独特的优势,在众多工业场景中得到了广泛应用,为工业数字化、智能化发展提供了有力支持。而研维三防基于 Ubuntu 定制系统的手持工业三防平板电脑,更是将 Ubuntu 系统的优势与工业级的性能、坚固耐用性完美结合,在电力、物流、制造等多个行业中展现出强大的应用价值,助力企业提高生产效率、优化管理流程、提升产品质量,成为推动工业现代化发展的重要力量。随着技术的不断进步与创新,相信 Ubuntu 系统以及研维三防这类工业级设备将在更多的工业领域中发挥更大的作用,为工业发展带来更多的机遇与变革。
|
10月前
|
开发框架 Java 关系型数据库
在Linux系统中安装JDK、Tomcat、MySQL以及部署J2EE后端接口
校验时,浏览器输入:http://[your_server_IP]:8080/myapp。如果你看到你的应用的欢迎页面,恭喜你,一切都已就绪。
633 17
|
10月前
|
Java 关系型数据库 MySQL
在Linux操作系统上设置JDK、Tomcat、MySQL以及J2EE后端接口的部署步骤
让我们总结一下,给你的Linux操作系统装备上最强的军队,需要先后装备好JDK的弓箭,布置好Tomcat的阵地,再把MySQL的物资原料准备好,最后部署好J2EE攻城车,那就准备好进军吧,你的Linux军团,无人可挡!
304 18