• Docker Swarm 线上环境 MariaDB XA 悬停事务故障排查


    场景:Docker Swarm 集群,MariaDB 10.4 服务异常重启,启动失败;数据库日志发现残留 XA Prepared 事务,常规重启无法自动恢复,业务无法连接数据库。 环境:Docker Swarm + MariaDB 10.4,业务使用XA分布式事务。

    一、故障现象

    1. MariaDB service 在 Swarm 集群反复重启,容器不断 crash,业务无法访问数据库;

    2. 查看容器日志,数据库启动阶段卡在事务恢复流程,无法完成启动;

    3. 多次重启 Swarm service 无效,数据卷 PVC(Swarm volume)数据保留完好,不能直接删除 volume。

      mysql容易的异常日志:

    image

    二、排障思路(完整定位过程)

    核心原则:不直接在故障业务容器内操作数据,防止数据损坏;使用同版本临时容器挂载原数据卷做离线修复

    1. 查看 Swarm service 容器日志,初步判断是数据库内部事务恢复问题,不是 Swarm 网络、端口或资源限制问题;
    2. 进入故障容器查看 mysqld 内核日志,发现关键日志:Found prepared XA transactions,确认存在XA悬停事务;

    ​ 直接进容器看到的异常日志,一直不能明确定位到具体原因。排查服务器磁盘空间都是够用的。

    容器内手动前台启动 mysqld(最关键,直接打印崩溃原因)

    # 容器内执行
    mysqld --datadir=/config/databases
    

    image

    1. 原理回顾:XA 两阶段事务,prepare 成功之后,协调器宕机/网络中断,没有收到 commit/rollback。数据库重启时会尝试自动处理;协调器永久丢失时,自动恢复失败,数据库无法启动;而且容器内的mysql进程无法杀除并重启,因为mysql的容器镜像中加了mysqld-safe的异常重启服务。

    2. 方案:新建临时容器,挂载原有 MariaDB 数据 volume,手动启动 mysqld,完成XA事务检查与清理;

    4.1 踩坑:临时容器缺少 /var/run/mysqld 目录,mysqld 默认把 sock、pid 文件写入该路径,导致启动失败;修改启动参数,将 sock/pid 文件放到 /tmp 目录解决;

    docker run --rm -it \
    --entrypoint bash \
    -v /root/controller_deployer/data/mysql:/config \
    -e PUID=0 -e PGID=0 \
    registry.tethrnet.com:5000/mariadb:version-110.4.15mariabionic
    
    

    --entrypoint bash 是关键!

    • 不再执行镜像默认的 mariadb 启动脚本
    • 容器启动直接进入 bash,不会自动启动 mysqld_safe

    4.2 数据库成功拉起后,登录验证XA事务;MariaDB 10.4 没有 information_schema.innodb_prepared_transactions 系统表,使用 XA RECOVER; 命令检查;

    临时容器内执行恢复命令

    mysqld --datadir=/config/databases --tc-heuristic-recover=ROLLBACK
    

    此时前台启动,执行 XA 事务恢复。

    • 看到 ready for connections 就代表恢复成功。
    • 保持这个终端,新开一个临时容器终端进去验证 XA 事务。

    4.3 确认XA残留事务清理完成,优雅关闭临时数据库,重新启动 Swarm 的 MariaDB 业务服务,故障恢复。

    执行查询,确认 XA 事务:

    SELECT * FROM information_schema.innodb_prepared_transactions;
    

    重要提醒

    • 以后绝对不要再带 --tc-heuristic-recover 参数启动,这个参数是一次性修复参数;重复带参数启动会直接 abort。
    • 启动业务容器前,留意宿主机数据目录权限,避免再次出现 Permission denied。

    三、完整操作步骤

    3.1 备份数据卷(操作前必做)

    修复前先备份 volume,防止误操作丢失数据

    # 将你的mariadb数据卷做备份,替换 volume 名称
    docker run --rm -v mariadb-data:/source -v /host/backup:/dest alpine cp -r /source /dest
    

    3.2 启动临时容器挂载原数据卷

    使用和业务完全一致的 MariaDB 版本,保证数据文件兼容

    docker run -it --rm \
    -v mariadb-data:/config/databases \
    --entrypoint bash mariadb:10.4.15
    

    进入容器后,/config/databases 就是原数据库的数据目录。

    3.3 启动 mysqld,指定参数规避 sock/pid 目录缺失问题

    mysqld --datadir=/config/databases \
    --skip-networking=0 \
    --socket=/tmp/mysqld.sock \
    --pid-file=/tmp/mysqld.pid
    

    等待日志输出 ready for connections,代表数据库内核成功启动。

    注意:这个终端保持不动,mysqld 在此前台运行。

    3.4 新开宿主机终端,进入临时容器登录数据库

    # 查看临时容器ID,替换为你的容器ID
    docker exec -it 982c15977c7a bash
    # 使用自定义sock文件登录
    mysql -uroot -S /tmp/mysqld.sock
    

    3.5 检查XA事务(重点踩坑点)

    ❌ 错误命令(MySQL8专属,MariaDB 10.4不存在这张表)

    select * from information_schema.innodb_prepared_transactions;
    

    ✅ MariaDB 正确查看XA pending事务命令

    XA RECOVER;
    
    • 返回空结果:✅ 残留XA事务已经处理完成;
    • 如有返回记录:可以手动执行 XA ROLLBACK 'gid'; 逐个回滚。

    3.6 验证库表可用性

    show databases;
    

    确认业务库都正常加载,表可以正常访问。

    3.7 关闭临时库,恢复业务服务

    1. 在 mysqld 运行窗口按 Ctrl+C,优雅关闭数据库进程;
    2. 退出临时容器,容器会自动销毁;
    3. 回到 Docker Swarm,重启 mariadb service:
    docker service update --force mariadb-service
    
    1. 观察容器状态,容器正常启动不再反复crash,业务连接恢复。

    四、原理分析

    XA分布式事务分为2PC:

    1. Prepare:各资源节点持久化事务,返回成功;
    2. Commit:事务协调器通知所有节点提交。

    故障场景:业务XA事务执行到prepare成功,协调器节点崩溃/网络断开,没有下发commit/rollback指令。 数据库重启时,InnoDB引擎会扫描所有prepared状态XA事务,等待协调器指令。协调器永久丢失时,数据库无法自动完成事务处理,数据库启动阻塞。

    ⚠️ 重要提醒:启发式回滚属于应急修复手段。修复完成后,业务侧需要核对相关业务数据,校验数据一致性。

    五、本次故障踩坑清单

    1. 混淆 MySQL8 和 MariaDB 的系统表,MariaDB 10.4 没有 innodb_prepared_transactions,查询会报表不存在;
    2. 临时容器环境缺少 /var/run/mysqld 目录,mysqld 启动时创建pid、socket文件失败,数据库内核已经加载完成但服务退出;
    3. 不要直接在业务Swarm容器内直接修改、启动mysqld,容易引发数据损坏;优先临时容器挂载volume离线修复;
    4. Docker Swarm 服务会自动重启崩溃容器,反复重启会加剧事务恢复异常,故障期间建议先缩容副本为0,避免持续损坏数据。

    六、预防方案

    1. XA事务协调器做好状态持久化,记录每个XA事务全局ID和状态,协调器重启后可以继续处理残留事务;
    2. 增加监控:定时执行 XA RECOVER;,一旦检测到pending事务,触发告警,尽早发现;
    3. Swarm中数据库服务配置合理的重启策略,故障时不要无限快速重启,避免放大故障;
    4. 定期备份volume,数据库数据卷损坏时可以快速回滚;
  • 相关阅读:
    Metabase学习教程:提问-1
    快速排序 sort
    整理下最近用canvas遇到的问题吧
    【PCA降维】在人脸识别中的应用
    【分治算法】【Python实现】二分搜索
    java 生成 pdf,支持中文显示
    如何编写lua扩展库
    FDA食品级认证是什么?
    使用Pytorch手写ViT — VisionTransformer
    点云从入门到精通技术详解100篇-三维文物点云去噪与精简方法研究与应用(中)
  • 原文地址:https://www.cnblogs.com/zjdxr-up/p/23049231