首页 > 数据库 >如何在删除ibdata1和ib_logfile的情况下恢复MySQL数据库

如何在删除ibdata1和ib_logfile的情况下恢复MySQL数据库

时间:2024-09-19 08:52:09浏览次数:9  
标签:2016 ibdata1 18 08 MySQL t2 t1 mysql ib

昨天,有个朋友对公司内部使用的一个MySQL实例开启binlog,但是在启动的过程中失败了(他也没提,为何会失败),在启动失败后,他删除了ibdata1和ib_logfile,后来,能正常启动了,但所有的表通过show tables能看到,但是select的过程中却报“Table doesn't exist”。

于是,建议他试试可传输表空间。

同时,自己也测试了下,确实可行。

测试版本 MySQL 5.6.32 社区版

 

恢复的基本步骤

1. 将原来的数据文件COPY到其它目录下。

2. 创建同名表,表结构必须保持一致。

3. 导出表空间

mysql> ALTER TABLE t DISCARD TABLESPACE;

4. 将原来的数据文件COPY回来

5. 导入表空间

mysql> ALTER TABLE t IMPORT TABLESPACE

 

下面的演示会略为复杂,主要是还原整个场景,并针对上述步骤中的2,4做了一个测试。

 

首先,创建测试数据

在这里创建两张表。之所以创建两张相同的表是为了方便后续的测试。

mysql> create table t1(id int,hiredate datetime);
Query OK, 0 rows affected (0.14 sec)

mysql> create table t2(id int,hiredate datetime);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t1 values(1,now());
Query OK, 1 row affected (0.06 sec)

mysql> insert into t1 values(2,now());
Query OK, 1 row affected (0.00 sec)

mysql> insert into t2 values(1,now());
Query OK, 1 row affected (0.00 sec)

mysql> insert into t2 values(2,now());
Query OK, 1 row affected (0.00 sec)

 

关闭数据库

# /usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/bin/mysqladmin shutdown -uroot -p123456 -h127.0.0.1 -P3310

 

删除ibdata1,ib_logfile0和ib_logfile1

[root@localhost data]# cd /data/
[root@localhost data]# ls
auto.cnf  ib_logfile0  localhost.localdomain.err  mysql_upgrade_info  test
ibdata1   ib_logfile1  mysql                      performance_schema
[root@localhost data]# rm -rf ibdata1 
[root@localhost data]# rm -rf ib_logfile*[root@localhost data]# ls
auto.cnf  localhost.localdomain.err  mysql  mysql_upgrade_info  performance_schema  test

 

重新启动数据库

# /usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/bin/mysqld --defaults-file=/usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/my.cnf &

并没有报错

启动过程中的日志信息如下:

# 2016-08-18 11:13:18 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2016-08-18 11:13:18 0 [Note] /usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/bin/mysqld (mysqld 5.6.32) starting as process 3948 ...
2016-08-18 11:13:18 3948 [Note] Plugin 'FEDERATED' is disabled.
2016-08-18 11:13:18 3948 [Note] InnoDB: Using atomics to ref count buffer pool pages
2016-08-18 11:13:18 3948 [Note] InnoDB: The InnoDB memory heap is disabled
2016-08-18 11:13:18 3948 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2016-08-18 11:13:18 3948 [Note] InnoDB: Memory barrier is not used
2016-08-18 11:13:18 3948 [Note] InnoDB: Compressed tables use zlib 1.2.3
2016-08-18 11:13:18 3948 [Note] InnoDB: Using Linux native AIO
2016-08-18 11:13:18 3948 [Note] InnoDB: Using CPU crc32 instructions
2016-08-18 11:13:18 3948 [Note] InnoDB: Initializing buffer pool, size = 128.0M
2016-08-18 11:13:19 3948 [Note] InnoDB: Completed initialization of buffer pool
2016-08-18 11:13:19 3948 [Note] InnoDB: The first specified data file ./ibdata1 did not exist: a new database to be created!
2016-08-18 11:13:19 3948 [Note] InnoDB: Setting file ./ibdata1 size to 12 MB
2016-08-18 11:13:19 3948 [Note] InnoDB: Database physically writes the file full: wait...
2016-08-18 11:13:19 3948 [Note] InnoDB: Setting log file ./ib_logfile101 size to 48 MB
2016-08-18 11:13:21 3948 [Note] InnoDB: Setting log file ./ib_logfile1 size to 48 MB
2016-08-18 11:13:22 3948 [Note] InnoDB: Renaming log file ./ib_logfile101 to ./ib_logfile0
2016-08-18 11:13:22 3948 [Warning] InnoDB: New log files created, LSN=45781
2016-08-18 11:13:22 3948 [Note] InnoDB: Doublewrite buffer not found: creating new
2016-08-18 11:13:22 3948 [Note] InnoDB: Doublewrite buffer created
2016-08-18 11:13:22 3948 [Note] InnoDB: 128 rollback segment(s) are active.
2016-08-18 11:13:22 3948 [Warning] InnoDB: Creating foreign key constraint system tables.
2016-08-18 11:13:22 3948 [Note] InnoDB: Foreign key constraint system tables created
2016-08-18 11:13:22 3948 [Note] InnoDB: Creating tablespace and datafile system tables.
2016-08-18 11:13:22 3948 [Note] InnoDB: Tablespace and datafile system tables created.
2016-08-18 11:13:22 3948 [Note] InnoDB: Waiting for purge to start
2016-08-18 11:13:22 3948 [Note] InnoDB: 5.6.32 started; log sequence number 0
2016-08-18 11:13:22 3948 [Note] Server hostname (bind-address): '*'; port: 3310
2016-08-18 11:13:23 3948 [Note] IPv6 is available.
2016-08-18 11:13:23 3948 [Note]   - '::' resolves to '::';
2016-08-18 11:13:23 3948 [Note] Server socket created on IP: '::'.
2016-08-18 11:13:23 3948 [Note] Event Scheduler: Loaded 0 events
2016-08-18 11:13:23 3948 [Note] /usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/bin/mysqld: ready for connections.
Version: '5.6.32'  socket: '/data/mysql.sock'  port: 3310  MySQL Community Server (GPL)

可见,在启动的过程中,MySQL会重建ibdata1和redo log。

 

登录mysql客户端,看之前创建的t1,t2是否能访问

# /usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/bin/mysql -h127.0.0.1 -p123456 -uroot -P3310

mysql> use test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| t1             |
| t2             |
+----------------+
2 rows in set (0.00 sec)

mysql> select * from t1;
ERROR 1146 (42S02): Table 'test.t1' doesn't exist

 

通过show tables能查看有t1表存在,但表中的具体内容则无法查看

同时,错误日志中输出以下信息

2016-08-18 11:15:13 3948 [Warning] InnoDB: Cannot open table test/t1 from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how you can resolve the problem.

 

将数据目录下的test目录中的t1,t2表的数据文件和表定义文件COPY到其它地方

[root@localhost test]# cd /data/test/
[root@localhost test]# ll
total 216
-rw-rw---- 1 mysql mysql  8594 Aug 18 11:06 t1.frm
-rw-rw---- 1 mysql mysql 98304 Aug 18 11:07 t1.ibd
-rw-rw---- 1 mysql mysql  8594 Aug 18 11:06 t2.frm
-rw-rw---- 1 mysql mysql 98304 Aug 18 11:07 t2.ibd
[root@localhost test]# mv * /backup/
[root@localhost test]# ls
[root@localhost test]# ll /backup/
total 216
-rw-rw---- 1 mysql mysql  8594 Aug 18 11:06 t1.frm
-rw-rw---- 1 mysql mysql 98304 Aug 18 11:07 t1.ibd
-rw-rw---- 1 mysql mysql  8594 Aug 18 11:06 t2.frm
-rw-rw---- 1 mysql mysql 98304 Aug 18 11:07 t2.ibd

 

登录客户端,创建t1和t2表,注意表结构和之前的必须保持一致

细心的童鞋会发现,下面的创表语句和刚开始的创表语句并不一样,列名不一致,这个其实是为了后续的测试

mysql> show tables;
Empty set (0.00 sec)

mysql> create table t1(id_1 int,hiredate_1 datetime);
ERROR 1146 (42S02): Table 'test.t1' doesn't exist

明明已经手动移除了,为什么创建表的时候还报这个错误呢?

接下来,可先执行个drop table操作

mysql> drop table t1;
ERROR 1051 (42S02): Unknown table 'test.t1'
mysql> create table t1(id_1 int,hiredate_1 datetime);
Query OK, 0 rows affected (0.07 sec)

 

对于t2表,我们定义一个不同的表结构,看是否可行?

mysql> drop table t2;
ERROR 1051 (42S02): Unknown table 'test.t2'
mysql> create table t2(id_1 int);
Query OK, 0 rows affected (0.01 sec)

 

导出表空间

mysql> ALTER TABLE t1 DISCARD TABLESPACE;
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE t2 DISCARD TABLESPACE;
Query OK, 0 rows affected (0.00 sec)

这个时候,数据目录下的test目录下,数据文件没有了,只剩下了表结构文件

[root@localhost test]# ls
t1.frm  t2.frm

 

导入表空间

首先对t1表进行测试

在这里,测试如下两种情况

1. 新的t1.frm+旧的t1.ibd

2. 旧的t1.frm+旧的t1.ibd

 

第一种情况

只是将t1表的数据文件COPY回来

[root@localhost test]# cp /backup/t1.ibd .
[root@localhost test]# chown mysql.mysql t1.ibd 

 

导入t1表的表空间

mysql> ALTER TABLE t1 IMPORT TABLESPACE;
Query OK, 0 rows affected, 1 warning (0.21 sec)

mysql> show warnings;
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                 |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+
| Warning | 1810 | InnoDB: IO Read error: (2, No such file or directory) Error opening './test/t2.cfg', will attempt to import without schema verification |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

 

查看t1表是否能访问

mysql> select * from t1;
+------+---------------------+
| id_1 | hiredate_1          |
+------+---------------------+
|    1 | 2016-08-18 17:45:02 |
|    2 | 2016-08-18 17:45:02 |
+------+---------------------+
2 rows in set (0.00 sec)

mysql> flush table t1;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1;
+------+---------------------+
| id_1 | hiredate_1          |
+------+---------------------+
|    1 | 2016-08-18 17:45:02 |
|    2 | 2016-08-18 17:45:02 |
+------+---------------------+
2 rows in set (0.00 sec)

喔,确实能访问,注意观察,表的列名与新的创表语句保持一致。

在这里之所以使用flush table操作,是为了刷新内存中的表定义。

 

下面看看t1的第二种情况,旧的t1.frm+旧的t1.ibd

mysql> ALTER TABLE t1 DISCARD TABLESPACE;
Query OK, 0 rows affected (0.00 sec)
[root@localhost test]# cp /backup/t1.frm .
cp: overwrite `./t1.frm'? y
[root@localhost test]# cp /backup/t1.ibd .
[root@localhost test]# chown mysql.mysql t1.frm 
[root@localhost test]# chown mysql.mysql t1.ibd 
mysql> ALTER TABLE t1 import TABLESPACE;
Query OK, 0 rows affected, 1 warning (0.04 sec)

mysql> select * from t1;
+------+---------------------+
| id_1 | hiredate_1          |
+------+---------------------+
|    1 | 2016-08-18 17:45:02 |
|    2 | 2016-08-18 17:45:02 |
+------+---------------------+
2 rows in set (0.00 sec)

mysql> flush table t1;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1;
+------+---------------------+
| id   | hiredate            |
+------+---------------------+
|    1 | 2016-08-18 17:45:02 |
|    2 | 2016-08-18 17:45:02 |
+------+---------------------+
2 rows in set (0.00 sec)

第一次查询的时候还是新的列名,对表进行flush后,就恢复到原来的列名了。

 

下面来看看t2表的导入情况

因为t2表的表结构发生了改变,在这里,也是测试如下两种情况

1. 新的t2.frm+旧的t2.ibd

2. 旧的t2.frm+旧的t2.ibd

 

首先,只是导入t2表的数据文件

[root@localhost test]# cp /backup/t2.ibd .
[root@localhost test]# ll
total 216
-rw-rw---- 1 mysql mysql  8594 Aug 18 17:55 t1.frm
-rw-r----- 1 mysql mysql 98304 Aug 18 18:00 t1.ibd
-rw-rw---- 1 mysql mysql  8556 Aug 18 17:52 t2.frm
-rw-r----- 1 root  root  98304 Aug 18 18:10 t2.ibd
[root@localhost test]# chown mysql.mysql t2.ibd 

 

导入t2表的表空间进行测试

mysql> ALTER TABLE t2 import TABLESPACE;
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql> select * from t2;
+------+
| id_1 |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)

mysql> flush table t2;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t2;
+------+
| id_1 |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)

从结果可以看出,只能读出第一列。

 

下面测试第二种情况,旧的t2.frm和t2.ibd

mysql> ALTER TABLE t2 DISCARD TABLESPACE;
Query OK, 0 rows affected (0.06 sec)
[root@localhost test]# rm -rf t2.frm 
[root@localhost test]# cp /backup/t2.frm .
[root@localhost test]# cp /backup/t2.ibd .
[root@localhost test]# chown mysql.mysql t2.frm 
[root@localhost test]# chown mysql.mysql t2.ibd 
mysql> ALTER TABLE t2 import TABLESPACE;
Query OK, 0 rows affected, 1 warning (0.09 sec)

mysql> select * from t2;
+------+
| id_1 |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)

mysql> flush table t2;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t2;
ERROR 1146 (42S02): Table 'test.t2' doesn't exist

在重新刷新后,就出现错误了,个人感觉,这个和系统表空间中的数据字典信息有关。

 

实际上,后续还测试了一下,如果将hiredate的列定义为varchar,则无论是使用之前的frm文件还是之后的,在导入表空间,进行查询时,数据库直接挂掉。

mysql> create table t1(id int,hiredate varchar(10));
Query OK, 0 rows affected (0.05 sec)

mysql> ALTER TABLE t1 DISCARD TABLESPACE;
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE t1 import TABLESPACE;
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql> select * from t1;
ERROR 2013 (HY000): Lost connection to MySQL server during query

 

结论

经过上面的一系列测试,可以看到

1. 使用可传输表空间,可以解决在删除ibdata1和ib_logfile的情况下恢复MySQL数据库,当然,本文测试的前提是数据库正常关闭下删除的ibdata1和ib_logfile。

2. 使用可传输表空间,建议新建表的表结构和原来的表结构完全一致,同时,在导入表空间前,只需COPY回原来的数据文件,即ibd。

 

事实上,在数据库正常关闭下删除ibdata1,会导致mysql库中的以下几张表无法访问

mysql> select table_name from information_schema.tables  where table_schema='mysql' and engine='innodb';
+----------------------+
| table_name           |
+----------------------+
| innodb_index_stats   |
| innodb_table_stats   |
| slave_master_info    |
| slave_relay_log_info |
| slave_worker_info    |
+----------------------+
5 rows in set (0.00 sec)

mysql> select * from mysql.innodb_index_stats;
ERROR 1146 (42S02): Table 'mysql.innodb_index_stats' doesn't exist
mysql> select * from mysql.innodb_table_stats;
ERROR 1146 (42S02): Table 'mysql.innodb_table_stats' doesn't exist
mysql> select * from mysql.slave_master_info;
ERROR 1146 (42S02): Table 'mysql.slave_master_info' doesn't exist
mysql> select * from mysql.slave_relay_log_info;
ERROR 1146 (42S02): Table 'mysql.slave_relay_log_info' doesn't exist
mysql> select * from mysql.slave_worker_info;
ERROR 1146 (42S02): Table 'mysql.slave_worker_info' doesn't exist

同时,错误日志中报如下信息

2016-08-19 12:10:18 3041 [Warning] InnoDB: Cannot open table mysql/innodb_index_stats from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how you can resolve the problem.
2016-08-19 12:10:26 3041 [Warning] InnoDB: Cannot open table mysql/innodb_table_stats from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how you can resolve the problem.
2016-08-19 12:10:34 3041 [Warning] InnoDB: Cannot open table mysql/slave_master_info from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how you can resolve the problem.
2016-08-19 12:10:40 3041 [Warning] InnoDB: Cannot open table mysql/slave_relay_log_info from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how you can resolve the problem.
2016-08-19 12:10:46 3041 [Warning] InnoDB: Cannot open table mysql/slave_worker_info from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how you can resolve the problem.

 

要解决这个问题,只能重建这些表。

 

参考

1. http://dev.mysql.com/doc/refman/5.6/en/tablespace-copying.html

2. http://dba.stackexchange.com/questions/48166/cannot-open-table-mysql-innodb-index-stats

来源:https://www.cnblogs.com/ivictor/p/5784258.html

标签:2016,ibdata1,18,08,MySQL,t2,t1,mysql,ib
From: https://www.cnblogs.com/ataoxz/p/18419734

相关文章

  • Can't connect to local MySQL server through socket
    mysql-urootERROR2002(HY000):Can'tconnecttolocalMySQLserverthroughsocket'/tmp/mysql.sock'(2)这是mysql登录时找不到套接字的问题。首先需要明白的是,Linux端的mysqlserver启动时会开启一个socket,Linux上的MySQL的客户端在不使用IP连接时mysqlserver时,默认......
  • MySQL 子查询全解析:执行、性能影响与优化策略
    在MySQL数据库的操作中,子查询是一个强大而又复杂的工具。今天,我们就来深入探讨MySQL如何执行子查询、其性能影响、优化方法以及哪些情况下应避免使用子查询。一、MySQL如何执行子查询非相关子查询非相关子查询也被称为独立子查询,它可以独立于外部查询进行执行。MyS......
  • MySQL 二进制日志(binlog):理解与应用
    在MySQL数据库的世界里,二进制日志(binlog)是一个至关重要的组成部分。那么,什么是MySQL的二进制日志呢?它又有着哪些重要的作用呢?让我们一起来深入探讨。一、什么是MySQL的二进制日志(binlog)MySQL的二进制日志是一种记录数据库变更的文件。它以二进制格式记录了数据库中......
  • MySQL 触发器的创建、使用及在 Java 中的调用
    在数据库管理中,MySQL的触发器是一种强大的工具,它可以在特定的数据库事件发生时自动执行一系列操作。同时,我们还可以在Java应用程序中与这些触发器进行交互,实现更复杂的业务逻辑。今天,我们就来一起探讨如何在MySQL中创建和使用触发器,并在Java中调用它们。一、MySQL中创建和......
  • MYSQL 查询将列中的所有数据从一个数据库复制到另一个数据库
    数据迁移的定义数据迁移是指将数据从一个系统或存储位置移动到另一个系统或存储位置的过程。它涉及到数据的提取、转换和加载,以确保数据在新的环境中能够正确地使用和访问。数据迁移通常是为了实现系统升级、数据中心迁移、数据库合并等目的。在数据迁移过程中,需要考虑数据的完整性......
  • mysql中varchar存储的长度
    一、varchar数据类型简介(一)varchar的定义和特点是一种可变长度的字符数据类型,用于存储可变长度的字符串。它的特点是可以根据实际存储的字符串长度动态分配存储空间,从而节省存储空间。与固定长度的字符数据类型相比,varchar更加灵活,可以适应不同长度的字符串存储需求。在MySQL......
  • 在idea中使用mysql失败
    在idea中测试mysql显示失败idea方面视图-工具窗口-数据库或者右边有图标直接点开新建-数据源-mysql名称-用户(root)-密码-测试连接如果测试连接有切换相关提示直接点击,如果出绿色对勾就成功了到这里本可以结束了,但是我最开始做的时候这个流程......
  • 1. 如何在Java中连接MySQL数据库?请解释使用JDBC连接的步骤。
    要在Java中连接MySQL数据库,通常使用JDBC(JavaDatabaseConnectivity)API。这是一个用于执行SQL语句的JavaAPI,可以用来访问关系型数据库。下面是使用JDBC连接MySQL数据库的详细步骤:1.添加MySQLJDBC驱动首先,需要确保项目中包含MySQL的JDBC驱动程序。这个驱动程序通常是一个......
  • MySql 对数据库和表的操作
    目录一.登入MySql二.数据库的操作1.创建数据库案例 2.字符集和校验规则 3.操纵数据库 4.数据库备份和恢复5.查看连接情况三..表结构的操作1. 创建表2.查看表结构3.表属性操作4.查看表中具体信息   5.修改表名6.删除表 7.备份和恢复一.登入MySql......
  • 【MySQL】使用C语言连接数据库
           看到标题,可能会疑惑,我们学习的不是C++吗,为什么使用C语言去连接数据库呢??实际上,这两种语言都可以连接数据库,但是C语言提供的API没有进行封装,更有利于我们学习数据库连接。面向API编程,哈哈哈哈哈哈!!!!!一、安装适合自己平台的mysqlconnect库    因为我使用......