导读:经常会有开发者咨询开源PolarDB-X部署相关问题。我们让AI全自动部署了一遍,看看在部署过程中有哪些容易被忽略的问题。如果你正准备部署PolarDB-X,这篇文章至少能帮你省下2小时排障时间。

PolarDB-X简介

PolarDB分布式版(简称PolarDB-X)是阿里云自主研发的云原生集中式和分布式一体化数据库产品,整体采用了基于存储计算分离的Shared-Nothing系统架构,支持水平扩展、分布式事务、混合负载等能力,具备金融级高可用、高吞吐、大存储、低延时、易扩展、高度兼容 MySQL 系统及生态等特点。

而PolarDB-X标准版,基于集中分布式一体化的架构,将分布式中的存储节点(DN)多副本单独提供服务,提供100%兼容MySQL的语法和功能,兼容MySQL5.7、8.0等多个版本。同时,标准版相对于原生MySQL进行了多方位的功能和性能的增强,基于分布式的技术丰富了高可用、性能提升等。

PolarDB-X标准版,采用分层架构:

日志层:采用Paxos的多数派复制协议,基于Paxos consensus协议日志完全兼容MySQL Binlog格式。相比于开源MySQL主备复制协议(基于Binlog的异步或半同步),PolarDB-X标准版可以金融级容灾能力,满足机房级故障时,不丢任何数据(RPO=0)。

存储层:自研Lizard事务系统,对接日志层,可以替换传统MySQL InnoDB的单机事务系统,分别设计了SCN单机事务系统和GCN分布式事务系统来解决这些弊端,可以满足集中式和分布式一体化的事务优化,同时PolarDB-X标准版基于SCN单机事务系统可以提供完全兼容MySQL的事务隔离级别。

执行层:类似于MySQL的Server层,自研xRPC Server可以对接PolarDB-X企业版的分布式查询。同时为完全兼容MySQL,也提供兼容MySQL Server的SQL执行能力,对接存储层的事务系统来提供数据操作。

本文目标:在3台阿里云ECS上,通过 RPM 包快速部署三节点HA集群,并记录AI在全自动部署过程中踩过的每一个坑。

环境配置

节点

公网IP(管理)

内网IP(集群通信)

角色

规格

Node1

120.xx.xx.211

192.168.0.20

Leader

4C8G,40G SSD

Node2

121.xx.xx.241

192.168.0.19

Follower

4C8G,40G SSD

Node3

121.xx.xx.171

192.168.0.21

Follower

4C8G,40G SSD

  • 操作系统:Alibaba Cloud Linux(兼容 CentOS 7/RHEL 7) 

  • 部署方式:RPM 一键安装 

部署流程(标准路径)

理想的部署流程应该是这样的:

# Step 1: 访问polardb开源官网(openpolardb.com/download)下载RPM包到每台机器
wget -O /tmp/polardbx-engine.rpm \
  "https://polar-db-prod.oss-cn-hangzhou.aliyuncs.com/...rpm"

# Step 2: 安装RPM
yum install -y /tmp/polardbx-engine.rpm

# Step 3: 创建运行用户和数据目录
useradd -s /sbin/nologin -M polarx
mkdir -p /data/polardbx/data /data/polardbx/tmp
chown -R polarx:polarx /data/polardbx

# Step 4: 生成 my.cnf(每台机器不同)
# 见下文"细节四"

# Step 5: 初始化数据目录(一次性)
mysqld --defaults-file=/data/polardbx/my.cnf \
  --initialize-insecure \
  --cluster-info="192.168.0.20:3201;192.168.0.19:3201;192.168.0.21:3201@1"

# Step 6: 启动服务(持久运行)
mysqld_safe --defaults-file=/data/polardbx/my.cnf --daemonize

# Step 7: 验证集群状态
mysql -uroot -h127.0.0.1 -P3306 -e "SELECT * FROM INFORMATION_SCHEMA.ALISQL_CLUSTER_GLOBAL;"

但实际上,AI在执行这个流程时,也忽略了多个细节。

容易被忽略的细节

细节一:公网IP互不通——安全组的隐形墙

错误场景:三台机器之间使用公网IP配置 cluster-info,启动后集群始终无法建立共识。查询 ALISQL_CLUSTER_GLOBAL 返回空集。

排查命令:

# Node1 上测试连通性
ping 121.xx.xx.241      # ❌ 100% packet loss
nc -zv 121.xx.xx.241 3201  # ❌ Connection timed out

ping 192.168.0.19        # ✅ 0.1ms
nc -zv 192.168.0.19 3201    # ✅ Connected

根本原因:阿里云ECS的公网IP之间默认不互通(安全组限制),但同VPC的内网IP完全互通。

错误配置:

# ❌ 错误:使用公网IP
--cluster-info="120.55.84.211:3201;121.43.233.241:3201;121.40.252.171:3201@1"

正确配置:

# ✅ 正确:使用内网IP
--cluster-info="192.168.0.20:3201;192.168.0.19:3201;192.168.0.21:3201@1"

经验教训:云环境部署三节点时,节点间通信务必使用内网IP。 公网IP仅用于外部客户端访问和管理。建议在部署前先用 ping 和 nc 验证三节点之间的网络连通性。


细节二:mysqld拒绝root启动——用户切换的细节

错误场景:安装RPM后,直接用 root 用户执行启动命令:

/opt/polardbx_engine/bin/mysqld_safe --defaults-file=/data/polardbx/my.cnf --daemonize

结果进程启动后立即退出,日志中没有任何有效错误信息。直接用 mysqld 测试时才暴露真相:

[ERROR] Fatal error: Please read "Security" section of the manual
to find out how to run mysqld as root!

根本原因:MySQL/PolarDB-X 出于安全考虑,禁止以 root 用户直接运行 mysqld。

正确做法:

# Step 1: 创建专用运行用户(所有节点执行)
useradd -s /sbin/nologin -M polarx

# Step 2: 数据目录授权(所有节点执行)
mkdir -p /data/polardbx/data /data/polardbx/tmp
chown -R polarx:polarx /data/polardbx

# Step 3: 以 polarx 用户启动(注意!坑3与此相关)
su -s /bin/bash polarx -c \
  "/opt/polardbx_engine/bin/mysqld_safe --defaults-file=/data/polardbx/my.cnf --daemonize"

经验教训:务必创建专用运行用户(如 polarx),并将数据目录权限授予该用户。 这是MySQL部署的基础要求,但在自动化脚本中很容易被忽略。


细节三:工作目录权限——su 继承的隐形陷阱

错误场景:在解决了坑2(创建polarx用户)之后,再次执行启动命令:

# 当前目录是 /root
su -s /bin/bash polarx -c \
  "/opt/polardbx_engine/bin/mysqld_safe --defaults-file=/data/polardbx/my.cnf --daemonize"

结果报错:

mysqld_safe: line 513: cd: /root: Permission denied

根本原因:su -s /bin/bash polarx -c "cmd" 会继承当前shell的工作目录。如果当前在 /root 目录下执行,mysqld_safe 内部会尝试 cd /root,而 polarx 用户没有 /root 的访问权限,导致启动失败。

正确做法:

# ✅ 先切换到 polarx 用户有权限的目录,再启动
su -s /bin/bash polarx -c \
  "cd /data/polardbx && /opt/polardbx_engine/bin/mysqld_safe --defaults-file=/data/polardbx/my.cnf --daemonize"

经验教训:使用 su 切换用户启动服务时,务必先 cd 到目标用户有权限访问的目录。 建议统一使用 /data/polardbx 作为工作目录。


细节四:--initialize-insecure 不是启动命令

错误场景:执行初始化命令后,返回码为0,但 ps aux 中看不到任何 mysqld 进程,端口也没有监听。

/opt/polardbx_engine/bin/mysqld --defaults-file=/data/polardbx/my.cnf --initialize-insecure
# 命令立即退出,echo $? = 0

排查过程:反复检查 my.cnf 配置、数据目录权限,都没有发现问题。最后才意识到——这个命令本来就是应该退出的。

根本原因:--initialize-insecure 是一个一次性数据目录初始化命令,它的作用是:

  • 创建系统表(mysql、information_schema 等)

  • 生成 root@localhost 用户(空密码)

  • 初始化 InnoDB 数据文件

完成后,进程自动退出。它不是守护进程启动命令。

正确流程:

# Step 1: 初始化(一次性,执行完自动退出)
su -s /bin/bash polarx -c \
  "/opt/polardbx_engine/bin/mysqld --defaults-file=/data/polardbx/my.cnf --initialize-insecure --cluster-info='...'"

# Step 2: 验证初始化成功
ls -la /data/polardbx/data/  # 应该看到 ibdata1、mysql 目录等29+个文件

# Step 3: 启动持久服务(mysqld_safe才是守护进程)
su -s /bin/bash polarx -c \
  "cd /data/polardbx && /opt/polardbx_engine/bin/mysqld_safe --defaults-file=/data/polardbx/my.cnf --daemonize"

# Step 4: 验证进程
ps aux | grep mysqld  # 应该看到 mysqld 进程
ss -tlnp | grep 3306  # 应该看到 3306 端口监听

经验教训:--initialize-insecure 和 mysqld_safe --daemonize 是两个独立的步骤。 初始化完成后,必须单独执行启动命令才能建立持久服务。很多开发者误以为初始化命令会同时启动服务。


细节五:缺失 libncurses.so.5——RPM安装的隐形依赖

错误场景:集群启动成功,进程和端口都正常。但尝试用 mysql 客户端连接时:

/opt/polardbx_engine/bin/mysql -uroot -h127.0.0.1 -P3306
# 报错:error while loading shared libraries: libncurses.so.5: cannot open shared object file

根本原因:RPM包是在 CentOS 7 / Alibaba Cloud Linux 环境下编译的,依赖 libncurses.so.5。但现代系统默认安装的是 ncurses 6.x,只提供 libncurses.so.6,缺少兼容版本的 .so.5

解决方案:

# CentOS / RHEL / Alibaba Cloud Linux
yum install -y ncurses-compat-libs

# 验证
ls -la /lib64/libncurses.so.5  # 应该存在

经验教训:RPM安装后,务必检查动态库依赖。 可以通过 ldd /opt/polardbx_engine/bin/mysql | grep "not found" 快速检查缺失的库。


细节六:cluster-info 中的分号截断远程命令

错误场景:通过SSH远程执行初始化命令时,因为 cluster-info 包含分号 ;,导致命令被shell截断:

# 预期执行的命令:
mysqld --initialize-insecure --cluster-info='ip1:3201;ip2:3201;ip3:3201@1'

# 实际执行结果(分号被当作命令分隔符):
mysqld --initialize-insecure --cluster-info='ip1:3201
# ip2:3201 被当作新命令执行,报错:command not found

根本原因:在通过SSH或脚本传递包含特殊字符(分号、引号、美元符号等)的命令时,多层shell的引号解析会导致命令被意外截断或变形。

解决方案——base64编码传递:

# 本地生成初始化脚本
cat > init.sh << 'EOF'
#!/bin/bash
/opt/polardbx_engine/bin/mysqld \
  --defaults-file=/data/polardbx/my.cnf \
  --initialize-insecure \
  --cluster-info="192.168.0.20:3201;192.168.0.19:3201;192.168.0.21:3201@1"
EOF

# base64编码后通过SSH传递(避免引号解析问题)
base64_script=$(base64 -w 0 init.sh)
ssh root@192.168.0.20 \
  "echo '$base64_script' | base64 -d > /tmp/init.sh && bash /tmp/init.sh"

经验教训:远程执行包含特殊字符的命令时,使用 base64 编码传递脚本是最可靠的方案。 这完全避免了多层shell引号解析的问题。


细节七:卸载不彻底——进程残留的"幽灵文件"

错误场景:第一次部署失败后执行了标准卸载流程:

mysqladmin shutdown
rm -rf /data/polardbx
rpm -e t-polardbx-engine

看起来干净利落?重新部署时发现磁盘空间不足,但 du -sh / 只统计到18GB,而 df -h 显示已用38GB。消失的20GB去哪了?

排查命令:

# 查看被删除但仍被进程占用的文件
lsof +L1 | grep polarx

# 输出示例:
# mysqld  39258  polarx  3u  REG  253,3  12582912  /data/polardbx/data/ibdata1 (deleted)
# mysqld  39258  polarx  4u  REG  253,3  50331648  /data/polardbx/data/undo_001 (deleted)
# ... 共约20GB

根本原因:mysqld 进程被 polarx 用户启动,即使数据文件被 rm -rf 删除,只要进程还在运行,文件描述符就继续占用磁盘空间。Linux 中这叫"已删除但仍被打开的文件(deleted-but-open files)"。

正确卸载流程:

# Step 1: 优雅停止服务
mysqladmin -uroot -h127.0.0.1 -P3306 shutdown

# Step 2: 强制终止运行用户的所有残留进程
pkill -9 -u polarx

# Step 3: 验证没有残留占用
lsof +L1 | grep -E 'polardbx|mysqld'
# 如果输出为空,说明空间已释放

# Step 4: 删除数据目录和RPM
rm -rf /data/polardbx
rpm -e t-polardbx-engine

# Step 5: 删除用户(可选)
userdel polarx

# Step 6: 验证磁盘空间释放
df -h

经验教训:卸载时务必终止运行用户(polarx)的所有进程,否则 rm -rf 删掉的只是文件入口,真正的磁盘块仍被进程持有。 建议在卸载脚本中加入 lsof +L1 检查,确认没有残留的已删除文件。


完整部署命令速查表

每台机器都需要执行的命令

# ========== Step 1: 下载并安装RPM ==========
wget -O /tmp/polardbx-engine.rpm "<你的RPM下载链接>"
yum install -y /tmp/polardbx-engine.rpm

# ========== Step 2: 安装客户端依赖 ==========
yum install -y ncurses-compat-libs

# ========== Step 3: 创建用户和数据目录 ==========
useradd -s /sbin/nologin -M polarx
mkdir -p /data/polardbx/data /data/polardbx/tmp
chown -R polarx:polarx /data/polardbx

# ========== Step 4: 生成 my.cnf ==========
# 注意:每台机器的 server_id 不同(1、2、3),其他配置相同
cat > /data/polardbx/my.cnf << 'EOF'
[mysqld]
server_id = 1              # Node2改为2,Node3改为3
datadir = /data/polardbx/data
tmpdir = /data/polardbx/tmp
socket = /data/polardbx/tmp/mysql.sock
log_error = /data/polardbx/data/error.log
port = 3306

# X-Paxos 配置
cluster_id = 1
cluster_info = '192.168.0.20:3201;192.168.0.19:3201;192.168.0.21:3201@1'

# 性能配置(根据内存调整)
innodb_buffer_pool_size = 2G
max_connections = 500

# 日志配置
log_bin = /data/polardbx/data/mysql-bin
binlog_format = ROW
EOF

# ========== Step 5: 初始化数据目录(一次性) ==========
su -s /bin/bash polarx -c \
  "/opt/polardbx_engine/bin/mysqld --defaults-file=/data/polardbx/my.cnf --initialize-insecure"

# 验证初始化成功(应该有29+个文件)
ls -la /data/polardbx/data/

# ========== Step 6: 启动服务 ==========
su -s /bin/bash polarx -c \
  "cd /data/polardbx && /opt/polardbx_engine/bin/mysqld_safe --defaults-file=/data/polardbx/my.cnf --daemonize"

# 验证进程和端口
ps aux | grep mysqld
ss -tlnp | grep -E '3306|3201'

部署验证:集群状态检查

在所有节点启动后,在 Leader 节点上执行验证:

-- 1. 查看版本
SELECT VERSION();
-- 结果:8.0.32-X-Cluster-8.4.19-20250825

-- 2. 查看本地角色(Leader上执行)
SELECT * FROM INFORMATION_SCHEMA.ALISQL_CLUSTER_LOCAL;
-- 结果:ROLE=Leader, CURRENT_LEADER=192.168.0.20:3201, SERVER_READY_FOR_RW=Yes

-- 3. 查看全局拓扑(Leader上执行)
SELECT * FROM INFORMATION_SCHEMA.ALISQL_CLUSTER_GLOBAL;
-- 结果:3 rows,显示所有节点角色和匹配索引

-- 4. 查看复制健康状态
SELECT * FROM INFORMATION_SCHEMA.ALISQL_CLUSTER_HEALTH;
-- 结果:LOG_DELAY_NUM=0, APPLY_DELAY_NUM=0, APPLY_DELAY_SECONDS=0

-- 5. 写入测试
CREATE DATABASE deploy_test;
USE deploy_test;
CREATE TABLE t1 (id INT PRIMARY KEY, msg VARCHAR(100));
INSERT INTO t1 VALUES (1, 'hello from leader');

-- 6. 在 Follower 节点上验证数据同步
-- 连接到 Node2 或 Node3
SELECT * FROM deploy_test.t1;
-- 结果:(1, hello from leader) ✅

故障切换测试:关闭 Leader(Node1)的 mysqld 进程

  • 观察 Node2/Node3 的 ALISQL_CLUSTER_LOCAL,约3秒内新 Leader 产生

  • 新 Leader 可正常读写

  • 原 Leader 重启后自动作为 Follower 重新加入集群


开发者部署检查清单

在部署前对照检查,避免踩坑:

检查项

命令/方法

预期结果

节点间网络连通性

ping <内网IP>

全部通

共识端口开放

nc -zv <内网IP> 3201

全部通

磁盘空间

df -h /

剩余 ≥ 10GB

内存

free -h

可用 ≥ 4GB

运行用户

id polarx

用户存在

数据目录权限

ls -la /data/polardbx

polarx:polarx

RPM依赖

ldd /opt/polardbx_engine/bin/mysql | grep not

无输出

客户端依赖

ls /lib64/libncurses.so.5

文件存在


Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐