truncate命令可以一次性删除当前表中所有记录并且不留任何日志,同时这个表的ID就自动初化从1开始,今天我就来给大家尝试一个利用truncate清除记录之后恢复过程。

实际线上的场景比较复杂,当时涉及了truncate, delete 两个操作,经确认丢数据差不多7万多行,等停下来时,差不多又有共计1万多行数据写入。 这里为了简单说明,只拿弄一个简单的业务场景举例。

测试环境: Percona-Server-5.6.16
日志格式: mixed 没起用gtid
表结构如下:
代码如下 复制代码
CREATETABLE`tb_wubx`(`id`INT(11)NOTNULLAUTO_INCREMENT,`name`VARCHAR(32)DEFAULTNULL,PRIMARYKEY(`id`)) ENGINE=InnoDB AUTO_INCREMENT=2DEFAULT CHARSET=utf8
基于某个时间点有一个备份或是有全量的binlog是能恢复数据的一个唯一保证。 例如我们的备份就是一个表结构创建语句,binlog pos相关信息: mysql-bin.000004 , 4,然后进行了如下:
代码如下 复制代码
-t1时间 程序写入:
insert into tb_wubx(name) values(‘张三’),(‘李四’);
insert into tb_wubx(name) values(‘隔壁老王’);
-t2时间 某个人员失误
truncate table tb_wubx;
-t3时间 程序写入
insert into tb_wubx(name) values(‘老赵’);
update tb_wubx set name=’老赵赵’ where id=1;
现在表里的数据情况:
代码如下 复制代码
mysql>SELECT*FROM tb_wubx;
+----+-----------+| id | name |+----+-----------+|1| 老赵赵 |+----+-----------+1ROWINSET(0.00 sec)
可以见truncate table操作后,表的自增id又变更为从1开始,原来写入的数据应该是:
+—-+———-+
| id | name |
+—-+———-+
| 1 | 张三 |
+—-+———-+
| 2 | 李四 |
+—-+———-+
| 3 | 隔壁老王 |
+—-+———-+
如果没生truncate table操作,实际的数据应该为:
代码如下 复制代码
+—-+———-+
| id | name |
+—-+———-+
| 1 | 张三 |
+—-+———-+
| 2 | 李四 |
+—-+———-+
| 3 | 隔壁老王 |
+—-+———-+
| 4 | 老赵赵 |
+—-+———-+
而且线上的恢复那个表时和序序开发人员了解才知道,原来那个id和缓存及其它地方有依赖,因为id乱了,也会造成程序错乱。这个时间修复id在程序层错乱的事,留给开发人员了关建是给他们讲明白恢复的结果是什么样,我们的关建任务是把数据恢复出来。好,接下来的工作是开始从binlog中恢复数据。
利用: show binary logs; 查看当的log文件分布, 然后利用show binlog events in ‘binary log文件’; 查看log文件的内容,目的是找到truncate发生的日志位置。
另外因为基于备份(由log的启始位置)或是从量log, 如果基于备份有log的起始位置,我们需要处理的log文件是启始位置到发生truncate的日值(后面的数据处理不了,会发生主建冲突的错误造成truncate后的数据不能恢复),
如果是全量日志,需要从创建完mysql后库后的日志去处理到当前的发生truncate的位置(后面数据会因为主建冲突写不进去)
恢复准备工作,创建一个库用于恢复数据,这里创建了一个re_wubx, 及原结构的表: tb_wubx (相当于恢复了备份,过程省略)
作者:吴炳锡 来源:http://www.mysqlsupport.cn/ 联系方式: wubingxi#gmail.com 转载请注明作/译者和出处,并且不能用于商业用途,违者必究.
代码如下 复制代码
mysql>SHOWBINARY logs;
+------------------+-----------+| Log_name | File_size |+------------------+-----------+| mysql-bin.000001 |143|| mysql-bin.000002 |261|| mysql-bin.000003 |562|| mysql-bin.000004 |1144|+------------------+-----------+4ROWSINSET(0.00 sec)
我这里有一个备份文件就是那个创建表的sql语句,位置是mysql-bin.000004 , 4
在这个案例里我只用cover住mysql-bin.000004这个文件。
代码如下 复制代码
mysql>SHOW binlog events IN'mysql-bin.000004';
+------------------+------+-------------+-----------+-------------+----------------------------------------------------+| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |+------------------+------+-------------+-----------+-------------+----------------------------------------------------+| mysql-bin.000004 |4| Format_desc |753306|120| Server ver: 5.6.16-64.2-rel64.2-log, Binlog ver: 4|| mysql-bin.000004 |120| Query |753306|209|USE`wubx`; TRUNCATETABLE tb_wubx || mysql-bin.000004 |209| Query |753306|281|BEGIN|| mysql-bin.000004 |281| Table_map |753306|334| table_id: 91(wubx.tb_wubx)|| mysql-bin.000004 |334| Write_rows |753306|393| table_id: 91 flags: STMT_END_F || mysql-bin.000004 |393| Xid |753306|424| COMMIT /* xid=1073 */|| mysql-bin.000004 |424| Query |753306|496|BEGIN|| mysql-bin.000004 |496| Table_map |753306|549| table_id: 91(wubx.tb_wubx)|| mysql-bin.000004 |549| Write_rows |753306|602| table_id: 91 flags: STMT_END_F || mysql-bin.000004 |602| Xid |753306|633| COMMIT /* xid=1074 */|| mysql-bin.000004 |633| Query |753306|722|USE`wubx`; TRUNCATETABLE tb_wubx || mysql-bin.000004 |722| Query |753306|794|BEGIN|| mysql-bin.000004 |794| Table_map |753306|847| table_id: 92(wubx.tb_wubx)|| mysql-bin.000004 |847| Write_rows |753306|894| table_id: 92 flags: STMT_END_F || mysql-bin.000004 |894| Xid |753306|925| COMMIT /* xid=1081 */|| mysql-bin.000004 |925| Query |753306|997|BEGIN|| mysql-bin.000004 |997| Table_map |753306|1050| table_id: 92(wubx.tb_wubx)|| mysql-bin.000004 |1050| Update_rows |753306|1113| table_id: 92 flags: STMT_END_F || mysql-bin.000004 |1113| Xid |753306|1144| COMMIT /* xid=1084 */|+------------------+------+-------------+-----------+-------------+----------------------------------------------------+19ROWSINSET(0.00 sec)
看到这个表刚开始就发生一次truncate, 那其实也可以说明我就恢复刚开始那个truncate到后来那个误操作的truncate table的语句之间的数据就是丢失的数据。
这个恢复可以从mysql-bin.000004 pos: 4到mysql-bin.000004 pos: 633 即:
代码如下 复制代码
mysqlbinlog --rewrite-db='wubx->re_wubx' --start-position=4 --stop-position=633 mysql-bin.000004 |mysql -S /tmp/mysql.sock re_wubx
恢复结果如下:
代码如下 复制代码
mysql -S /tmp/mysql.sock re_wubx;
mysql>SELECTCOUNT(*)FROM tb_wubx;
+----------+|COUNT(*)|+----------+|3|+----------+1ROWINSET(0.02 sec)

mysql>SELECT*FROM tb_wubx;
+----+--------------+| id | name |+----+--------------+|1| 张三 ||2| 李四 ||3| 隔壁老王 |+----+--------------+3ROWSINSET(0.00 sec)

mysql>INSERTINTO tb_wubx(name)SELECT name FROM wubx.tb_wubx;
Query OK,1ROW affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0

mysql>RENAMETABLE wubx.tb_wubx TO wubx.bak_tb_wubx;
Query OK,0ROWS affected (0.04 sec)

mysql>RENAMETABLE re_wubx.tb_wubx TO wubx.tb_wubx;
Query OK,0ROWS affected (0.03 sec)

mysql>SELECT*FROM wubx.tb_wubx;
+----+--------------+| id | name |+----+--------------+|1| 张三 ||2| 李四 ||3| 隔壁老王 ||4| 老赵赵 |+----+--------------+4ROWSINSET(0.00 sec)
恢复完成。
想一想,如果我跳过那个truncate继续执行那些binlog会怎么样
总结:从这次数据丢失给删除之后得到一些感想了我们还是要经常对数据库进行备份了,这样可以保证我们的数据不给丢失了,同时也可以保证我们网站数据安全。

truncate 命令删除恢复的更多相关文章

  1. 【转】Linux 中清空或删除大文件内容的五种方法(truncate 命令清空文件)

    原文: http://www.jb51.net/article/100462.htm truncate -s 0 access.log -------------------------------- ...

  2. MySQL数据库有外键约束时使用truncate命令的办法

    MySQL数据库操作中,Delete与Truncate两个命令都可以删除一个数据表中的全部数据,使用办法分别是: DELETE FROM t_question TRUNCATE TABLE t_que ...

  3. Oracle数据库中truncate命令和delete命令的区别

    首先讲一下,truncate命令: 语法:TRUNCATE  TABLE  table; 表格里的数据被清空,存储空间被释放. 运行后会自动提交,包括之前其它未提交的会话,因而一旦清空无法回退. 只有 ...

  4. MySQL中的binlog相关命令和恢复技巧

    操作命令: 复制代码 代码如下: show binlog events in 'mysql-bin.000016' limit 10; reset master 删除所有的二进制日志 flush lo ...

  5. 使用mysqldump命令备份恢复MySQL数据库

    1.各种用法说明 A. 最简单的用法: mysqldump -uroot -pPassword [database name] > [dump file] 上述命令将指定数据库备份到某dump文 ...

  6. 如何将Linux rm命令删除的文件放入垃圾箱

    因为rm命令删除的文件是不会放入垃圾箱的,所以无法恢复,下面小编就给大家介绍一种方法,通过替换Linux rm命令的方法,从而将rm命令删除的文件放入垃圾箱. 方法: 1. 在/home/userna ...

  7. 误删tree命令如何恢复

    误删tree命令如何恢复 考察rpm,yum的用法 一.删除tree命令,tree命令不可用 [root@centos7 ~]# which tree /usr/bin/tree [root@cent ...

  8. Linux操作系统启动故障排错之"/sbin/init"文件被删除恢复案例

    Linux操作系统启动故障排错之"/sbin/init"文件被删除恢复案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.删除"/sbin/ini ...

  9. Linux操作系统启动故障排错之"/etc/fstab"文件被删除恢复案例

    Linux操作系统启动故障排错之"/etc/fstab"文件被删除恢复案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.模拟故障 [root@yinzhe ...

随机推荐

  1. OpenStack G版以后的Availability Zone与Aggregate Hosts

    关于Availability Zone与Aggregate Hosts的概念解析,可以参考这篇文章:http://blog.chinaunix.net/uid-20940095-id-3875022. ...

  2. centos平台openstack spice配置

    配置过程只涉及控制节点(192.168.209.11)和计算节点(192.168.209.31),根据情况修改为实际环境的IP地址.     修改控制节点 安装软件包 yum install spic ...

  3. CentOS系统cobbler完全部署及案例测试

    本篇内容注主要涉及cobbler架构快速搭建,Cobbler命令行语法简单应用,Cobbler-WEB,system-config-kickStart基于Windows界面配置生成ks脚本模板,ks简 ...

  4. linux驱动开发之GCC问题

    最近正在学习驱动开发,进展到字符设备驱动开发阶段. 先不多说,首先把刚看的一篇学习驱动步骤的帖子记录如下: 1. 学会写简单的makefile 2. 编一应用程序,可以用makefile跑起来 3. ...

  5. 362. Design Hit Counter

    这个傻逼题..我没弄明白 you may assume that calls are being made to the system in chronological order (ie, the ...

  6. 有关Transaction not successfully started问题解决的方法

    我的项目配置:struts2+hibernate3.3+spring3.2.5 主要问题:在进行更新和提交操作时出现下面异常 org.springframework.transaction.Trans ...

  7. UVA 10465 Homer Simpson(dp + 完全背包)

    Problem C: Homer Simpson Time Limit: 3 seconds Memory Limit: 32 MB Homer Simpson, a very smart guy, ...

  8. linux下的僵尸进程处理SIGCHLD信号

    什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打开的文件等,但内核为每一个终止子进程保存了一定量的信息.这些信息至少包括进程ID,进程的终止状态,以及该 ...

  9. hdu 4622 Reincarnation(后缀数组)

    hdu 4622 Reincarnation 题意:还是比较容易理解,给出一个字符串,最长2000,q个询问,每次询问[l,r]区间内有多少个不同的字串. (为了与论文解释统一,这里解题思路里sa数组 ...

  10. 11.1 morning

    完美的序列(sequence)Time Limit:1000ms Memory Limit:64MB题目描述LYK 认为一个完美的序列要满足这样的条件:对于任意两个位置上的数都不相同.然而并不是所有的 ...