WalMiner
[TOC]
WalMiner是從PostgreSQL的WAL(write ahead logs)日誌中解析出執行的SQL語句的工具,並能生 成出對應的undo SQL語句。
referenceXlogMiner renamed to WalMiner XlogMiner Enhancements Released and Renamed to WalMinerPosted on 2019-02-22 by Highgo Software
reference XLogMiner reference WalMiner
注意:walminer是Highgo開源的一款軟件。HGDB所有版本均支持walminer。
walminer安裝
reference WalMiner
1 配置要求
需要將數據庫日誌級別配置需要大於minimal
創建歸檔路徑
mkdir /home/hgdb565/archive/ -p
必須設置如下三個參數,據庫日誌級別配置需要大於minimal wal_level minimal, archive, hot_standby, or logical ,若想做最完整的日誌挖掘,建議設 置爲logical。
alter system set wal_level = 'logical';
alter system set archive_mode = on;
alter system set archive_directory = '/home/hgdb565/archive';
修改後重啓數據庫生效。
2 版本查看
查看本機環境數據庫版本
select kernel_version();
or
select version();
PG版本支持 PG9.5.0之前的版本沒有做過測試 PG9.5.0~PG10.X版本使用WalMiner_10_X PG11之後的版本使用WalMiner_11_X
3 編譯安裝
download and reaad README.md.or read online README.md
unzip movead-XLogMiner-WalMiner_10_0_1.zip
cp -rpi ./XLogMiner/walminer/ ./postgresql-10.6/contrib/
cd ./postgresql-10.6/contrib/walminer
make && make install
make install
/bin/mkdir -p '/opt/pg106/lib/postgresql'
/bin/mkdir -p '/opt/pg106/share/postgresql/extension'
/bin/mkdir -p '/opt/pg106/share/postgresql/extension'
/bin/install -c -m 755 walminer.so '/opt/pg106/lib/postgresql/walminer.so'
/bin/install -c -m 644 ./walminer.control '/opt/pg106/share/postgresql/extension/'
/bin/install -c -m 644 ./walminer--1.0.sql '/opt/pg106/share/postgresql/extension/'
note 將walminer目錄放置到編譯通過的PG源碼的"../contrib/"目錄下
hgdb無源碼編譯目錄。可在對應版本的pg中編譯好,再將文件拷貝到hgdb的目錄下。
cd /opt/pg106/share/postgresql/extension/
scp wal* [email protected]:/opt/HighGo5.6.5/share/postgresql/extension
cd /opt/pg106/lib/postgresql
scp walminer.so [email protected]:/opt/HighGo5.6.5/lib/postgresql/
4 創建擴展
創建walminer的extension
create extension walminer;
注意HGDBV5之前爲: create extension xlogminer;
===========
使用方法
場景一:從WAL日誌產生的數據庫中直接執行解析
1. 創建walminer的extension
create extension walminer;
2. Add wal日誌文件
-- 增加wal文件:
select walminer_wal_add('/opt/HighGo5.6.5/data/pg_wal');
-- 注:參數可以爲目錄或者文件
3. Remove wal日誌文件
-- 移除wal文件:
select walminer_wal_remove('/opt/HighGo5.6.5/data/pg_wal');
-- 注:參數可以爲目錄或者文件
4. List wal日誌文件
-- 列出wal文件:
select walminer_wal_list();
5. 執行解析
select walminer_start(’START_TIMSTAMP’,’STOP_TIMESTAMP’,’START_XID’,’STOP_XID’)
---如果分析全部日誌:
select walminer_start('null','null',0,0);
---將系統表修改結果輸出到$PGDATA/walminer/temp下:
select walminer_start('null','null',0,0,true);
- START_TIMESTAMP:指定輸出結果中最早的記錄條目,即從該時間開始輸出分析數據;若該參數值爲空,則以分析日誌列表中最早數據開始輸出;若該參數值指定時間沒有包含在所分析xlog列表中,即通過分析發現全部早於該參數指定時間,則返回空值。
- STOP_TIMESTAMP:指定數據結果中最晚的記錄條目,即輸出結果如果大於該時間,則停止分析,不需要繼續輸出;如果該參數值爲空,則從START_TIMESTAMP開始的所有日誌都進行分析和輸出。
- START_XID:作用與START_TIMESTAMP相同,指定開始的XID值;
- STOP_XID:作用與STOP_TIMESTAMP相同,指定結束的XID值
:warning: 兩組參數只能有一組爲有效輸入,否則報錯。
6. 解析結果查看
select * from walminer_contents;
7. 結束walminer操作
該函數作用爲釋放內存,結束日誌分析,該函數沒有參數。
select walminer_stop();
場景二:從非WAL產生的數據庫中執行WAL日誌解析
:warning: 要求執行解析的PostgreSQL數據庫和被解析的爲同一版本
於生產數據庫
1.創建walminer的extension
create extension walminer;
2.生成數據字典
select walminer_build_dictionary('/opt/HighGo5.6.5/store_dictionary');
-- 注:參數可以爲目錄或者文件
於測試數據庫
1. 創建walminer的extension
create extension walminer;
將字典文件和日誌傳輸到測試數據庫
將父目錄創建出來
mkdir -p /opt/pg106/data/archive_hgdb565
cd /opt/pg106/
scp [email protected]:/opt/HighGo5.6.5/store_dictionary .
copy wal or archive
cd /opt/pg106/data/archive_hgdb565
scp [email protected]:/opt/HighGo5.6.5/data/pg_wal/0* .
2. load數據字典
select walminer_load_dictionary('/opt/pg106/store_dictionary');
-- 注:參數可以爲目錄或者文件
如出現一下錯誤,將父目錄創建出來即可
postgres=# select walminer_load_dictionary('/opt/pg106/store_dictionary');
ERROR: It is failed to create dictionary "/opt/pg106/data/walminer/temp".
將父目錄創建出來
mkdir -p /opt/pg106/data/walminer
3. add wal日誌文件
-- 增加wal文件:
select walminer_wal_add('/opt/pg106/data/archive_hgdb565');
-- 注:參數可以爲目錄或者文件
4. remove wal日誌文件
-- 移除wal文件:
select walminer_wal_remove('/opt/test/wal');
-- 注:參數可以爲目錄或者文件
5. list wal日誌文件
-- 列出wal文件:
select walminer_wal_list();
-- 注:參數可以爲目錄或者文件
6. 執行解析
select walminer_start(’START_TIMSTAMP’,’STOP_TIMESTAMP’,’START_XID’,’STOP_XID’)
select walminer_start('null','null',0,0);
- START_TIMESTAMP:指定輸出結果中最早的記錄條目,即從該時間開始輸出分析數據;若該參數值爲空,則以分析日誌列表中最早數據開始輸出;若該參數值指定時間沒有包含在所分析xlog列表中,即通過分析發現全部早於該參數指定時間,則返回空值。
- STOP_TIMESTAMP:指定數據結果中最晚的記錄條目,即輸出結果如果大於該時間,則停止分析,不需要繼續輸出;如果該參數值爲空,則從START_TIMESTAMP開始的所有日誌都進行分析和輸出。
- START_XID:作用與START_TIMESTAMP相同,指定開始的XID值;
- STOP_XID:作用與STOP_TIMESTAMP相同,指定結束的XID值 兩組參數只能有一組爲有效輸入,否則報錯。
7. 解析結果查看
select * from walminer_contents;
select timestamptz,record_user,op_type,op_text,op_undo from walminer_contents where timestamptz >= '2020-05-12 14:10:00'::timestamp and timestamptz <= '2020-05-12 14:20:00'::timestamp and op_type='DELETE';
timestamptz | record_user | op_type | op_text | op_undo
-------------------------------+-------------+---------+--------------------------------------------------------------------------------------------+------------------------------------------------------------
---------------------------------
2020-05-12 14:14:49.189156+08 | highgo | DELETE | DELETE FROM "public"."test_t" WHERE "id"=1 AND "name"='4e4ff1685131a4cdc6643b523620e10f'; | INSERT INTO "public"."test_t"("id", "name") VALUES(1, '4e4f
f1685131a4cdc6643b523620e10f');
2020-05-12 14:14:49.189156+08 | highgo | DELETE | DELETE FROM "public"."test_t" WHERE "id"=2 AND "name"='126ce4b149a49d1a68f6c2a0af4b2bdd'; | INSERT INTO "public"."test_t"("id", "name") VALUES(2, '126c
e4b149a49d1a68f6c2a0af4b2bdd');
2020-05-12 14:14:49.189156+08 | highgo | DELETE | DELETE FROM "public"."test_t" WHERE "id"=3 AND "name"='dc65893ca95dee5e6547854d3fd4f505'; | INSERT INTO "public"."test_t"("id", "name") VALUES(3, 'dc65
893ca95dee5e6547854d3fd4f505');
2020-05-12 14:14:49.189156+08 | highgo | DELETE | DELETE FROM "public"."test_t" WHERE "id"=4 AND "name"='f04daec7b38fe12ced141b1c6a01346a'; | INSERT INTO "public"."test_t"("id", "name") VALUES(4, 'f04d
aec7b38fe12ced141b1c6a01346a');
2020-05-12 14:14:49.189156+08 | highgo | DELETE | DELETE FROM "public"."test_t" WHERE "id"=5 AND "name"='05bba4c686505ec88bd65ddc8ff42498'; | INSERT INTO "public"."test_t"("id", "name") VALUES(5, '05bb
a4c686505ec88bd65ddc8ff42498');
2020-05-12 14:14:49.189156+08 | highgo | DELETE | DELETE FROM "public"."test_t" WHERE "id"=6 AND "name"='a8fa80d0188d37629e057aa6a52fe8d8'; | INSERT INTO "public"."test_t"("id", "name") VALUES(6, 'a8fa
80d0188d37629e057aa6a52fe8d8');
......
8.結束walminer操作
該函數作用爲釋放內存,結束日誌分析,該函數沒有參數。
select walminer_stop();
:warning: 注意:walminer_contents是walminer自動生成的臨時表,因此當session斷開再重新進入或其他session中解析數據不可見。這麼做主要是基於安全考慮。 如果希望保留解析結果,可利用create xxx as select * from walminer_contents;寫入普通表中。
使用限制
- 本版本只解析DML語句,不處理DDL語句
- 執行了刪除表、truncate表、更改表的表空間、更改表字段的類型、vacuum full,這樣的DDL語句後,發生DDL語句之前的此表相關的DML語句不會再被解析。
- 解析結果依賴於數據字典。(舉例:創建表t1,所有者爲user1,但是中間將所有者改爲user2。那解析結果中,所有t1相關操作所有者都將標示爲user2)
- wal日誌如果發生缺失,在缺失的wal日誌中發生提交的數據,都不會在解析結果中出現
- 解析結果中undo字段的ctid屬性是發生變更“當時”的值,如果因爲vacuum等操作導致ctid發生變更,這個值將不準確。對於有可能存在重複行的數據,我們需要通過這個值確定undo對應的tuple條數,不代表可以直接執行該undo語句。
- 執行了表字段drop的DDL語句後,發生DDL語句之前的這個字段相關的值都會被解析爲encode('AD976BC56F',hex)的形式,另外自定義類型也會解析爲這種形式
- 只能解析與數據字典時間線一致的wal文件
- 不建議使用walminer解析大宗copy語句(在同一個事務中插入大量數據行)產生的wal日誌,這會導致解析過程中的效率低下和內存佔用過高