TiDB Binlog的增量恢復
本文作者為 運維保障中心-王寧
1.TiDB Binlog介紹
2. TiDB Binlog架構與原理
3.叢集擴容Drainer
3.1 編輯drainer的配置檔案
3.2 執行擴容命令
3.3 檢查叢集狀態
3.4 檢查binlog目錄下是否有binlog檔案
4.Reparo解析TiDB binlog
4.1 安裝Reparo
4.2 編輯reparo配置檔案
4.3 啟動reparo
4.4 檢視解析文字
5.實驗利用全備+Binlog恢復資料
5.1 獲取備份中的TSO
5.2 到備用環境進行恢復
5.3 編輯reparo配置檔案
5.4 啟動reparo
5.5 找到恢復TSO點
5.6 在備用Tidb環境編輯reparo source配置檔案
5.7 啟動reparo source
背景:作為DBA最關心的就是資料的安全,在最初使用TiDB的時候,就考慮到萬一資料有誤操作或者其他危險狀況,我們應該怎麼來恢復資料,保障TiDB的資料像MySQL資料庫一樣可以恢復到任意時間點。TiDB的Binlog就是一個類似MySQL Binlog的工具,既可以進行資料同步,又可以儲存成檔案。大部分DBA可能都使用過它的資料同步功能,但是TiDB的binlog儲存成檔案這樣才能保障我們的資料安全。這篇文章主要涉及的就是將TiDB的binlog儲存下來,並且使用TiDB的Reparo工具進行解析及恢復資料。
0 1
TiDB Binlog介紹
TiDB Binlog工具可以收集TiDB資料庫的日誌binlog,並且提供資料同步和準實時備份的功能。
(一)TiDB Binlog支援以下功能場景:
資料同步:同步TiDB叢集資料到其他資料庫
實時備份和恢復:備份TiDB叢集資料,同時可以用於 TiDB 叢集故障時恢復。
(二)TiDB資料庫的Binlog格式:
1.與MySQL Binlog的Row格式類似,按照事務提交的時間記錄的,只記錄增刪改,只記錄提交的事務。
2.以每一行資料的變更為最小單位進行記錄。
3.只有被提交的事務才會被記錄,且記錄的是完整事務。
(1)在Binlog中會記錄主鍵和開始的時間戳。
(2)在Binlog中會記錄提交的時間戳。
0 2
TiDB Binlog架構與原理
TiDB Binlog 叢集由 Pump 和 Drainer 兩個元件組成。一個 Pump叢集中有若干個 Pump 節點。TiDB 例項連線到各個 Pump節點併發送 binlog 資料到 Pump 節點。Pump叢集連線到 Drainer節點,Drainer將接收到的更新資料轉換到某個特定下游(例如 Kafka、另一個 TiDB 叢集或 MySQL 或 MariaDB Server或者是直接儲存日誌)指定的正確格式。
Pump:Pump用於實時記錄 TiDB 產生的 Binlog,並將 Binlog 按照事務的提交時間進行排序,再提供給 Drainer 進行消費。Pump 的叢集架構能確保 TiDB 或 Pump 叢集中有新的例項加入或退出時更新資料不會丟失。
Drainer:Drainer 從各個 Pump 中收集 Binlog 進行歸併,再將 Binlog 轉化成 SQL或者指定格式的資料,最終同步到下游。
03
叢集擴容Drainer節點儲存日誌
(一)編輯drainer的配置檔案
式
的資料,再寫入到本地檔案中。
#編輯擴容的配置檔案
cd /home/tidb/scale_task
vim scale_out_drainer.yaml
#儲存為本地檔案
drainer_servers:
- host: 10.***.***.8
# drainer meta data directory path
data_dir: "/data1/tidb-data/drainer-8249"
deploy_dir: "/data1/tidb-deploy/drainer-8249"
log_dir: "/data1/tidb-deploy/drainer-8249/log"
config:
syncer.db-type: "file"
# directory to save binlog file,
# default same as data-dir(save checkpoint file) if this is not configured.
# syncer.to.dir: "/path/to/save/binlog"
syncer.to.dir: "/data1/tidb-data/drainer-8249/binlog"
#擴容drainer節點之前,需要檢查如下配置是否新增開啟
tiup cluster edit-config <cluster-name>
server_configs:
tidb:
binlog.enable: true
binlog.ignore-error: true
pump_servers:
- host: 10.***.***.1
ssh_port: 22
port: 8250
deploy_dir: /data1/tidb-deploy/pump-8249
data_dir: /data1/tidb-data/pump-8249
log_dir: /data1/tidb-deploy/pump-8249/log
config:
gc: 14
arch: amd64
os: linux
(二)執行擴容命令
tiup cluster scale-out <cluster-name> scale_out_drainer.yaml --user tidb -p
(三)檢查叢集狀態
tiup cluster display <cluster-name>
(四)檢查binlog目錄下是否有binlog檔案
$$ cd /data1/tidb-data/drainer-8249/binlog
$ ll -h
總用量 525M
-rw-------. 1 tidb tidb 513M 7月 13 15:46 binlog-0000000000000000-20220713110333
-rw-------. 1 tidb tidb 13M 7月 13 15:53 binlog-0000000000000001-20220713154625
04
Reparo解析TiDB binlog
如果 TiDB Binlog 用於增量恢復,可以設定配置項 db-type="file",Drainer 會將 binlog 轉化為指定的 proto buffer格式的資料,再寫入到本地檔案中。這樣就可以使用 Reparo 恢復增量資料。
Reparo 是 TiDB Binlog 的一個配套工具,用於增量的恢復。使用 TiDB Binlog 中的 Drainer 將 binlog 按照 protobuf格式輸出到檔案,通過這種方式來備份增量資料。當需要恢復增量資料時,使用 Reparo 解析檔案中的 binlog,並將其應用到 TiDB/MySQL 中。
(一)安裝Reparo
#在drainer所在的伺服器上安裝
su - tidb
wget http://download.pingcap.org/tidb-binlog-cluster-latest-linux-amd64.tar.gz
tar -xvf tidb-binlog-cluster-latest-linux-amd64.tar.gz
mv tidb-binlog-cluster-latest-linux-amd64 tidb-binlog-cluster
cd /home/tidb/tidb-binlog-cluster/bin
$ ll -h
總用量 204M
-rwxr-xr-x 1 tidb tidb 47M 3月 3 2020 arbiter
-rwxr-xr-x 1 tidb tidb 23M 3月 3 2020 binlogctl
-rwxr-xr-x 1 tidb tidb 50M 3月 3 2020 drainer
-rwxr-xr-x 1 tidb tidb 41M 3月 3 2020 pump
-rwxr-xr-x 1 tidb tidb 44M 3月 3 2020 reparo
(二)編輯reparo配置檔案
由於dest-type = "print"這個配置,此配置檔案只是將binlog解析成文字檔案,方便檢視。
cd /home/tidb
vim reparo.toml
#Drainer 輸出的 protobuf 格式 binlog 檔案的儲存路徑。
data-dir = "/data1/tidb-data/drainer-8249/binlog"
#日誌輸出資訊等級設定:debug, info, warn, error, fatal (預設值:info)。
log-level = "info"
#使用 start-datetime 和 stop-datetime 來選擇恢復指定時間範圍內的 binlog,
#格式為 “2006-01-02 15:04:05”。
start-datetime = "2022-07-27 16:42:00"
stop-datetime = "2022-07-27 16:51:00"
#start-tso、stop-tso 分別對應 start-datetime 和 stop-datetime,
#也是用於恢復指定時間範圍內的 binlog,用 tso 的值來設定。
#如果已經設定了 start-datetime 和 stop-datetime,
#就不需要再設定 start-tso 和 stop-tso。
#在從全量或者上次增量位置繼續同步時,start-tso 應當指定為全量 tso + 1
#或者上次增量的 stop-tso + 1
#start-tso = 0
#stop-tso = 0
#下游服務型別。 取值為 print, mysql(預設值:print)。
#當值為 print 時,只做解析列印到標準輸出,不執行 SQL;
#如果為 mysql,則需要在 [dest-db] 中配置 host、port、user、password 等資訊。
dest-type = "print"
#dest-type = "mysql"
#輸出到下游資料庫一個事務的 SQL 語句數量(預設 20)。
#txn-batch = 20
#同步下游的併發數,該值設定越高同步的吞吐效能越好(預設 16)。
#worker-count = 16
#安全模式配置。取值為 true 或 false(預設值:false)。
#當值為 true 時,Reparo 會將 update 語句拆分為 delete + replace 語句。
safe-mode = false
# replicate-do-db 和 replicate-do-table 用於指定恢復的庫和表,
# replicate-do-db 的優先順序高於 replicate-do-table。
# 支援使用正則表示式來配置,需要以 '~' 開始宣告使用正則表示式。
# 注:replicate-do-db 和 replicate-do-table 使用方式與 Drainer 的使用方式一致。
# replicate-do-db = ["~^b.*","s1"]
# [[replicate-do-table]]
# db-name ="test"
# tbl-name = "log"
# [[replicate-do-table]]
# db-name ="test"
# tbl-name = "~^a.*"
# 如果 dest-type 設定為 mysql, 需要配置 dest-db。
# [dest-db]
# host = "127.0.0.1"
# port = 3309
# user = "****"
# password = "*****"
(三)啟動reparo
#這樣啟動,內容會列印到binlog_parse.log這個日誌中
reparo -config /home/tidb/reparo.toml >/home/tidb/binlog_parse.log
(四)檢視解析文字
DDL及增刪改的解析文字如下:
[2022/07/27 16:53:55.748 +08:00] [INFO] [config.go:153] ["Parsed start TSO"] [ts=434873649070080000]
[2022/07/27 16:53:55.749 +08:00] [INFO] [config.go:160] ["Parsed stop TSO"] [ts=434873774899200000]
[2022/07/27 16:53:55.749 +08:00] [INFO] [version.go:50] ["Welcome to Reparo"] ["Release Version"=v4.0.0-beta.1-2-g20397869] ["Git Commit Hash"=20397869d35a5bc8a130f615ceb669322fa8600e] ["Build TS"="2020-03-02 09:50:53"] ["Go Version"=go1.13] ["Go OS/Arch"=linux/amd64]
[2022/07/27 16:53:55.768 +08:00] [INFO] [reparo.go:38] ["New Reparo"] [config="{\"data-dir\":\"/data1/tidb-data/drainer-8249/binlog\",\"start-datetime\":\"2022-07-27 16:42:00\",\"stop-datetime\":\"2022-07-27 16:50:00\",\"start-tso\":434873649070080000,\"stop-tso\":434873774899200000,\"txn-batch\":20,\"worker-count\":16,\"dest-type\":\"print\",\"dest-db\":null,\"replicate-do-table\":null,\"replicate-do-db\":null,\"replicate-ignore-table\":null,\"replicate-ignore-db\":null,\"log-file\":\"\",\"log-level\":\"info\",\"safe-mode\":false}"]
[2022/07/27 16:53:56.247 +08:00] [INFO] [file.go:77] ["after filter files"] [files="[/mysqldata/tidb-data/drainer-8249/binlog/binlog-0000000000000011-20220525054234]"] ["start tso"=434873649070080000] ["stop tso"=434873774899200000]
DDL query : use `wangn_test`; CREATE TABLE `t_random_t` (
`id` bigint(20) NOT NULL COMMENT 'id',
`code` varchar(30) NOT NULL,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
[2022/07/27 16:54:14.207 +08:00] [INFO] [reparo.go:83] ["sync binlog success"] [ts=434873689486917637] [datetime=2022/07/27 16:44:34.178 +08:00]
schema: wangn_test; table: t_random_t; type: Insert
id(bigint): 5577006791947779410
code(varchar): et impedit voluptatem et in fa
create_time(datetime): 2022-05-08 08:08:02
[2022/07/27 16:54:14.207 +08:00] [INFO] [reparo.go:83] ["sync binlog success"] [ts=434873731705208833] [datetime=2022/07/27 16:47:15.228 +08:00]
schema: wangn_test; table: t_random_t; type: Update
id(bigint): 1732098207891296284 => 1732098207891296284
code(varchar): consequuntur quasi error volup => error volup
create_time(datetime): 2022-04-18 18:06:04 => 2022-04-18 18:06:04
[2022/07/27 16:54:14.207 +08:00] [INFO] [reparo.go:83] ["sync binlog success"] [ts=434873750474719235] [datetime=2022/07/27 16:48:26.828 +08:00]
schema: wangn_test; table: t_random_t; type: Delete
id(bigint): 4045349876957839238
code(varchar): vel ut quia enim ut qui.
create_time(datetime): 2021-07-30 16:04:26
[2022/07/27 17:19:10.453 +08:00] [INFO] [reparo.go:83] ["sync binlog success"] [ts=434873755219525633] [datetime=2022/07/27 16:48:44.928 +08:00]
DDL query : use `wangn_test`; alter table t_random_t add column address varchar(30) NOT NULL;
[2022/07/27 17:19:10.455 +08:00] [INFO] [reparo.go:83] ["sync binlog success"] [ts=434873779376095235] [datetime=2022/07/27 16:50:17.078 +08:00]
[2022/07/27 17:19:10.455 +08:00] [INFO] [read.go:123] ["read file end"] [file=/data1/ti db-data/drainer-8249/bi nlog/binlog-0000000000000011-20220525054234]
05
實驗-利用全備+Binlog恢復資料
實驗背景:凌晨都會例行備份。一天的業務增刪改。某張表因操作失誤被delete掉了。需要恢復回來。
其實如果是MySQL資料庫的話,我們可以利用MySQL的binlog,使用工具,反向解析binlog,把delete語句解析成insert語句,但是目前TiDB的reparo這個工具並沒有這個功能。
在不考慮GC的情況下,我們只能用備份+TiDB的binlog進行恢復。
(一)獲取備份中的TSO
如果是br備份的話,從備份日誌中檢視
[BackupTS=433311088594911234]
或者可以使用 validate 指令獲取上一次備份的時間戳,示例如下:
br validate decode --field="end-version" \
-s local:///bak/data1/wangn/tidb_test/7120519| tail -n1
Detail BR log in /tmp/br.log.2022-05-19T18.15.34+0800
433311088594911234
(二)到備用環境進行恢復
安全恢復單表資料,利用全備及br工具將單表資料恢復出來, 恢復的時候,目標叢集內不能有相同庫名的庫,否則會報錯。
#恢復單表wangn_test.tt
br restore table --pd "10.***.***.104:2379" --db "wangn_test" --table "tt" \
--ratelimit 128 --storage "local:///bak/data1/wangn/tidb_test/7120519" \
--log-file /tmp/restorefull.log
(三)編輯reparo配置檔案
這個是要檢視誤操作之前的最後一個tso的, 先解析binlog成文字 ,找到操作的tso時間點 需要開發提供誤刪除的大概時間,庫,表等資訊
vim reparo.toml
data-dir = "/data1/tidb-data/drainer-8249/binlog"
log-level = "info"
start-datetime = "2022-05-19 20:24:00"
stop-datetime = "2022-05-19 20:30:00"
dest-type = "print"
safe-mode = false
db-name ="wangn_test"
tbl-name = "tt"
(四)啟動reparo
reparo -config /home/tidb/reparo.toml >/home/tidb/binlog_parse_0519.log
(五)找到恢復TSO點
less binlog_parse_0519.log
[2022/05/19 20:43:19.591 +08:00] [INFO] [reparo.go:83] ["sync binlog success"]
[ts=433314381739589634] [datetime=2022/05/19 20:26:27.178 +08:00]
schema: wangn_test; table: tt; type: Delete
從上面日誌中找到了Delete操作之前最後一個事務結束的時間點,ts=433314381739589634。
我們需要從全量或者上次增量位置繼續同步時,start-tso 應當指定為全量 tso + 1 或者上次增量的 stop-tso + 1,那麼現在我們就有了恢復的起始tso與結束tso。
起始tso:433311088594911235。即[BackupTS=433311088594911234+1]
結束tso:[ts=433314381739589634]
(六)在備用Tidb環境編輯reparo source配置檔案
因為binlog在生產環境的drainer/binlog下,我們的測試環境沒有這些binlog, 所以需要拷貝到共同的儲存中,許可權所屬是tidb使用者的,拷貝到/bak/data1/wangn/binlog下。
這個配置檔案是要把資料恢復到目標測試庫的配置檔案。
vim reparo_source.toml
# Drainer 輸出的 protobuf 格式 binlog 檔案的儲存路徑。
data-dir = "/bak/data1/wangn/binlog"
# 日誌輸出資訊等級設定:debug, info, warn, error, fatal (預設值:info)。
log-level = "info"
# 在從全量或者上次增量位置繼續同步時,start-tso 應當指定為全量 tso + 1
# 或者上次增量的 stop-tso + 1
start-tso = 433311088594911235
stop-tso = 433314381739589634
# 下游服務型別。 取值為 print, mysql(預設值:print)。
# 如果為 mysql,則需要在 [dest-db] 中配置 host、port、user、password 等資訊。
dest-type = "mysql"
# 安全模式配置。取值為 true 或 false(預設值:false)。
# 當值為 true 時,Reparo 會將 update 語句拆分為 delete + replace 語句。
safe-mode = false
# replicate-do-db 和 replicate-do-table 用於指定恢復的庫和表,
# replicate-do-db 的優先順序高於 replicate-do-table。
# 支援使用正則表示式來配置,需要以 '~' 開始宣告使用正則表示式。
# 注:replicate-do-db 和 replicate-do-table 使用方式與 Drainer 的使用方式一致。
# replicate-do-db = ["~^b.*","s1"]
[[replicate-do-table]]
db-name ="wangn_test"
tbl-name = "tt"
# 如果 dest-type 設定為 mysql, 需要配置 dest-db。
[dest-db]
host = "10.***.***.104"
port = 4000
user = "******"
password = "******"
(七)啟動reparo source
reparo -config /home/tidb/reparo_source.toml >/home/tidb/binlog_parse_source.log
檢視資料已經恢復回來了。把測試環境中恢復的資料匯出來,匯入到生產環境中,就OK了!
參考文獻均來自PingCap官網:
http://docs.pingcap.com/zh/tidb/v5.3/tidb-binlog-overview
http://docs.pingcap.com/zh/tidb/v5.3/tidb-binlog-reparo
END
往期回顧
自如技術
Ziroom Technology
掃碼關注,獲取更多資訊
![](http://mdimg.wxwenku.com/getimg/ccdf080c7af7e8a10e9b88444af9839353490fb1798440730e33f98889159b827858329298a6ae7e72bc479d4cf40e51.jpg)