Go程序连接MariaDB后无法访问Unix Socket的诡异问题求助
调试方向建议
核心现象回顾
- 连接MariaDB前,
os.Stat("/var/lib/mysql/mysql.sock")正常,可成功连接并查询数据 - 连接建立后,再次执行
os.Stat返回stat /var/lib/mysql/mysql.sock: no such file or directory SetConnMaxLifetime到期后,连接池无法重连,所有查询失败- 调用
db.Close()后,os.Stat又能正常找到socket文件 - socket权限为
0777,父目录均具备o+x权限,已禁用fapolicyd和SELinux
具体调试步骤
1. 排查进程命名空间隔离问题
- 找到Go进程PID:
ps aux | grep <你的Go程序名> - 检查进程根目录下的socket路径:
ls -l /proc/<Go进程PID>/root/var/lib/mysql/mysql.sock,若不存在,说明进程可能处于独立的文件系统命名空间,路径映射发生变化 - 对比Go进程与MariaDB进程的命名空间:
重点对比# 查看Go进程命名空间 lsns -p <Go进程PID> # 查看MariaDB进程命名空间(先拿PID) ps aux | grep mysqld lsns -p <MariaDB进程PID>mnt(挂载)命名空间是否一致
2. 跟踪进程系统调用
- 实时跟踪Go进程的
stat和connect调用:
观察连接前后strace -p <Go进程PID> -e stat,connectstat的路径参数、返回值差异 - 全程记录系统调用日志,事后分析:
搜索日志中strace -o go_db_trace.log -f <你的Go程序启动命令>stat /var/lib/mysql/mysql.sock相关条目,定位错误触发的上下文
3. 监控MariaDB socket文件状态
- 持续监控socket的存在、权限、inode变化:
若inode号发生变化,说明socket被删除重建watch -n 1 ls -li /var/lib/mysql/mysql.sock - 查看MariaDB日志(默认路径
/var/log/mariadb/mariadb.log),搜索socket相关条目,确认是否存在重启、异常重建socket的情况
4. 验证Go连接池行为
- 在代码中添加日志,记录连接获取、释放时间点,以及
SetConnMaxLifetime的配置值,确认连接到期回收时机与问题触发时间是否匹配 - 限制连接池大小为1,复现问题:
排查是否为多连接导致的资源冲突db.SetMaxOpenConns(1)
5. 检查文件描述符限制
- 查看Go进程的文件描述符限制:
对比系统限制,确认是否存在文件描述符耗尽情况cat /proc/<Go进程PID>/limits | grep "Max open files" - 查看socket的进程持有情况:
排查是否有异常进程持续占用socket资源lsof | grep mysql.sock
内容的提问来源于stack exchange,提问作者Taco de Wolff
相关产品推荐
相关产品推荐

