mirror of
https://github.com/postgres/postgres.git
synced 2025-04-18 13:44:19 +03:00
Since its introduction, LogLogicalMessage() (via the SQL interface pg_logical_emit_message()) has never included a call to XLogFlush(), causing it to potentially lose messages on a crash when used in non-transactional mode. This has come up to me as a problem while playing with ideas to design a test suite for what has become 039_end_of_wal.pl introduced in bae868caf222 by Thomas Munro, because there are no direct ways to force a WAL flush via SQL. The default is false, to not flush messages and influence existing use-cases where this function could be used. If set to true, the message emitted is flushed before returning back to the caller, making the message durable on crash. This new option has no effect when using pg_logical_emit_message() in transactional mode, as the record's flush is guaranteed by the WAL record generated by the transaction committed. Two queries of test_decoding are tweaked to cover the new code path for the flush. Bump catalog version. Author: Michael Paquier Reviewed-by: Andres Freund, Amit Kapila, Fujii Masao, Tung Nguyen, Tomas Vondra Discussion: https://postgr.es/m/ZNsdThSe2qgsfs7R@paquier.xyz
107 lines
2.4 KiB
Plaintext
107 lines
2.4 KiB
Plaintext
-- predictability
|
|
SET synchronous_commit = on;
|
|
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding');
|
|
?column?
|
|
----------
|
|
init
|
|
(1 row)
|
|
|
|
-- These two cover the path for the flush variant.
|
|
SELECT 'msg1' FROM pg_logical_emit_message(true, 'test', 'msg1', true);
|
|
?column?
|
|
----------
|
|
msg1
|
|
(1 row)
|
|
|
|
SELECT 'msg2' FROM pg_logical_emit_message(false, 'test', 'msg2', true);
|
|
?column?
|
|
----------
|
|
msg2
|
|
(1 row)
|
|
|
|
BEGIN;
|
|
SELECT 'msg3' FROM pg_logical_emit_message(true, 'test', 'msg3');
|
|
?column?
|
|
----------
|
|
msg3
|
|
(1 row)
|
|
|
|
SELECT 'msg4' FROM pg_logical_emit_message(false, 'test', 'msg4');
|
|
?column?
|
|
----------
|
|
msg4
|
|
(1 row)
|
|
|
|
ROLLBACK;
|
|
BEGIN;
|
|
SELECT 'msg5' FROM pg_logical_emit_message(true, 'test', 'msg5');
|
|
?column?
|
|
----------
|
|
msg5
|
|
(1 row)
|
|
|
|
SELECT 'msg6' FROM pg_logical_emit_message(false, 'test', 'msg6');
|
|
?column?
|
|
----------
|
|
msg6
|
|
(1 row)
|
|
|
|
SELECT 'msg7' FROM pg_logical_emit_message(true, 'test', 'msg7');
|
|
?column?
|
|
----------
|
|
msg7
|
|
(1 row)
|
|
|
|
COMMIT;
|
|
SELECT 'ignorethis' FROM pg_logical_emit_message(true, 'test', 'czechtastic');
|
|
?column?
|
|
------------
|
|
ignorethis
|
|
(1 row)
|
|
|
|
SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'force-binary', '0', 'skip-empty-xacts', '1', 'include-xids', '0');
|
|
data
|
|
--------------------------------------------------------------------
|
|
BEGIN
|
|
message: transactional: 1 prefix: test, sz: 4 content:msg1
|
|
COMMIT
|
|
message: transactional: 0 prefix: test, sz: 4 content:msg2
|
|
message: transactional: 0 prefix: test, sz: 4 content:msg4
|
|
message: transactional: 0 prefix: test, sz: 4 content:msg6
|
|
BEGIN
|
|
message: transactional: 1 prefix: test, sz: 4 content:msg5
|
|
message: transactional: 1 prefix: test, sz: 4 content:msg7
|
|
COMMIT
|
|
BEGIN
|
|
message: transactional: 1 prefix: test, sz: 11 content:czechtastic
|
|
COMMIT
|
|
(13 rows)
|
|
|
|
-- test db filtering
|
|
\set prevdb :DBNAME
|
|
\c template1
|
|
SELECT 'otherdb1' FROM pg_logical_emit_message(false, 'test', 'otherdb1');
|
|
?column?
|
|
----------
|
|
otherdb1
|
|
(1 row)
|
|
|
|
SELECT 'otherdb2' FROM pg_logical_emit_message(true, 'test', 'otherdb2');
|
|
?column?
|
|
----------
|
|
otherdb2
|
|
(1 row)
|
|
|
|
\c :prevdb
|
|
SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'force-binary', '0', 'skip-empty-xacts', '1');
|
|
data
|
|
------
|
|
(0 rows)
|
|
|
|
SELECT 'cleanup' FROM pg_drop_replication_slot('regression_slot');
|
|
?column?
|
|
----------
|
|
cleanup
|
|
(1 row)
|
|
|