Closed12
[TiDB] うっかり消してしまったデータを取り戻す方法

TiDBはMVCCの仕組みを流用して、過去データを取得できるFlashbackやAS OF TIMESTAMPという技がある。これでどのようなケースのリカバリができるのか調べてみた。

まずはGCの期間を伸ばす。MVCCのヒストリは定期的に削除されており、そのインターバルは下記変数でグローバルに設定できる。
mysql> set global tidb_gc_life_time=3h;
Query OK, 0 rows affected (0.01 sec)

レコードを消してみる
mysql> delete from employees where emp_no > 499000;
Query OK, 999 rows affected (0.18 sec)
mysql> select count(*) from employees;
+----------+
| count(*) |
+----------+
| 299025 |
+----------+
1 row in set (0.11 sec)

AS OF TIMESTAMP で、削除前のレコードを出力できる。
mysql> select count(*) from employees as of timestamp now() - interval 10 minute;
+----------+
| count(*) |
+----------+
| 300024 |
+----------+
1 row in set (0.09 sec)

古いテーブルからINSERTするのは駄目。
mysql> INSERT INTO employees SELECT * FROM employees as of timestamp now() - interval 10 minute;
ERROR 8135 (HY000): can not set different time in the as of

CREATE TABLE ... SELECTは未実装
mysql> CREATE TABLE employees2 SELECT * FROM employees as of timestamp now() - interval 10 minute;
ERROR 1105 (HY000): 'CREATE TABLE ... SELECT' is not implemented yet

コピー作っていれるも
mysql> CREATE TABLE employees2 LIKE employees;
Query OK, 0 rows affected (0.07 sec)
mysql> insert into employees2 SELECT * FROM employees as of timestamp now() - interval 10 minute;
ERROR 8135 (HY000): can not set different time in the as of
なんでよ
これか

そもそも過去データをINSERTすることができないようだ。
mysql> set @@tidb_snapshot=now() - interval 20 minute;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@tidb_snapshot;
+---------------------+
| @@tidb_snapshot |
+---------------------+
| 2024-12-23 14:13:08 |
+---------------------+
1 row in set (0.00 sec)
mysql> insert into employees2 SELECT * FROM employees;
ERROR 1146 (42S02): Table 'employees.employees2' doesn't exist
-- その時には存在しなかったから
mysql> CREATE TABLE employees2 LIKE employees;
ERROR 1105 (HY000): can not execute write statement when 'tidb_snapshot' is set
ドキュメントにもOUTFILEで出力してLOAD DATAしろと書いてあった

SELECT ... INTO OUTFILE は、サーバに出力するものでローカルに出力するものではない。
TiDB Cloudでもサポートしないって書いてあった

結局dumplingしかなさそう。
tiup dumpling --snapshot "2024-12-23 14:13:08" -u root -P 4000 -h 127.0.0.1 --filetype sql -t 8 -o snapshot -r 200000 -F 256MiB
ただdumplingだとINSERTでduplicate keyエラーが大量に発生するので、INSERT IGNOREにしておく。
sed -ie 's/INSERT/INSERT IGNORE/g' employees.employees.0000000010000.sql
これで上手く行くが、スマートじゃないな。。。
Query OK, 999 rows affected, 11165 warnings (0.16 sec)
Records: 12164 Duplicates: 11165 Warnings: 11165
mysql> select count(*) from employees;
+----------+
| count(*) |
+----------+
| 300024 |
+----------+
1 row in set (0.09 sec)

lightningを使ってみる。ignoreオプションは名前に反して重複エラーをカウントするので途中で中断してしまう。何も考えずにいれるならreplace、もしくはDBごとdropしてしまって全量入れ替えるのが良さそう。
mysql> select count(*) from employees;
+----------+
| count(*) |
+----------+
| 299025 |
+----------+
1 row in set (0.09 sec)
tiup tidb-lightning -config tidb-lightning.toml
mysql> select count(*) from employees;
+----------+
| count(*) |
+----------+
| 300024 |
+----------+
1 row in set (0.10 sec)

tidb-lightning.toml
[lightning]
# Logging
level = "info"
file = "tidb-lightning.log"
[conflict]
strategy = "replace"
[tikv-importer]
# Configure the import mode
backend = "tidb"
[mydumper]
# Local source data directory
data-source-dir = "snapshot"
[tidb]
# Information of the target cluster
host = "127.0.0.1"
port = 4000
user = "root"
password = ""
このスクラップは4ヶ月前にクローズされました
ログインするとコメントできます