MySQL 可能会由于各种原因表空间损坏,导致 show tables 可以看到表,但 show create table 或 select 查询等操作时,提示表不存在
问题
MySQL InnoDB 引擎的表 show tables 可以看到表存在,但使用时提示表不存在,为了避免数据丢失,需要进行数据恢复。如果数据可以丢失或再次写入,可直接 drop 之后,手动删除表物理文件,并重新创建表写入数据。 这里只针对需要保留数据的情况进行恢复
前提条件
- 数据文件
ibd 文件存在 - 存在表结构备份,可以找到一模一样的
create table 语句 - 这里以系统表
mysql.gtid_executed 表为例
恢复步骤
为了避免操作失误导致数据丢失,可先将对应数据文件多复制一份到临时路径 本身可以直接在业务库进行恢复,但这里为了避免恢复重要数据,导致其他不可控异常,所以新建临时库进行恢复
create database gtid_recover;
use gtid_recover
CREATE TABLE `gtid_executed` (
`source_uuid` char(36) NOT NULL COMMENT 'uuid of the source where the transaction was originally executed.',
`interval_start` bigint(20) NOT NULL COMMENT 'First number of interval.',
`interval_end` bigint(20) NOT NULL COMMENT 'Last number of interval.',
PRIMARY KEY (`source_uuid`,`interval_start`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE gtid_executed DISCARD TABLESPACE;
cp /backup_dir/gtid_executed.ibd /mysqldatadir/mysql/
chown -R mysql.mysql /mysqldatadir
alter table gtid_executed IMPORT TABLESPACE;
use gtid_recover
rename table gtid_executed to mysql.gtid_executed_bak;
use mysql
drop table gtid_executed;
rename table gtid_executed_bak to gtid_executed;
改表期间数据库崩溃导致异常
如果使用临时表的方式改表,改表过程中数据库异常崩溃,此时需要先找到删除该表中间的临时表,再进行上述操作。
如果数据库存在主从架构,需执行完成后,根据主从异常报错信息处理对应主从问题即可
- 查找临时表名称 SQL
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE '%#sql%'; - 在物理机上,将临时表空间文件改为查询后的表名
mv \#sql-物理机显示名称.frm \#sql-上步查询结果.frm - 删除这个孤立的临时表
drop table 第一步查询结果的临时表名 - 按照前面恢复步骤再重构表,恢复数据库异常
|