TiDB 误删数据后的常见应急措施

Tiit 772 2024-03-14

背景

在 DBA 的日常工作中,误删除数据是一种常见但令人头疼的问题。作为数据库管理员,DBA 承担着维护数据库完整性和安全性的责任。误删测试数据可能造成项目延期,影响测试,重复工作,误删生产数据可能导致业务中断,客户数据丢失,导致公司面临法律风险。一旦发生误删除,DBA 需要迅速应对,本文主要介绍在 TiDB 数据库中,误删数据后的常见应急措施。

常见场景

  1. drop database 误删除数据库

  2. truncate table 误清空表

  3. drop table 误删除表

  4. delete、update 误删除/更新数据

恢复方法

应急操作

TiDB 的事务的实现采用了 MVCC(多版本并发控制)机制,当新写入的数据覆盖旧的数据时,旧的数据不会被替换掉,而是与新写入的数据同时保留,并以时间戳来区分版本。TiDB 通过定期 GC 的机制来清理不再需要的旧数据。因此,GC 没有过期是我们进行数据恢复的基础。

在生产环境中,可以通过适当设置垃圾收集(GC)参数来应对误删除场景,但同时也需要考虑历史版本过多可能引起的性能和容量上的开销。

当出现误删除数据情况时,应在第一时间调整 GC 相关参数,增加 GC 保留时长,操作方法如下:

# 查看gc参数配置show variables like '%tidb_gc_life_time%';# 调整gc参数配置set global tidb_gc_life_time='48h';

drop database 误删除数据库恢复(TiDB v6.4之前)

确定误操作时间,可以通过 admin show ddl jobs 语句确认误操作时间

MySQL [test]> admin show ddl jobs;+--------+---------+------------+---------------+--------------+-----------+----------+-----------+---------------------+---------------------+--------+| JOB_ID | DB_NAME | TABLE_NAME | JOB_TYPE      | SCHEMA_STATE | SCHEMA_ID | TABLE_ID | ROW_COUNT | START_TIME          | END_TIME            | STATE  |+--------+---------+------------+---------------+--------------+-----------+----------+-----------+---------------------+---------------------+--------+|    116 | test1   |            | drop schema   | queueing     |       102 |        0 |         0 | 2024-03-07 12:59:56 | 2024-03-07 12:59:56 | synced ||    115 | test1   | t2         | add index     | public       |       102 |      112 |     10000 | 2024-03-07 12:41:29 | 2024-03-07 12:41:33 | synced ||    114 | test1   | t1         | add index     | public       |       102 |      110 |     10000 | 2024-03-07 12:41:23 | 2024-03-07 12:41:27 | synced ||    113 | test1   | t2         | create table  | public       |       102 |      112 |         0 | 2024-03-07 12:41:21 | 2024-03-07 12:41:21 | synced ||    111 | test1   | t1         | create table  | public       |       102 |      110 |         0 | 2024-03-07 12:41:21 | 2024-03-07 12:41:21 | synced ||    109 | test    | t2         | add index     | public       |         1 |      106 |     10000 | 2024-03-07 12:40:47 | 2024-03-07 12:40:51 | synced ||    108 | test    | t1         | add index     | public       |         1 |      104 |     10000 | 2024-03-07 12:40:41 | 2024-03-07 12:40:45 | synced ||    107 | test    | t2         | create table  | public       |         1 |      106 |         0 | 2024-03-07 12:40:39 | 2024-03-07 12:40:40 | synced ||    105 | test    | t1         | create table  | public       |         1 |      104 |         0 | 2024-03-07 12:40:38 | 2024-03-07 12:40:38 | synced ||    103 | test1   |            | create schema | public       |       102 |        0 |         0 | 2024-03-07 12:35:14 | 2024-03-07 12:35:14 | synced |+--------+---------+------------+---------------+--------------+-----------+----------+-----------+---------------------+---------------------+--------+10 rows in set (0.73 sec)

或通过 TiDB Dashboard 日志搜索功能确认误操作时间

确认下删除时间没超过 GC 时间,即下面SQL查询出来的 tikv_gc_safe_point 小于数据删除时间

MySQL [test1]> SELECT * FROM mysql.tidb WHERE variable_name = 'tikv_gc_safe_point';+--------------------+-----------------------------+--------------------------------------------------------------+| VARIABLE_NAME      | VARIABLE_VALUE              | COMMENT                                                      |+--------------------+-----------------------------+--------------------------------------------------------------+| tikv_gc_safe_point | 20240307-13:28:51.993 +0800 | All versions after safe point can be accessed. (DO NOT EDIT) |+--------------------+-----------------------------+--------------------------------------------------------------+1 row in set (0.01 sec)

使用 SQL 确认下删除时间。

MySQL [test]> set session tidb_snapshot='2024-03-07 12:59:56';Query OK, 0 rows affected (0.00 sec)MySQL [test]> show databases;+--------------------+| Database           |+--------------------+| INFORMATION_SCHEMA || METRICS_SCHEMA     || PERFORMANCE_SCHEMA || mysql              || test               || test1              || tpcc               |+--------------------+7 rows in set (0.00 sec)MySQL [test]> set session tidb_snapshot='2024-03-07 12:59:57';Query OK, 0 rows affected (0.00 sec)MySQL [test]> show databases;+--------------------+| Database           |+--------------------+| INFORMATION_SCHEMA || METRICS_SCHEMA     || PERFORMANCE_SCHEMA || mysql              || test               || tpcc               |+--------------------+6 rows in set (0.01 sec)

使用 dumpling 导出要保留的数据

tiup dumpling -uroot  -h192.168.0.1 -P4000 -B test1 --filetype sql -t 4 -F 256MiB -o ./dump_test1 -L ./dump_test1.log --snapshot "2024-03-07 12:59:56"

使用 lighting 导出要保留的数据

tiup tidb-lightning -backend tidb -d ./dump_test1 -tidb-host 192.168.0.1 -tidb-password "" -tidb-port 4000 -tidb-user root

数据恢复完成

DROP DATABASE 误删除数据库恢复(TiDB v6.4之后)

从 TiDB v6.4 版本开始,TiDB 引入了 FLASHBACKUP DATABASE 语法,该语法允许快速恢复误删除的数据库,无需再确认误操作时间,极大地加快了误删除数据库恢复的速度。值得注意的是,该功能同样依赖于 GC(垃圾收集)机制。

MySQL [(none)]> flashback database test1;Query OK, 0 rows affected (0.31 sec)MySQL [(none)]> show databases;+--------------------+| Database           |+--------------------+| INFORMATION_SCHEMA || METRICS_SCHEMA     || PERFORMANCE_SCHEMA || mysql              || result             || test               || test1              || tpcc               |+--------------------+8 rows in set (0.00 sec)MySQL [(none)]> use test1;Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -ADatabase changed
MySQL [test1]> show tables;+-----------------+| Tables_in_test1 |+-----------------+| t1              || t2              |+-----------------+2 rows in set (0.00 sec)

TRUNCATE TABLE 误清空表

使用 FLASHBACK TABLE 语句可以快速恢复误清空表导致的数据丢失。值得注意的是,该语句仅能恢复上一次 TRUNCATE 操作丢失的数据。如果需要恢复多次 TRUNCATE 操作前的数据,可以按照 TiDB v6.4 之前版本的drop database误删除库的恢复操作进行处理。值得注意的是,该功能同样依赖于 GC(垃圾收集)机制。

MySQL [test1]> truncate table t1;Query OK, 0 rows affected (0.52 sec)MySQL [test1]> select count(1) from t1;+----------+| count(1) |+----------+|        0 |+----------+1 row in set (0.00 sec)MySQL [test1]> insert into t1 select * from t2 limit 3;Query OK, 3 rows affected (0.02 sec)Records: 3  Duplicates: 0  Warnings: 0MySQL [test1]> select * from t1;+------+------------+------------+------------+| id   | col1       | col2       | col3       |+------+------------+------------+------------+|    1 | 0f74fa3c18 | 66b149a20e | 0e1e7bf8c8 ||    2 | f0f976f0d3 | 75fc7f6174 | d562074867 ||    3 | 579cfa1074 | 1d74595138 | e9220d8e86 |+------+------------+------------+------------+3 rows in set (0.00 sec)MySQL [test1]> flashback table t1;ERROR 1050 (42S01): Table 't1' already existsMySQL [test1]> flashback table t1 to t1_old;Query OK, 0 rows affected (2.03 sec)MySQL [test1]> select count(1) from t1_old;+----------+| count(1) |+----------+|    10000 |+----------+1 row in set (0.01 sec)

DROP TABLE 误删除表

DROP TABLE 误删除表与 TRUNCATE TABLE 误清空数据的处理方式类似,这里就不再赘述。

DELETE、UPDATE 误删除/更新数据

DELETE、UPDATE 误删除/更新数据与 TiDB v6.4 版本前的 DROP DATABASE 误删除库处理方式相似,只不过在确认误操作时间上相对困难。以下是确定误操作时间的可能思路:

  • TiDB 慢查询日志:如果 DELETE 或 UPDATE 的 SQL 执行时长超过慢查询日志阈值,相关信息将被记录在慢查询日志中。

  • 审计日志:包括 TiDB 审计日志、堡垒机审计、第三方数据库审计软件等。通过审计日志可以追踪到数据库操作的详细信息,包括误删除或误更新的时间戳。

  • 误操作人员的时间描述:误操作人员提供的关于误操作发生时间的描述。虽然这种方式相对主观,但可能有助于缩小确认误操作时间的范围。

通过以上信息,结合 TiDB 提供的 tidb_snapshot 功能,可以进一步确定误操作的确切时间,为后续数据的准确恢复提供基础。

总结建议

总结:TiDB 数据库针对数据库误删除的场景处理方式还是很友好的,多数场景下都能比较快速的找回数据。但恢复比较依赖 GC 机制,如果超过了 GC 的时长,就是能使用备份对误删除的数据进行恢复了。

建议:如果tidb_snapshot功能下能够支持将查询出来的数据insert into/import into到另一张表,那样误删除/更新数据场景下的恢复速度就更快了。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:TiDB Binlog功能使用实践指南
下一篇:TiDB MVCC机制问题定位与处理
相关文章