上一篇文章介绍了PostgreSQL如何恢复误操作的数据(详见:PG数据库误删除数据怎么办,还需要跑路吗?),由于使用了Walminer 4.8版本,这个需要购买license,才能使用。有读者私信,有没有开源的工具可以使用呢?当然了,Walminer有完全开源的3.0版,但它需要以插件的方式安装在数据库,支持PostgreSQL10及其以上版本,功能上也相比Walminer 4.x版本弱。如果你的需求不高,应该也能满足使用,下面就来说说walminer 3.0是怎么使用的。
WalMiner3.0安装
软件下载地址:https://gitee.com/movead/XLogMiner/tree/master/
它的安装方式主要有2种:
编译一:PG源码编译 如果你从编译pg数据库开始
-
将walminer目录放置到编译通过的PG工程的"…/contrib/"目录下
-
进入walminer目录
-
执行命令
make && make install
编译二:依据PG安装编译 如果你使用yum或者pg安装包安装了pg
-
配置pg的bin路径至环境变量
export PATH=/h2/pg_install/bin:$PATH
-
进入walminer代码路径
-
执行编译安装
USE_PGXS=1 MAJORVERSION=12 make #MAJORVERSION支持‘10’,‘11’,‘12’,‘13’,‘14’,‘15’,‘16’,‘17’ USE_PGXS=1 MAJORVERSION=12 make install
以我本机的pg 14.4安装为例:
--把下载的软件进行解压
[root@pgdkcs XLogMiner-walminer_3.0_stable]# unzip -q XLogMiner-walminer_3.0_stable.zip
[root@pgdkcs XLogMiner-walminer_3.0_stable]# cd walminer/
[root@pgdkcs walminer]# ls
datadictionary.c expected imagemanage.c pagecollect.h todo.md wal2sql_ddl.h wal2sql_spi.h walminer_12.conf walminer.c walminer_contents.h walminer_decode.h wm_compatible.c wm_utils.h
datadictionary.h fetchcatalogtable.c Makefile sql wal2sql.c wal2sql.h wallist.c walminer--2.0.sql walminer.conf walminer.control walminer_thread.c wm_compatible.h
debug_info.md image pagecollect.c temp.h wal2sql_ddl.c wal2sql_spi.c walminer--1.0.sql walminer--3.0.sql walminer_contents.c walminer_decode.c walreader.c wm_utils.c
[root@pgdkcs walminer]# USE_PGXS=1 MAJORVERSION=14 make
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o walminer.o walminer.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o wm_utils.o wm_utils.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o datadictionary.o datadictionary.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o fetchcatalogtable.o fetchcatalogtable.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o wallist.o wallist.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o walreader.o walreader.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o walminer_decode.o walminer_decode.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o imagemanage.o imagemanage.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o wal2sql.o wal2sql.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o walminer_contents.o walminer_contents.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o walminer_thread.o walminer_thread.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o wal2sql_spi.o wal2sql_spi.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o wal2sql_ddl.o wal2sql_ddl.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o pagecollect.o pagecollect.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -DPG_VERSION_14 -I. -I./ -I/usr/local/pg144/include/postgresql/server -I/usr/local/pg144/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o wm_compatible.o wm_compatible.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -shared -o walminer.so walminer.o wm_utils.o datadictionary.o fetchcatalogtable.o wallist.o walreader.o walminer_decode.o imagemanage.o wal2sql.o walminer_contents.o walminer_thread.o wal2sql_spi.o wal2sql_ddl.o pagecollect.o wm_compatible.o -L/usr/local/pg144/lib -Wl,--as-needed -Wl,-rpath,'/usr/local/pg144/lib',--enable-new-dtags
[root@pgdkcs walminer]#
[root@pgdkcs walminer]#
[root@pgdkcs walminer]# USE_PGXS=1 MAJORVERSION=14 make install
/usr/bin/mkdir -p '/usr/local/pg144/lib/postgresql'
/usr/bin/mkdir -p '/usr/local/pg144/share/postgresql/extension'
/usr/bin/mkdir -p '/usr/local/pg144/share/postgresql/extension'
/usr/bin/install -c -m 755 walminer.so '/usr/local/pg144/lib/postgresql/walminer.so'
/usr/bin/install -c -m 644 .//walminer.control '/usr/local/pg144/share/postgresql/extension/'
/usr/bin/install -c -m 644 .//walminer--3.0.sql '/usr/local/pg144/share/postgresql/extension/'
创建walminer的extension:
postgres@[local]:5432=#\dx
List of installed extensions
Name | Version | Schema | Description
--------------------+---------+------------+------------------------------------------------------------------------
pg_stat_statements | 1.9 | public | track planning and execution statistics of all SQL statements executed
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(2 rows)
postgres@[local]:5432=#create extension walminer;
CREATE EXTENSION
postgres@[local]:5432=#\dx
List of installed extensions
Name | Version | Schema | Description
--------------------+---------+------------+------------------------------------------------------------------------
pg_stat_statements | 1.9 | public | track planning and execution statistics of all SQL statements executed
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
walminer | 3.0 | public | analyse wal to SQL
(3 rows)
WalMiner使用步骤
有用过oracle的logminer挖掘归档日志,WalMiner使用方式大概类似:
(1)添加要解析的wal日志文件
-- 添加wal文件:
select walminer_wal_add('/usr/local/pg144/data/pg_wal');
-- 注:参数可以为目录或者文件
如果添加错误了,要Remove wal日志文件,可以使用下面的方法:
-- 移除wal文件:
select walminer_wal_remove('/usr/local/pg144/data/pg_wal');
-- 注:参数可以为目录或者文件
查看已添加的wal日志文件
-- 列出wal文件:
select walminer_wal_list();
(2)解析已添加的wal日志
普通解析,解析add的全部wal日志
--解析add的全部wal日志
select walminer_all();
或 select wal2sql();
精确解析:
--在add的wal日志中查找对应时间范围的wal记录
select walminer_by_time(starttime, endtime,'true');
或 select wal2sql(starttime, endtime,'true');
--在add的wal日志中查找对应lsn范围的wal记录
select walminer_by_lsn(startlsn, endlsn,'true');
或 select wal2sql(startlsn, endlsn,'true');
--在add的wal日志中查找对应xid的wal记录
select walminer_by_xid(xid,'true');
或 select wal2sql(xid,'true');
(3)解析结果查看
select * from walminer_contents;
-- 表walminer_contents
(
sqlno int, --本条sql在其事务内的序号
xid bigint, --事务ID
topxid bigint, --如果为子事务,这是是其父事务;否则为0
sqlkind int, --sql类型1->insert;2->update;3->delete(待优化项目)
minerd bool, --解析结果是否完整(缺失checkpoint情况下可能无法解析出正确结果)
timestamp timestampTz, --这个SQL所在事务提交的时间
op_text text, --sql
undo_text text, --undo sql
complete bool, --如果为false,说明有可能这个sql所在的事务是不完整解析的
schema text, --目标表所在的模式
relation text, --目标表表名
start_lsn pg_lsn, --这个记录的开始LSN
commit_lsn pg_lsn --这个事务的提交LSN
)
注意:walminer_contents是walminer自动生成的unlogged表,在一次解析开始会首先创建或truncate walminer_contents表。
(4)结束walminer操作
select walminer_stop();
该函数作用为释放内存,结束日志分析,该函数没有参数。
测试案例
–创建测试表
create table walminer_t(id int,col1 varchar(8));
insert into walminer_t values(1,'w1'),(2,'w2');
postgres@[local]:5432=#select * from walminer_t ;
id | col1
----+------
1 | w1
2 | w2
(2 rows)
postgres@[local]:5432=#select pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/3B0533F0
(1 row)
postgres@[local]:5432=#select pg_walfile_name(pg_current_wal_lsn());
pg_walfile_name
--------------------------
00000001000000000000003B
(1 row)
–添加需要解析的wal文件
我们可以添加wal目录,也可以添加指定的wal文件(默认情况下此步骤可以省略,因为会直接加载当前数据字典和当前wal路径下的所有wal文件,但不建议省略)。
select walminer_wal_add('/usr/local/pg144/data/pg_wal');
或
select walminer_wal_add('/usr/local/pg144/data/pg_wal/00000001000000000000003B');
–列出已添加的wal文件
postgres@[local]:5432=#select walminer_wal_list();
walminer_wal_list
---------------------------------------------------------
(/usr/local/pg144/data/pg_wal/00000001000000000000003B)
(1 row)
–解析wal
postgres@[local]:5432=#select walminer_all();
NOTICE: ===========================================
NOTICE: ======OPEN SOURCE PROJECT WALMINER=========
NOTICE: ======Author mail [email protected]========
NOTICE: ===========================================
NOTICE: Switch wal to 00000001000000000000003B on time 2024-10-28 21:31:00.728701+08
walminer_all
-----------------
wal2sql success
(1 row)
–查看解析后的数据
walminer_contents是walminer自动生成的unlogged表,用来存储解析结果,在一次解析开始会先create或truncate此表,在表中我们看到这两条数据的xid、执行时间、执行操作、开始/结束lsn,甚至undo sql文本都写好了,很强大。
walminer_contents各字段解释:
(
sqlno int, --本条sql在其事务内的序号
xid bigint, --事务ID
topxid bigint, --如果为子事务,这是是其父事务;否则为0
sqlkind int, --sql类型1->insert;2->update;3->delete(待优化项目)
minerd bool, --解析结果是否完整(缺失checkpoint情况下可能无法解析出正确结果)
timestamp timestampTz, --这个SQL所在事务提交的时间
op_text text, --sql
undo_text text, --undo sql
complete bool, --如果为false,说明有可能这个sql所在的事务是不完整解析的
schema text, --目标表所在的模式
relation text, --目标表表名
start_lsn pg_lsn, --这个记录的开始LSN
commit_lsn pg_lsn --这个事务的提交LSN
)
postgres@[local]:5432=#select * from walminer_contents;
sqlno | xid | topxid | sqlkind | minerd | timestamp | op_text | undo_text | complete | schema | relation | start_lsn |
commit_lsn
-------+-----+--------+---------+--------+-------------------------------+---------------------------------------------------------+--------------------------------------------------------+----------+--------+------------+------------+-
-----------
1 | 869 | 0 | 1 | t | 2024-10-28 21:23:18.084329+08 | INSERT INTO public.walminer_t(id ,col1) VALUES(1 ,'w1') | DELETE FROM public.walminer_t WHERE id=1 AND col1='w1' | t | public | walminer_t | 0/3B053310 |
0/3B0533B8
2 | 869 | 0 | 1 | t | 2024-10-28 21:23:18.084329+08 | INSERT INTO public.walminer_t(id ,col1) VALUES(2 ,'w2') | DELETE FROM public.walminer_t WHERE id=2 AND col1='w2' | t | public | walminer_t | 0/3B053350 |
0/3B0533B8
(2 rows)
postgres@[local]:5432=#select undo_text from walminer_contents;
undo_text
--------------------------------------------------------
DELETE FROM public.walminer_t WHERE id=1 AND col1='w1'
DELETE FROM public.walminer_t WHERE id=2 AND col1='w2'
(2 rows)
我们可以直接执行undo_text 的语句,进行恢复数据。也可以通过以下方式先进行导出恢复的语句,然后在导入。
–导出数据
postgres@[local]:5432=#\pset footer
Default footer is off.
postgres@[local]:5432=#\pset t
Tuples only is on.
postgres@[local]:5432=#\o huifu.sql
postgres@[local]:5432=#select undo_text from walminer_contents;
postgres@[local]:5432=#\q
[postgres@pgdkcs ~]$ cat huifu.sql
DELETE FROM public.walminer_t WHERE id=1 AND col1='w1'
DELETE FROM public.walminer_t WHERE id=2 AND col1='w2'
–结束walminer操作
select walminer_stop();
–恢复数据
\set AUTOCOMMIT off
\i huifu.sql
commit;
使用精确的解析方式,还可以用以下方式:
–基于时间范围解析
select walminer_by_time('2024-10-28 21:22:00','2024-10-28 21:23:18');
–基于lsn范围解析
select walminer_by_lsn('0/3B053310','0/3B0533B8');
–基于指定xid解析
select walminer_by_xid('869');
当然,walminer还有很多其它骚操作,有兴趣的可以去试试。
关注我,学习更多的数据库知识!