Zenn
Closed12

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

bohnenbohnen

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

bohnenbohnen

まずはGCの期間を伸ばす。MVCCのヒストリは定期的に削除されており、そのインターバルは下記変数でグローバルに設定できる。

mysql> set global tidb_gc_life_time=3h;
Query OK, 0 rows affected (0.01 sec)
bohnenbohnen

レコードを消してみる

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)
bohnenbohnen

AS OF TIMESTAMP で、削除前のレコードを出力できる。

mysql> select count(*) from employees as of timestamp now() - interval 10 minute;
+----------+
| count(*) |
+----------+
|   300024 |
+----------+
1 row in set (0.09 sec)
bohnenbohnen

古いテーブルから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
bohnenbohnen

コピー作っていれるも

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

なんでよ

https://github.com/pingcap/tidb/issues/18672

これか

bohnenbohnen

そもそも過去データを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しろと書いてあった
https://docs.pingcap.com/ja/tidb/stable/read-historical-data

bohnenbohnen

結局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)
bohnenbohnen

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)
bohnenbohnen

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ヶ月前にクローズされました
ログインするとコメントできます