我想知道是否可以使用标准查询选择查询交易。
例如:
SELECT * FROM information_schema.transaction_logs
WHERE table_name = 'product' AND time_stamp > '2016-01-01';
结果将类似于
===> table_name | operation | old_val_json | new_val_json...
product | update | {....desc:...} | {...desc...}|
查询不起作用,因为没有像transaction_logs这样的表,但是存在类似的东西吗?
答案 0 :(得分:7)
您可以通过逻辑复制槽查询预写日志流。
首先,您需要更改几个参数,然后重新启动服务器以进行更改:
postgres=# alter system set wal_level = logical;
postgres=# alter system set max_replication_slots = 1;
然后(重启后)你需要创建一个插槽:
postgres=# SELECT * FROM pg_create_logical_replication_slot('slot', 'test_decoding');
slot_name | xlog_position
-----------+---------------
slot | 2E/839F3300
(1 row)
此处,test_decoding
是一个输出插件名称,用于将日志记录(二进制)转换为某些文本表示。
然后让我们创建一个表......
postgres=# create table product(id serial, val json);
CREATE TABLE
现在您可以查询WAL流:
postgres=# SELECT * FROM pg_logical_slot_get_changes('slot', NULL, NULL);
location | xid | data
-------------+-------+--------------
2E/83A0BA48 | 80243 | BEGIN 80243
2E/83A1D2B8 | 80243 | COMMIT 80243
(2 rows)
不幸的是,现在你无法解码DDL,所以你得到的只是BEGIN和END。 Xid
字段代表交易号。
但是让我们插入一些东西......
postgres=# insert into product(val) values ('{"desc":"aaa"}');
INSERT 0 1
现在再次查询流:
postgres=# SELECT * FROM pg_logical_slot_get_changes('slot', NULL, NULL);
location | xid | data
-------------+-------+------------------------------------------------------------------------
2E/83A1D3C0 | 80244 | BEGIN 80244
2E/83A1D3C0 | 80244 | table public.product: INSERT: id[integer]:1 val[json]:'{"desc":"aaa"}'
2E/83A1D440 | 80244 | COMMIT 80244
(3 rows)
您可以在此处查看表名和插入值。
更新声明相同:
postgres=# update product set val = '{"desc":"bbb"}';
UPDATE 1
postgres=# SELECT * FROM pg_logical_slot_get_changes('slot', NULL, NULL);
location | xid | data
-------------+-------+------------------------------------------------------------------------
2E/83A1D560 | 80245 | BEGIN 80245
2E/83A1D560 | 80245 | table public.product: UPDATE: id[integer]:1 val[json]:'{"desc":"bbb"}'
2E/83A1D5E8 | 80245 | COMMIT 80245
(3 rows)
请注意,使用pg_logical_slot_get_changes
函数从流中“消耗”某些更改后,您无法再次查询相同的更改。
如果您不再需要,请删除插槽:
postgres=# SELECT pg_drop_replication_slot('slot');
pg_drop_replication_slot
--------------------------
(1 row)
您可以阅读有关逻辑解码in the documentation的更多信息。