Ubuntu系统下如何从外接硬盘恢复无dump文件的MySQL数据库
问题原因说明
你两次操作失败的核心原因如下:
- 仅迁移单库文件夹到现有
datadir提示表不存在:InnoDB引擎的表元数据存储在共享表空间文件ibdata1以及重做日志文件ib_logfile0/ib_logfile1中,仅拷贝单库文件夹的情况下,现有MySQL实例的ibdata1中没有对应表的记录,自然无法识别到表。 - 修改
datadir后MySQL启动失败:Ubuntu 18.04 默认启用AppArmor安全模块,会限制MySQL仅能访问默认的/var/lib/mysql/路径,无额外规则的情况下自定义路径会被拦截;此外文件权限不匹配、MySQL版本不兼容也会导致启动失败。
前提条件
你持有的完整数据库文件夹必须包含原MySQL实例根目录下的所有文件,包括ibdata1、ib_logfile0、ib_logfile1以及待恢复库对应的同名文件夹,且恢复用的MySQL大版本必须和原库版本完全一致(如原库为MySQL 5.7就不能用MySQL 8.0 恢复)。
恢复方案
方案1:独立启动恢复(推荐,不影响现有数据库)
该方案适合需要保留现有MySQL实例数据,仅需要导出旧库数据的场景:
停止当前MySQL服务:
sudo systemctl stop mysql将外接硬盘中的完整MySQL数据目录拷贝到本地路径,例如
/data/mysql_old,执行以下命令修复权限(MySQL运行用户为mysql,权限不对无法读取文件):sudo cp -a /外接硬盘的MySQL数据目录路径 /data/mysql_oldsudo chown -R mysql:mysql /data/mysql_oldsudo chmod -R 750 /data/mysql_old修改AppArmor规则,放开MySQL对新数据目录的访问权限:
编辑规则文件:sudo nano /etc/apparmor.d/usr.sbin.mysqld
找到以下两行配置:/var/lib/mysql/ r,
/var/lib/mysql/** rwk,在下方新增两行对应你的新数据目录路径:
/data/mysql_old/ r,
/data/mysql_old/** rwk,保存退出后重载规则:
sudo systemctl reload apparmor修改MySQL配置文件:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf,找到datadir配置项修改为新路径:datadir = /data/mysql_old启动MySQL服务:
sudo systemctl start mysql
若启动失败,可查看错误日志排查问题:sudo tail -n 50 /var/log/mysql/error.log启动成功后即可登录MySQL查看旧库数据,使用
mysqldump导出需要的库之后,将datadir配置改回原有路径重启即可恢复原有实例,再将导出的SQL导入现有实例即可完成数据迁移。
方案2:替换现有实例数据目录
该方案适合不需要保留现有MySQL实例数据的场景,操作和方案1一致,拷贝数据时直接覆盖默认/var/lib/mysql路径即可,不需要修改AppArmor和datadir配置,覆盖后修复/var/lib/mysql的权限为mysql:mysql,直接启动MySQL即可。
注意事项
- 拷贝数据文件时必须用
cp -a参数保留文件原有属性,不要用普通拖拽拷贝,避免属性丢失导致启动失败- 若原数据库不是正常关闭的,不要删除
ib_logfile0/ib_logfile1文件,否则会导致数据丢失;若启动报错提示日志文件大小不匹配,可先在mysqld.cnf中配置innodb_log_file_size参数和原库配置一致即可- 若原库启用了表空间加密,没有对应密钥的情况下无法完成恢复
内容的提问来源于stack exchange,提问作者Spectre

