• 0929误删除innodb ibdata数据文件


    今天在群里看到有人说不熟悉innodb把ibdata(数据文件)和ib_logfile(事务日志)文件误删除了。不知道怎么解决。当时我也不知道怎么办。后来查阅相关资料。终找到解决方法。其实恢复也挺简单的。我们不知道的时候就觉得难了。谁说不是这样呢?

    下面我们就来模拟生产环境下,人为删除数据文件和重做日志文件。然后详细说明恢复步骤。

    1.用sysbench模拟数据的写入,如下所示:

    [root@yayun-mysql-server ~]# sysbench --test=oltp --oltp-table-size=1000000 --oltp-read-only=off --init-rng=on --num-threads=16 --max-requests=0 --oltp-dist-type=uniform --max-time=1800 --mysql-user=root --mysql-socket=/tmp/mysqld.sock --mysql-password=123456 --db-driver=mysql --mysql-table-engine=innodb --oltp-test-mode=complex prepare      
    sysbench 0.4.10:  multi-threaded system evaluation benchmark
    
    Creating table 'sbtest'...
    Creating 1000000 records in table 'sbtest'...

    2.使用命令rm -f ib*删除数据文件和事务日志文件:

    复制代码
    [root@yayun-mysql-server mysql]# ls
    employees    ib_logfile1       mysql-bin.000003  mysql-bin.000008  performance_schema  world_innodb                  yayun-mysql-server.pid
    general.log  menagerie         mysql-bin.000004  mysql-bin.000009  sakila              world_myisam
    host         mysql             mysql-bin.000005  mysql-bin.000010  sbtest              xtrabackup_binlog_pos_innodb
    ibdata1      mysql-bin.000001  mysql-bin.000006  mysql-bin.index   slow-query.log      yayun
    ib_logfile0  mysql-bin.000002  mysql-bin.000007  percona           test                yayun-mysql-server.err
    [root@yayun-mysql-server mysql]# rm -f ib*
    [root@yayun-mysql-server mysql]# 
    复制代码

    下面我们来看看如何恢复:

    若此时发现数据库还能正常工作,数据依然可读可写,切记:这个时候千万不要把mysqld进程杀死,否则真没法挽救了,你就等着哭吧。

    复制代码
    (root@yayun 20:42:25pm> ) [yayun]>select * from t1;
    +----+-------+
    | id | name  |
    +----+-------+
    |  1 | yayun |
    |  2 | atlas |
    |  3 | mysql |
    +----+-------+
    3 rows in set (0.00 sec)
    
    (root@yayun 20:42:28pm> ) [yayun]>insert into t1 select 4,'python';
    Query OK, 1 row affected (0.01 sec)
    Records: 1  Duplicates: 0  Warnings: 0
    
    (root@yayun 20:42:48pm> ) [yayun]>select * from t1;                
    +----+--------+
    | id | name   |
    +----+--------+
    |  1 | yayun  |
    |  2 | atlas  |
    |  3 | mysql  |
    |  4 | python |
    +----+--------+
    4 rows in set (0.00 sec)
    
    (root@yayun 20:42:50pm> ) [yayun]>
    复制代码

    我这里读写都正常。所以我们能够恢复成功的。
    (1)首先,先找到mysqld进程的pid,如下所示:

    [root@yayun-mysql-server ~]# netstat -nltp | grep mysqld
    tcp        0      0 0.0.0.0:3306                0.0.0.0:*                   LISTEN      5725/mysqld         
    [root@yayun-mysql-server ~]# 

    可见mysqld的pid是5725,这一步是关键的一步。

    (2)使用如下命令查看结果(非常重要)

    [root@yayun-mysql-server ~]# ll /proc/5725/fd | egrep 'ib_|ibdata'
    lrwx------. 1 root root 64 Apr 30 20:44 10 -> /data/mysql/ib_logfile1 (deleted)
    lrwx------. 1 root root 64 Apr 30 20:44 4 -> /data/mysql/ibdata1 (deleted)
    lrwx------. 1 root root 64 Apr 30 20:44 9 -> /data/mysql/ib_logfile0 (deleted)
    [root@yayun-mysql-server ~]# 

    这里有相关很重要的知识,童鞋们自行查阅,删除一个文件时,并不是真正删除,而是打一个标记,同样在我们mysql数据库中,delete一条记录实际的删除操作也没有发生。
    上面显示的结果中,其中10,4,9就是我们需要恢复的文件。

    (3)在恢复文件前,需要执行flush tables with read lock,确保数据库没有写入操作,以便我们完成恢复

    (root@yayun 20:55:26pm> ) [(none)]>flush tables with read lock;
    Query OK, 0 rows affected (0.00 sec)
    
    (root@yayun 20:55:31pm> ) [(none)]>

    那么我们如何确定没有数据写入呢?分几个步骤查看

    (1)设置脏页刷新比例(让脏页尽快刷新到磁盘)

    (root@yayun 20:55:31pm> ) [(none)]>set global innodb_max_dirty_pages_pct=0;
    Query OK, 0 rows affected (0.00 sec)
    
    (root@yayun 20:57:42pm> ) [(none)]>

    (2)查看binlog日志写入情况,确保File和Position的值没有发生变化

    复制代码
    (root@yayun 20:57:42pm> ) [(none)]>show master status;
    +------------------+----------+--------------+------------------+
    | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +------------------+----------+--------------+------------------+
    | mysql-bin.000010 | 61704130 |              |                  |
    +------------------+----------+--------------+------------------+
    1 row in set (0.00 sec)
    
    (root@yayun 20:59:11pm> ) [(none)]>
    复制代码

    (3)查看innodb状态信息,确保脏页已经刷新到磁盘

    复制代码
    (root@yayun 20:59:11pm> ) [(none)]>show engine innodb statusG
    ------------
    TRANSACTIONS
    ------------
    Trx id counter B9E0F
    Purge done for trx's n:o < B9E0C undo n:o < 0    #确保后台线程purge把undo log全部清刷掉
    
    -------------------------------------
    INSERT BUFFER AND ADAPTIVE HASH INDEX
    -------------------------------------
    Ibuf: size 1, free list len 2543, seg size 2545, 0 merges  #确保合并插入缓存等于1
    
    ---
    LOG
    ---
    Log sequence number 6173930288
    Log flushed up to   6173930288            #确保这里三个值保持一致,并且不再变化
    Last checkpoint at  6173930288
    
    Buffer pool size   65534
    Free buffers       50513
    Database pages     15020
    Old database pages 5506
    Modified db pages  0                       #确保脏页数量为0
    
    --------------
    ROW OPERATIONS
    --------------
    0 queries inside InnoDB, 0 queries in queue
    1 read views open inside InnoDB
    Main thread process no. 5725, id 140014471358208, state: waiting for server activity
    Number of rows inserted 1000004, updated 1995, deleted 0, read 2008
    0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s           #确保插入,更新,删除为0
    复制代码

    上面我们都确认后,就可以进行恢复操作了。记得前面我们查看要恢复的文件的命令吧,我们的mysqld进程的pid是5725,我们再次看看需要恢复的文件

    [root@yayun-mysql-server ~]# ll /proc/5725/fd | egrep 'ib_|ibdata'
    lrwx------. 1 root root 64 Apr 30 20:44 10 -> /data/mysql/ib_logfile1 (deleted)
    lrwx------. 1 root root 64 Apr 30 20:44 4 -> /data/mysql/ibdata1 (deleted)
    lrwx------. 1 root root 64 Apr 30 20:44 9 -> /data/mysql/ib_logfile0 (deleted)
    [root@yayun-mysql-server ~]# 

    把10,4,9文件cp到原来mysql的数据目录下:

    [root@yayun-mysql-server ~]# cd /proc/5725/fd
    [root@yayun-mysql-server fd]# cp 10 /data/mysql/ib_logfile1
    [root@yayun-mysql-server fd]# cp 4 /data/mysql/ibdata1
    [root@yayun-mysql-server fd]# cp 9 /data/mysql/ib_logfile0
    [root@yayun-mysql-server fd]# 

    修改文件权限

    复制代码
    [root@yayun-mysql-server ~]# cd /data/mysql
    [root@yayun-mysql-server mysql]# chown -R mysql.mysql ib*
    [root@yayun-mysql-server mysql]# ll | egrep 'ib_|ibdata1'
    -rw-r--r-- 1 mysql mysql 866123776 Apr 30 21:13 ibdata1
    -rw-r--r-- 1 mysql mysql  67108864 Apr 30 21:13 ib_logfile0
    -rw-r--r-- 1 mysql mysql  67108864 Apr 30 21:11 ib_logfile1
    [root@yayun-mysql-server mysql]# 
    复制代码

    重启mysql,修复完成

    [root@yayun-mysql-server mysql]# /etc/init.d/mysqld restart
    Shutting down MySQL...                                     [  OK  ]
    Starting MySQL....                                         [  OK  ]
    [root@yayun-mysql-server mysql]# 

    注意:生产环境切勿测试,童鞋们可以自己开启虚拟机进行测试。

  • 相关阅读:
    1.8其他命令
    1.7远程管理常用命令
    1.6.系统信息相关命令
    1.5linux用户权限相关命令
    python 进程创建和共享内容的方法
    python 操作数据库
    python 类方法中参数使用默认值的方法
    异常处理
    推导列表
    装饰器 装饰带参数的函数和添加函数
  • 原文地址:https://www.cnblogs.com/qcfeng/p/7611707.html
Copyright © 2020-2023  润新知