| -- Test: SELECT or other read-only operations which set hint bits on pages, |
| -- and in turn generate Full Page Images (FPI) WAL records should be throttled. |
| -- We will only throttle when our transaction wal exceeds |
| -- wait_for_replication_threshold. While the backend is throttled waiting for |
| -- synchronous replication, it should not block the CHECKPOINT process, and if |
| -- the mirror is taken down, synchronous replication should be turned off and |
| -- the backend should stop waiting for synchronous replication and proceed. |
| |
| -- Setup: |
| -- 1. Set wait_for_replication_threshold to 1kB for quicker test |
| -- 2. create two tables (one small and one large) |
| -- 3. set gp_disable_tuple_hints=off so buffer will be immediately marked dirty on hint bit change |
| |
| -- set wait_for_replication_threshold to 1kB for quicker test |
| ALTER SYSTEM SET wait_for_replication_threshold = 1; |
| SELECT pg_reload_conf(); |
| |
| CREATE TABLE select_no_throttle(a int) DISTRIBUTED BY (a); |
| INSERT INTO select_no_throttle SELECT generate_series (1, 10); |
| CREATE TABLE select_throttle(a int) DISTRIBUTED BY (a); |
| INSERT INTO select_throttle SELECT generate_series (1, 900000); |
| |
| -- Enable tuple hints so that buffer will be marked dirty upon a hint bit change |
| -- (so that we don't have to wait for the tuple to age. See logic in markDirty) |
| 1U: SET gp_disable_tuple_hints=off; |
| |
| -- Test 1: |
| -- 1. Suspend walsender |
| -- 2. Perform a read-only operation (SELECT) which would now set the hint bits |
| -- For the small table this operation should finish, |
| -- but for large table the SELECT should be throttled |
| -- since it would generate a lot of WAL greater than wait_for_replication_threshold |
| -- 3. Confirm that the query is waiting on Syncrep |
| -- 4. Reset the walsender and the transaction should complete |
| |
| -- flush the data to disk |
| checkpoint; |
| |
| -- Suspend walsender |
| SELECT gp_inject_fault_infinite('wal_sender_loop', 'suspend', dbid) FROM gp_segment_configuration WHERE role = 'p' and content = 1; |
| |
| -- the following SELECTS will set the hint bit on (the buffer will be marked dirty) |
| -- This query should not wait |
| 1U: SELECT count(*) FROM select_no_throttle; |
| checkpoint; |
| -- This query should wait for Syncrep since its WAL size for hint bits is greater than wait_for_replication_threshold |
| 1U&: SELECT count(*) FROM select_throttle; |
| |
| -- check if the above query is waiting on SyncRep in pg_stat_activity |
| SELECT is_query_waiting_for_syncrep(50, 'SELECT count(*) FROM select_throttle;'); |
| |
| -- reset walsender |
| SELECT gp_inject_fault_infinite('wal_sender_loop', 'reset', dbid) FROM gp_segment_configuration WHERE role = 'p' and content = 1; |
| -- after this, system continue to proceed |
| |
| 1U<: |
| |
| SELECT wait_until_all_segments_synchronized(); |
| |
| -- Test 2: |
| -- 1. Suspend walsender |
| -- 2. Perform a read-only operation (SELECT) which would now set the hint bits |
| -- For the large table the SELECT should be throttled |
| -- since it would generate a lot of WAL greater than wait_for_replication_threshold |
| -- 3. Confirm that the query is waiting on Syncrep |
| -- 4. Perform CHECKPOINT and confirm that it does not block |
| -- 5. Stop the mirror |
| -- 6. Reset the walsender and the transaction should complete without waiting for syncrep |
| |
| -- Setup: |
| -- set mirror down grace period to zero to instantly mark mirror down. |
| -- the 1Uq and 1U pair will force a wait on the config reload. |
| !\retcode gpconfig -c gp_fts_mark_mirror_down_grace_period -v 2; |
| !\retcode gpstop -u; |
| 1Uq: |
| 1U: show gp_fts_mark_mirror_down_grace_period; |
| -- Enable tuple hints so that buffer will be marked dirty upon a hint bit change |
| -- (so that we don't have to wait for the tuple to age. See logic in markDirty) |
| 1U: SET gp_disable_tuple_hints=off; |
| Truncate select_throttle; |
| INSERT INTO select_throttle SELECT generate_series (1, 100000); |
| -- flush the data to disk |
| checkpoint; |
| -- Suspend walsender |
| SELECT gp_inject_fault_infinite('wal_sender_loop', 'suspend', dbid) FROM gp_segment_configuration WHERE role = 'p' and content = 1; |
| |
| checkpoint; |
| -- SELECT will set the hint bit on (the buffer will be marked dirty) |
| -- This query should wait for Syncrep since its WAL size for hint bits is greater than wait_for_replication_threshold |
| 1U&: SELECT count(*) FROM select_throttle; |
| |
| -- check if the above query is waiting on SyncRep in pg_stat_activity |
| SELECT is_query_waiting_for_syncrep(50, 'SELECT count(*) FROM select_throttle;'); |
| |
| -- while SELECT is waiting for syncrep, it should not block a subsequent checkpoint |
| CHECKPOINT; |
| |
| -- stop the mirror should turn off syncrep |
| SELECT pg_ctl(datadir, 'stop', 'immediate') FROM gp_segment_configuration WHERE content=1 AND role = 'm'; |
| |
| -- reset walsender and let it exit so that mirror stop can be detected |
| SELECT gp_inject_fault_infinite('wal_sender_loop', 'reset', dbid) FROM gp_segment_configuration WHERE role = 'p' and content = 1; |
| |
| -- perform fts probe scan and verify that mirror is down |
| select wait_for_mirror_down(1::smallint, 30); |
| select content, role, preferred_role, mode, status from gp_segment_configuration where content = 1; |
| |
| -- after mirror is stopped, the SELECT query should proceed without waiting for syncrep |
| 1U<: |
| |
| -- Cleanup |
| 1U: RESET gp_disable_tuple_hints; |
| -- reset the mirror down grace period back to its default value. |
| -- the 1Uq and 1U pair will force a wait on the config reload. |
| !\retcode gpconfig -r gp_fts_mark_mirror_down_grace_period; |
| !\retcode gpstop -u; |
| 1Uq: |
| 1U: show gp_fts_mark_mirror_down_grace_period; |
| |
| ALTER SYSTEM RESET wait_for_replication_threshold; |
| SELECT pg_reload_conf(); |
| |
| !\retcode gprecoverseg -av; |
| SELECT wait_until_all_segments_synchronized(); |