すっかりお正月ムードに突入しましたね、皆様いかがお過ごしでしょうか。
前回残してしまった、ディスク障害の検証を続けます。
ご報告まで、TiDBコミュニティに2点質問していました
質問1 INSERT文を実行した場合、データをメモリに保持せず即座にSSTファイルに書き込む方法はありますか。
回答は、NOでした。
但し、TiDB Lightningというツールが存在し、SQLファイルを直接SSTファイルに変換し、TiKVに投入できるとか。
質問2 SSTファイルが破損した場合、自動的にスナップショットなどから復旧する機能はありますか。
回答は、NOでした。
が、破損したSSTファイル情報を出力し(コマンドがあるみたいです)、強制的に破損SSTファイルをオフラインにするか、IGNOREフラグを立ててくださいとのことでした。
ちなみに、破損したSSTファイルをそのまま放置したら、TiKVプロセスがクラッシュする可能性があるようです。
破損ファイルに早く気付き、取り除いた方がよさそうです。
SSTファイルを壊し、破損したSSTを見つけてくれるかやってみます
tikv-ctl bad-sstsコマンドが使えるようですが、
必ずTiKVインスタンスを止めてから実行してくださいとのことです。
TiKVノードにアクセスし、tikv-ctlコマンドを使ってみます
二つのモードが使えるようです。
リモートモード
ネットワーク経由の接続でして、まずはkubectl port-forwardコマンドを用いてローカルからTiKVノードへの接続を確立しておく必要があります。
TiKV Pod名を確認します、basic-tikv-0になっています
$ kubectl get pods -n tidb-cluster
NAME READY STATUS RESTARTS AGE
basic-discovery-f699b74cd-mpgw4 1/1 Running 1 22h
basic-monitor-0 3/3 Running 3 22h
basic-pd-0 1/1 Running 1 22h
basic-tidb-0 2/2 Running 2 22h
basic-tikv-0 1/1 Running 1 22h
ポートフォワードを設定します
$ kubectl port-forward -n tidb-cluster basic-tikv-0 20160:20160 &>/tmp/portforward-tikv.log &
ローカルからポート番号20160を経由し、TiKVノードにアクセスし、tikv-ctlコマンド実行できます。
$ tikv-ctl --host 127.0.0.1:20160 ${subcommands}
ローカルモード
流れとしては、診断モードに入り、TiKVインスタンスの自動再起動をオフに変更、TiKVプロセスを停止、対象となるTiKV Podにログインしたら、tikv-ctlコマンドを使って操作可能です。
1. 診断モードに切り替え
$ kubectl annotate pod basic-tikv-0 -n tidb-cluster runmode=debug
pod/basic-tikv-0 annotated
2. TiKV processを停止
$ kubectl exec basic-tikv-0 -n tidb-cluster -c tikv -- kill -s TERM 1
3. TiKVコンテナが再起動できたらログイン
$ kubectl exec -it basic-tikv-0 -n tidb-cluster -- sh
4. tikv-ctlを実行
TiKVコンテナ内でデフォルトのdbパスは/var/lib/tikv/db
のようです。
$ ./tikv-ctl --data-dir /var/lib/tikv size -r 2
今回は、ローカルモードを使用します。
SSTファイルの先頭部を覗いてみます
SSTファイルが格納されてディレクトリに移動します。
/ # cd /var/lib/tikv/db
var/lib/tikv/db # ls -l *.sst
-rw-r--r-- 1 root root 568123 Dec 21 23:49 000012.sst
-rw-r--r-- 1 root root 150661 Dec 21 23:49 000015.sst
-rw-r--r-- 1 root root 1220 Dec 22 01:55 000022.sst
-rw-r--r-- 1 root root 25141 Dec 22 01:55 000023.sst
-rw-r--r-- 1 root root 3377 Dec 22 01:55 000028.sst
odコマンドで、000012.sstの先頭200バイトを覗いてみます。
/var/lib/tikv/db # od -N200 -c 000012.sst
0000000 \0 \n \f 001 001 001 001 \0 \0 \0 \0 \0 \0 \b 252 206
0000020 345 276 224 357 314 340 a 020 001 001 \t \0 002 \0 005 \0
0000040 \0 \0 \0 \0 \0 \0 > 364 \a z m D B : 1 \0
0000060 \0 \0 377 \0 373 \0 \0 \0 \0 \0 \0 377 \0 h T a
0000100 b l e : 377 5 3 377 \0 \0 \0 \0 \0 377 \0 \0
0000120 \0 367 \0 \0 \0 \0 373 372 \b 222 337 324 357 377 376 001
0000140 j 030 \0 \0 \0 \0 \0 { " i d " : 5 3 ,
0000160 " n a m e " : { " O " : " t e s
0000200 t " , " L " : " t e s t " } , "
0000220 c h a r s e t " : " u t f 8 m b
0000240 4 " , " c o l l a t e " : " u t
0000260 f 8 m b 4 _ b i n " , " c o l s
0000300 " : [ { " i d "
0000310
4行目の末尾ぐらいに、hTableの文字列が見え、そのあと、
"id":53,
"name":{"O":"test",...
のようにテーブルのスキーマ定義らしき内容が。
id 53?なんだろう。
別端末から、TiDBに接続しtestテーブルのスキーマ定義を確認
TiDBサービス名を確認します。
$ kubectl get svc -n tidb-cluster
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
basic-discovery ClusterIP 10.96.222.171 <none> 10261/TCP,10262/TCP 26h
basic-grafana ClusterIP 10.96.87.28 <none> 3000/TCP 26h
basic-monitor-reloader ClusterIP 10.96.209.73 <none> 9089/TCP 26h
basic-pd ClusterIP 10.96.149.28 <none> 2379/TCP 26h
basic-pd-peer ClusterIP None <none> 2380/TCP 26h
basic-prometheus ClusterIP 10.96.205.157 <none> 9090/TCP 26h
basic-tidb ClusterIP 10.96.162.173 <none> 4000/TCP,10080/TCP 26h
basic-tidb-peer ClusterIP None <none> 10080/TCP 26h
basic-tikv-peer ClusterIP None <none> 20160/TCP 26h
ローカルからTiDBへ接続するため、ポートフォワードを設定し、mysqlコマンドで接続します。
$ kubectl port-forward -n tidb-cluster svc/basic-tidb 4000 > pf4000.out &
$ mysql -h 127.0.0.1 -P 4000 -u root
testテーブルのスキーマ定義を確認すると、tidb_table_idが53でした。
mysql> use information_schema;
Database changed
mysql> select tidb_table_id,table_name from tables where table_name='test';
+---------------+------------+
| tidb_table_id | table_name |
+---------------+------------+
| 53 | test |
+---------------+------------+
1 row in set (0.04 sec)
SSTファイルを壊します
TiKVノードにログインしていた端末に戻ります。
ddコマンドで000012.sstの先頭部分を0で上書きします
/var/lib/tikv/db # dd if=/dev/zero of=/var/lib/tikv/db/000012.sst bs=512 count=1
破損されたSSTファイルを検知できるか
tikv-ctl bad-sstsコマンドを以下のパラメータを指定し、実行します。
--dbパラメータ、dbパスを指定
--pdパラメータ、PDサービスのCLUSTER-IPを指定(kubectl get svc -n tidb-cluster
コマンドで確認したbasic-pdサービス)。
/var/lib/tikv/db # /tikv-ctl bad-ssts --db /var/lib/tikv/db --pd 10.96.149.28:2379
... ...
--------------------------------------------------------
corruption info:
/var/lib/tikv/db/000012.sst: Corruption: Bad table magic number: expected 9863518390377041911, found 0 in /var/lib/tikv/db/000012.sst
sst meta:
12:568123[1 .. 6281]['0101' seq:1, type:1 .. '7A7480000000000000FF0F5F728000000000FF0000870000000000FAFA0895315D0FFFFA' seq:2394, type:1] at level 0 for Column family "default" (ID 0)
it isn't easy to handle local data, start key:0101
overlap region:
RegionInfo { region: id: 2001 end_key: 7480000000000000FF0500000000000000F8 region_epoch { conf_ver: 1 version: 2 } peers { id: 2002 store_id: 1 }, leader: Some(id: 2002 store_id: 1) }
RegionInfo { region: id: 2003 start_key: 7480000000000000FF0500000000000000F8 end_key: 7480000000000000FF0700000000000000F8 region_epoch { conf_ver: 1 version: 3 } peers { id: 2004 store_id: 1 }, leader: Some(id: 2004 store_id: 1) }
RegionInfo { region: id: 2005 start_key: 7480000000000000FF0700000000000000F8 end_key: 7480000000000000FF0900000000000000F8 region_epoch { conf_ver: 1 version: 4 } peers { id: 2006 store_id: 1 }, leader: Some(id: 2006 store_id: 1) }
RegionInfo { region: id: 2007 start_key: 7480000000000000FF0900000000000000F8 end_key: 7480000000000000FF0B00000000000000F8 region_epoch { conf_ver: 1 version: 5 } peers { id: 2008 store_id: 1 }, leader: Some(id: 2008 store_id: 1) }
RegionInfo { region: id: 2009 start_key: 7480000000000000FF0B00000000000000F8 end_key: 7480000000000000FF0D00000000000000F8 region_epoch { conf_ver: 1 version: 6 } peers { id: 2010 store_id: 1 }, leader: Some(id: 2010 store_id: 1) }
RegionInfo { region: id: 2011 start_key: 7480000000000000FF0D00000000000000F8 end_key: 7480000000000000FF0F00000000000000F8 region_epoch { conf_ver: 1 version: 7 } peers { id: 2012 store_id: 1 }, leader: Some(id: 2012 store_id: 1) }
RegionInfo { region: id: 2013 start_key: 7480000000000000FF0F00000000000000F8 end_key: 7480000000000000FF1100000000000000F8 region_epoch { conf_ver: 1 version: 8 } peers { id: 2014 store_id: 1 }, leader: Some(id: 2014 store_id: 1) }
suggested operations:
tikv-ctl ldb --db=/var/lib/tikv/db unsafe_remove_sst_file "/var/lib/tikv/db/000012.sst"
tikv-ctl --db=/var/lib/tikv/db tombstone -r 2001 --pd <endpoint>
tikv-ctl --db=/var/lib/tikv/db tombstone -r 2003 --pd <endpoint>
tikv-ctl --db=/var/lib/tikv/db tombstone -r 2005 --pd <endpoint>
tikv-ctl --db=/var/lib/tikv/db tombstone -r 2007 --pd <endpoint>
tikv-ctl --db=/var/lib/tikv/db tombstone -r 2009 --pd <endpoint>
tikv-ctl --db=/var/lib/tikv/db tombstone -r 2011 --pd <endpoint>
tikv-ctl --db=/var/lib/tikv/db tombstone -r 2013 --pd <endpoint>
--------------------------------------------------------
corruption analysis has completed
破損した000012.sstが見事に検知されたようです。
破損原因と対処法まで親切にコマンドベースで提示してくれています。
終わりに
ディスク障害によりSSTファイルが破損した、といったシナリオで検証してみました。
自動復旧まではいかないものの、早いうちに破損ファイルを検知、対策を打つことはできそうです。
次回は、個人的に一番やってみたかった、TiDBの分散トランザクション検証を予定しております。
お楽しみに。