第四章:数据库运维实录 — 密码更换、故障恢复与经验教训

作者:

背景

CleanLearn 的 MariaDB 数据库有一个应用用户 english_app,原始密码是 english_app_pass——太弱了,而且是明文写在多个配置文件里的。出于安全考虑,决定把密码换掉,同时把忘了的 root 密码也重置。

看起来很简单:改 config.py → 改 MySQL 用户密码 → 重启服务。实际上踩了一串坑。

踩坑全记录

坑 1:改了配置文件但忘了改数据库

第一步很自然地用 sed/opt/english-api/config.py 里的 english_app_pass 替换成了 mypwd。改完重启服务——所有 API 返回 500。

原因很简单:MySQL 里 english_app 用户的密码还是旧的。配置文件改了,但数据库用户密码没同步,连接当然失败。

坑 2:不知道 root 密码

要改 english_app 的密码,需要 root 权限。但 root 密码是什么?翻遍了服务器上的配置文件、脚本、环境变量,都没有。尝试无密码登录:

mysql -u root           # 不行
mysql -u root -p        # 不知道密码
mariadb -u root         # 也不行

MariaDB 10.11 默认没有开启 unix_socket 认证,root 必须用密码。唯一的办法:跳过权限验证启动

坑 3:skip-grant-tables 下的 ALTER USER 不生效

跳过权限验证的标准操作:

systemctl stop mariadb
mariadbd --skip-grant-tables --user=mysql &
mariadb -u root -e "ALTER USER 'english_app'@'localhost' IDENTIFIED BY 'mypwd';"

结果报错:

ERROR 1290 (HY000): The MariaDB server is running with the
--skip-grant-tables option so it cannot execute this statement

--skip-grant-tables 模式下,权限表完全不加载,所以 ALTER USER 这类 DCL 语句不能直接执行。必须先 FLUSH PRIVILEGES 加载权限表,再执行 ALTER

mariadb -u root -e "
  FLUSH PRIVILEGES;
  ALTER USER 'english_app'@'localhost' IDENTIFIED BY 'mypwd';
  ALTER USER 'root'@'localhost' IDENTIFIED BY 'mypwd';
  FLUSH PRIVILEGES;
"

坑 4:临时进程没杀掉,服务起不来

密码改完后,用 kill %1 杀临时 mariadbd 进程,然后 systemctl start mariadb。结果服务启动失败——因为临时进程是 nohup 启动的,kill %1 在非交互式 SSH 中无效,旧进程还占着 3306 端口。

正确做法是 pkill -9 mariadbd 彻底清场再重启

pkill -9 mariadbd
sleep 2
systemctl start mariadb
# 验证
mysql -u root -pmypwd -e "SELECT 1 AS ok;"

后续完善

创建免密配置文件

改完密码后,每次敲 mysql -u root -pmypwd 很麻烦,而且密码会留在 shell 历史里。创建 /root/.my.cnf

[client]
user=root
password=mypwd
chmod 600 /root/.my.cnf
# 之后直接 mysql -e "..." 即可

同步所有配置文件

密码改了,但服务器上还有多个脚本硬编码了旧密码:

/opt/english-api/fix_phonetics.py
/opt/english-api/fix_worker.py
/opt/english-api/extract_answers.py
/opt/english-api/link_audio.py
/opt/english-api/link_audio2.py
# 全部 sed 替换 english_app_pass → mypwd

本地也一样——CLAUDE.md 和知识库 memory 文件里的连接串也要更新。

完整操作 checklist

总结一个”安全更换数据库密码”的步骤,下次照着做就不会踩坑:

  1. 确认知道 root 密码(不知道就先 reset)
  2. 改 MySQL 用户密码ALTER USER 'xxx'@'localhost' IDENTIFIED BY 'newpass'; FLUSH PRIVILEGES;
  3. 改应用配置文件config.py 里的连接串
  4. 改所有硬编码脚本:grep 全局搜索旧密码,逐一替换
  5. 重启应用服务systemctl restart english-api
  6. 验证连接mysql -u xxx -pnewpass -e "SELECT 1"
  7. 更新文档:CLAUDE.md、知识库、团队共享的配置说明
  8. 清理 shell 历史history -c 避免密码残留

经验教训

  • skip-grant-tables 模式下要先 FLUSH PRIVILEGES 再 ALTER USER,否则语法报错
  • 非交互 shell 不认 kill %1,用 pkill 杀进程更可靠
  • 密码要全局搜索替换:配置文件、脚本、文档、知识库,少改一处就是一颗定时炸弹
  • 创建 ~/.my.cnf 不仅能免密登录,还能避免密码留在命令历史里

← 返回目录

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注