INNODB数据库恢复方法

发布时间 2023-09-22 17:50:28作者: donfag

MYSQL数据库经常会出现重启数据库服务时卡住不动了,这时只能手动KILL进程,但很多情况下KILL后数据库服务就无法启动了,一般都是ibdata1这个文件损坏导致的,基本没有办法在原来的基础上恢复数据库。官方文档给出的解决办法是,新建一台数据库实例,版本要和原来的一样,前提是INNODB表必须是独立表空间,表的.ibd文件要有。具体处理方法如下:

比如需要恢复testtable这个表:
一、在新的服务器上创建表结构(和原来表结构要一样)
二、丢弃新创建的表的表空间:
ALTER TABLE testtable DISCARD TABLESPACE;
运行结果大概如下:
Query OK, 0 rows affected (0.02 sec)
三、拷贝原来表的.ibd文件到数据库目录下,如:
cp testtable.ibd /var/lib/mysql/sq_data/(确保.ibd文件具有必要的文件权限(chown mysql:mysql testtable.ibd)
四、导入孤立.ibd文件。会发出警告,表明InnoDB正试图在没有架构验证的情况下导入文件:
ALTER TABLE testtable IMPORT TABLESPACE; SHOW WARNINGS;
此命令根据数据库表大小不同运行时间不同,测试一个15G的表大概用了4分多钟。
运行结果大概如下:
Query OK, 0 rows affected, 1 warning (4 min 2.12 sec)
Warning | 1810 | InnoDB: IO Read error: (2, No such file or directory) Error opening './sq_data/testtable.cfg', will attempt to import without schema verification
五、查看数据是否正常:SELECT COUNT(*) testtable;

如果数据表比较多,手动一个个恢复确实太耗时了,所以写了一个脚本批量处理:

 1 import os,sys,logging
 2 from subprocess import Popen #pyton2.7里没有run只能用Popen
 3 LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s - line %(lineno)d"
 4 DATE_FORMAT = "%Y-%m-%d %H:%M:%S %p"
 5 logging.basicConfig(filename='restore_mysql.log', level=logging.DEBUG, format=LOG_FORMAT,datefmt=DATE_FORMAT)
 6 
 7 structure_file_dir = "/root/mysqldata/" #数据表结构文件所在目录
 8 ibd_file_dir = "/root/olddata/sq_date/" #原数据库.ibd文件所在目录
 9 mysql_root_passwd = "*****************" #数据库ROOT用户密码
10 new_mysql_data_dir = "/var/lib/mysql/sq_data/" #新数据库表数据所在目录
11 
12 exclude_table = [ #不需处理的表
13     "test1",
14     "test2"
15 ]
16 def create_table_structure(table_name,sql_file):
17     cmd = "mysql -uroot -p'%s' sq_data<%s%s" % (mysql_root_passwd,structure_file_dir,sql_file)
18     res = Popen(cmd,shell=True)
19     res.wait()
20     if res.returncode != 0:
21         logging.debug("%s structure import failed! exit program!",table_name)
22         sys.exit(0)
23     #print(cmd)
24 def discard_tablespace(table_name):
25     cmd = "mysql -uroot -p'%s' -e 'ALTER TABLE sq_data.%s DISCARD TABLESPACE;'" % (mysql_root_passwd,table_name)
26     res = Popen(cmd,shell=True)
27     res.wait()
28     if res.returncode != 0:
29         logging.debug("%s DISCARD TABLESPACE failed! exit program!",table_name)
30         sys.exit(0)
31     #print(cmd)
32 def copy_ibd_file(table_name):
33     table_path = "%s%s.ibd" % (ibd_file_dir,table_name)
34     if os.path.isfile(table_path):
35         cmd = "cp %s %s" % (table_path,new_mysql_data_dir)
36         cmd2 = "chown mysql:mysql %s%s.ibd" % (new_mysql_data_dir,table_name)
37         res1 = Popen(cmd,shell=True)
38         res1.wait()
39         res2 = Popen(cmd2,shell=True)
40         res2.wait()
41         if res1.returncode != 0:
42             logging.debug("Copy %s failed! exit program!",table_path)
43             sys.exit(0)
44         if res2.returncode != 0:
45             logging.debug("chown %s%s.ibd failed! exit program!",new_mysql_data_dir,table_name)
46             sys.exit(0)
47     else:
48         logging.debug("%s not exist!exit program!",table_path)
49         sys.exit(0)
50         #print(cmd)
51         #print(cmd2)
52 def import_tablespace(table_name):
53     cmd = 'mysql -uroot -p"%s" -e "ALTER TABLE sq_data.%s IMPORT TABLESPACE;"' % (mysql_root_passwd,table_name)
54     res = Popen(cmd,shell=True)
55     res.wait()
56     if res.returncode != 0:
57         logging.debug("%s IMPORT TABLESPACE failed! exit program!",table_name)
58         sys.exit(0)
59     else:
60         print("%s OK" % table_name)
61     #print(cmd)
62 
63 structure_file_list = os.listdir(structure_file_dir)
64 for structure_file_name in structure_file_list:
65     if "_structure." in structure_file_name:
66         table_name = structure_file_name.split("_structure.")[0]
67         if table_name in exclude_table:continue
68         create_table_structure(table_name,structure_file_name) #import table structure
69         discard_tablespace(table_name) #discard tablespace
70         copy_ibd_file(table_name) #copy table.ibd to new dir
71         import_tablespace(table_name) #import tablespace

 

参考网址:http://dev.mysql.com/doc/refman/8.0/en/innodb-troubleshooting-datadict.html