47.1. ÐÑимеÑÑ Ð»Ð¾Ð³Ð¸ÑеÑкого декодиÑÐ¾Ð²Ð°Ð½Ð¸Ñ #
СледÑÑÑий пÑÐ¸Ð¼ÐµÑ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑиÑÑÐµÑ ÑпÑавление логиÑеÑким декодиÑованием на ÑÑовне SQL.
ÐÑежде Ñем Ð²Ñ ÑможеÑе иÑполÑзоваÑÑ Ð»Ð¾Ð³Ð¸ÑеÑкое декодиÑование, Ð²Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ ÑÑÑановиÑÑ Ð² wal_level знаÑение logical, а в max_replication_slots знаÑение, не менÑÑее 1. ÐоÑле ÑÑого Ð²Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿Ð¾Ð´ÐºÐ»ÑÑиÑÑÑÑ Ðº Ñелевой базе даннÑÑ
(в ÑледÑÑÑем пÑимеÑе, ÑÑо postgres) как ÑÑпеÑполÑзоваÑелÑ.
postgres=# -- СоздаÑÑ ÑÐ»Ð¾Ñ Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ 'regression_slot', иÑполÑзÑÑÑий модÑÐ»Ñ Ð²Ñвода 'test_decoding'
postgres=# SELECT * FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding', false, true);
slot_name | lsn
-----------------+-----------
regression_slot | 0/16B1970
(1 row)
postgres=# SELECT slot_name, plugin, slot_type, database, active, restart_lsn, confirmed_flush_lsn FROM pg_replication_slots;
slot_name | plugin | slot_type | database | active | restart_lsn | confirmed_flush_lsn
-----------------+---------------+-----------+----------+--------+-------------+-----------------
regression_slot | test_decoding | logical | postgres | f | 0/16A4408 | 0/16A4440
(1 row)
postgres=# -- Ðока никакие Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ðµ виднÑ
postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
lsn | xid | data
-----+-----+------
(0 rows)
postgres=# CREATE TABLE data(id serial primary key, data text);
CREATE TABLE
postgres=# -- DDL не ÑеплиÑиÑÑеÑÑÑ, поÑÑÐ¾Ð¼Ñ Ð²Ð¸Ð´Ð½Ð° ÑолÑко ÑÑанзакÑиÑ
postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
lsn | xid | data
-----------+-------+--------------
0/BA2DA58 | 10297 | BEGIN 10297
0/BA5A5A0 | 10297 | COMMIT 10297
(2 rows)
postgres=# -- Ðогда Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿ÑоÑиÑанÑ, они ÑÑиÑаÑÑÑÑ Ð¾Ð±ÑабоÑаннÑми и Ñже не вÑдаÑÑÑÑ
postgres=# -- в поÑледÑÑÑем вÑзове:
postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
lsn | xid | data
-----+-----+------
(0 rows)
postgres=# BEGIN;
postgres=*# INSERT INTO data(data) VALUES('1');
postgres=*# INSERT INTO data(data) VALUES('2');
postgres=*# COMMIT;
postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
lsn | xid | data
-----------+-------+---------------------------------------------------------
0/BA5A688 | 10298 | BEGIN 10298
0/BA5A6F0 | 10298 | table public.data: INSERT: id[integer]:1 data[text]:'1'
0/BA5A7F8 | 10298 | table public.data: INSERT: id[integer]:2 data[text]:'2'
0/BA5A8A8 | 10298 | COMMIT 10298
(4 rows)
postgres=# INSERT INTO data(data) VALUES('3');
postgres=# -- Также можно заглÑнÑÑÑ Ð²Ð¿ÐµÑÑд в поÑоке изменений, не ÑÑиÑÑÐ²Ð°Ñ ÑÑи изменениÑ
postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL);
lsn | xid | data
-----------+-------+---------------------------------------------------------
0/BA5A8E0 | 10299 | BEGIN 10299
0/BA5A8E0 | 10299 | table public.data: INSERT: id[integer]:3 data[text]:'3'
0/BA5A990 | 10299 | COMMIT 10299
(3 rows)
postgres=# -- СледÑÑÑий вÑзов pg_logical_slot_peek_changes() Ñнова возвÑаÑÐ°ÐµÑ Ñе же изменениÑ
postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL);
lsn | xid | data
-----------+-------+---------------------------------------------------------
0/BA5A8E0 | 10299 | BEGIN 10299
0/BA5A8E0 | 10299 | table public.data: INSERT: id[integer]:3 data[text]:'3'
0/BA5A990 | 10299 | COMMIT 10299
(3 rows)
postgres=# -- ÐодÑÐ»Ñ Ð²Ñвода можно пеÑедаÑÑ Ð¿Ð°ÑамеÑÑÑ, влиÑÑÑие на ÑоÑмаÑиÑование
postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL, 'include-timestamp', 'on');
lsn | xid | data
-----------+-------+---------------------------------------------------------
0/BA5A8E0 | 10299 | BEGIN 10299
0/BA5A8E0 | 10299 | table public.data: INSERT: id[integer]:3 data[text]:'3'
0/BA5A990 | 10299 | COMMIT 10299 (at 2017-05-10 12:07:21.272494-04)
(3 rows)
postgres=# -- Ðе забÑдÑÑе ÑдалиÑÑ ÑлоÑ, коÑоÑÑй вам болÑÑе не нÑжен, ÑÑÐ¾Ð±Ñ Ð¾Ð½
postgres=# -- не поÑÑеблÑл ÑеÑÑÑÑÑ ÑеÑвеÑа:
postgres=# SELECT pg_drop_replication_slot('regression_slot');
pg_drop_replication_slot
-----------------------
(1 row)СледÑÑÑие пÑимеÑÑ Ð¿Ð¾ÐºÐ°Ð·ÑваÑÑ, как можно ÑпÑавлÑÑÑ Ð»Ð¾Ð³Ð¸ÑеÑким декодиÑованием ÑÑедÑÑвами пÑоÑокола поÑоковой ÑепликаÑии, иÑполÑзÑÑ Ð¿ÑогÑÐ°Ð¼Ð¼Ñ pg_recvlogical, вклÑÑÑннÑÑ Ð² диÑÑÑибÑÑив PostgreSQL. ÐÐ»Ñ ÑÑого нÑжно, ÑÑÐ¾Ð±Ñ ÐºÐ¾Ð½ÑигÑÑаÑÐ¸Ñ Ð°ÑÑенÑиÑикаÑии клиенÑов допÑÑкала подклÑÑÐµÐ½Ð¸Ñ Ð´Ð»Ñ ÑепликаÑии (Ñм. ÐодÑаздел 26.2.5.1) и ÑÑÐ¾Ð±Ñ Ð·Ð½Ð°Ñение max_wal_senders бÑло доÑÑаÑоÑно болÑÑим и позволило ÑÑÑановиÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑное подклÑÑение. ÐÑоÑой пÑÐ¸Ð¼ÐµÑ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑиÑÑÐµÑ Ð¿Ð¾ÑоковÑÑ Ð¿ÐµÑедаÑÑ Ð´Ð²ÑÑ
ÑазнÑÑ
ÑÑанзакÑий. ÐÑежде Ñем иÑполÑзоваÑÑ Ð´Ð²ÑÑ
ÑазнÑе командÑ, Ð´Ð»Ñ Ð¿Ð°ÑамеÑÑа max_prepared_transactions нÑжно ÑÑÑановиÑÑ Ð·Ð½Ð°Ñение не менÑÑе 1.
ÐÑÐ¸Ð¼ÐµÑ 1: $ pg_recvlogical -d postgres --slot=test --create-slot $ pg_recvlogical -d postgres --slot=test --start -f - Control+Z $ psql -d postgres -c "INSERT INTO data(data) VALUES('4');" $ fg BEGIN 693 table public.data: INSERT: id[integer]:4 data[text]:'4' COMMIT 693 Control+C $ pg_recvlogical -d postgres --slot=test --drop-slot ÐÑÐ¸Ð¼ÐµÑ 2: $ pg_recvlogical -d postgres --slot=test --create-slot --enable-two-phase $ pg_recvlogical -d postgres --slot=test --start -f - Control+Z $ psql -d postgres -c "BEGIN;INSERT INTO data(data) VALUES('5');PREPARE TRANSACTION 'test';" $ fg BEGIN 694 table public.data: INSERT: id[integer]:5 data[text]:'5' PREPARE TRANSACTION 'test', txid 694 Control+Z $ psql -d postgres -c "COMMIT PREPARED 'test';" $ fg COMMIT PREPARED 'test', txid 694 Control+C $ pg_recvlogical -d postgres --slot=test --drop-slot
Ð ÑледÑÑÑем пÑимеÑе показан инÑеÑÑÐµÐ¹Ñ SQL, коÑоÑÑй можно иÑполÑзоваÑÑ Ð´Ð»Ñ Ð´ÐµÐºÐ¾Ð´Ð¸ÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð´Ð³Ð¾ÑовленнÑÑ
ÑÑанзакÑий. ÐеÑед Ñем, как иÑполÑзоваÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð´Ð²ÑÑ
Ñазной ÑикÑаÑии, Ð²Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ ÑÑÑановиÑÑ Ð·Ð½Ð°Ñение max_prepared_transactions ÑавнÑм как минимÑм 1. ÐÑ Ñакже Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿Ñи Ñоздании ÑлоÑа пеÑедаÑÑ Ð² паÑамеÑÑе two_phase ÑÑнкÑии pg_create_logical_replication_slot знаÑение true. ÐбÑаÑиÑе внимание, вÑÑ ÑÑанзакÑÐ¸Ñ Ð±ÑÐ´ÐµÑ ÑÑанÑлиÑоваÑÑÑÑ Ð¿Ð¾Ñле ÑикÑаÑии, еÑли она еÑÑ Ð½Ðµ бÑла декодиÑована.
postgres=# BEGIN;
postgres=*# INSERT INTO data(data) VALUES('5');
postgres=*# PREPARE TRANSACTION 'test_prepared1';
postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
lsn | xid | data
-----------+-----+---------------------------------------------------------
0/1689DC0 | 529 | BEGIN 529
0/1689DC0 | 529 | table public.data: INSERT: id[integer]:3 data[text]:'5'
0/1689FC0 | 529 | PREPARE TRANSACTION 'test_prepared1', txid 529
(3 rows)
postgres=# COMMIT PREPARED 'test_prepared1';
postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NULL);
lsn | xid | data
-----------+-----+--------------------------------------------
0/168A060 | 529 | COMMIT PREPARED 'test_prepared1', txid 529
(4 row)
postgres=#-- Ð²Ñ Ñакже можеÑе оÑкаÑиÑÑ Ð¿Ð¾Ð´Ð³Ð¾ÑовленнÑÑ ÑÑанзакÑиÑ
postgres=# BEGIN;
postgres=*# INSERT INTO data(data) VALUES('6');
postgres=*# PREPARE TRANSACTION 'test_prepared2';
postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NULL);
lsn | xid | data
-----------+-----+---------------------------------------------------------
0/168A180 | 530 | BEGIN 530
0/168A1E8 | 530 | table public.data: INSERT: id[integer]:4 data[text]:'6'
0/168A430 | 530 | PREPARE TRANSACTION 'test_prepared2', txid 530
(3 rows)
postgres=# ROLLBACK PREPARED 'test_prepared2';
postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NULL);
lsn | xid | data
-----------+-----+----------------------------------------------
0/168A4B8 | 530 | ROLLBACK PREPARED 'test_prepared2', txid 530
(1 row)