使用Docker部署MySQL数据库时数据无法持久化问题求助
问题根因与修复方案
1. 最可能原因:host网络模式引发的端口冲突
你给MySQL容器配置了network_mode: "host",此时容器会直接复用宿主机的网络栈,MySQL默认监听的3306端口会直接绑定到宿主机。如果你的宿主机本身就运行着一个MySQL服务,就会出现逻辑错位:
- 你的Python代码实际连接的是宿主机本地的MySQL,写入操作也落到了本地库中
- 你查看容器内
/var/lib/mysql/donuts/*.ibd的更新,实际是容器初始化、启动时的文件变动,和你的写入操作无关 - 自然你进入容器查库是空的,重启容器数据也不会持久化到容器的挂载卷里
验证方法:
停止所有Docker容器后,Windows系统执行netstat -ano | findstr 3306,Linux/macOS系统执行sudo lsof -i:3306,如果还有进程占用3306端口,就说明宿主机本地存在MySQL服务。
修复方法:
如果确实需要保留host网络模式,可以修改MySQL容器的配置,让容器内的MySQL监听非默认端口,避免和宿主机本地MySQL冲突,同时修改Python代码里的数据库连接端口对应即可。
2. 第二高频原因:数据库事务未提交
pymysql连接默认关闭自动提交,如果你执行写入操作后没有显式调用commit(),会出现以下现象:
- 执行写入的Python连接可以读到自己写入的未提交数据,符合你说的“容器存活时Python可以正常读取数据”
- 其他连接(比如你CLI进入容器打开的mysql客户端)看不到未提交的事务数据
- 容器重启、连接断开后,未提交的事务会自动回滚,数据彻底丢失
修复方法:
两种方案二选一即可:
- 每次执行INSERT、UPDATE等写入操作后,手动调用
connection.commit() - 创建pymysql连接时添加
autocommit=True参数,开启自动提交
3. 挂载卷有效性验证
你的docker-compose配置里已经正确声明了mysql-data命名卷挂载到/var/lib/mysql,正常情况下docker compose down不会删除该卷,只有执行docker compose down -v或者docker volume prune时才会清理。你可以按以下步骤验证卷是否正常:
- 插入数据后停止db容器:
docker stop db - 临时启动一个容器挂载该卷查看文件:
docker run --rm -v mysql-data:/vol mysql:8.0.25 ls -l /vol/donuts - 确认ibd文件的修改时间和你写入数据的时间匹配,即可确认卷挂载正常。
内容的提问来源于stack exchange,提问作者James McCormac
相关产品推荐
相关产品推荐

