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
标签:testtable,恢复,数据库,ibd,INNODB,mysql,data,sq From: https://www.cnblogs.com/donfag/p/17723041.html