| -- @Description Test scenario where a backend accesses AO table with a snapshot |
| -- that was acquired before vacuum. |
| -- |
| DROP TABLE IF EXISTS ao; |
| DROP |
| CREATE TABLE ao (a INT, b INT) USING @amname@; |
| CREATE |
| INSERT INTO ao SELECT i as a, i as b FROM generate_series(1, 100) AS i; |
| INSERT 100 |
| |
| DELETE FROM ao WHERE a <= 30; |
| DELETE 30 |
| |
| create or replace function myfunc() returns bigint as $$ begin /* inside a function */ perform pg_sleep(10); /* inside a function */ return (select count(*) from ao); /* inside a function */ end; /* inside a function */ $$ stable language plpgsql; |
| CREATE |
| |
| -- Launch function into the background. |
| 1&: select myfunc(); <waiting ...> |
| |
| -- Meanwhile, DELETE some rows and VACUUM. VACUUM should not recycle the |
| -- old tuple versions that are still needed by the function later. It will |
| -- compact the segfile, but keep the old segfile in AWAITING_DROP state. |
| 2: DELETE FROM ao WHERE a <= 50; |
| DELETE 20 |
| 2: SELECT segno, tupcount, state FROM gp_ao_or_aocs_seg('ao'); |
| segno | tupcount | state |
| -------+----------+------- |
| 0 | 100 | 1 |
| (1 row) |
| 2: VACUUM ao; |
| VACUUM |
| 2: SELECT segno, tupcount, state FROM gp_ao_or_aocs_seg('ao'); |
| segno | tupcount | state |
| -------+----------+------- |
| 0 | 100 | 2 |
| 1 | 50 | 1 |
| (2 rows) |
| |
| -- A second VACUUM shouldn't recycle them either. |
| 2: VACUUM ao; |
| VACUUM |
| 2: SELECT segno, tupcount, state FROM gp_ao_or_aocs_seg('ao'); |
| segno | tupcount | state |
| -------+----------+------- |
| 0 | 100 | 2 |
| 1 | 50 | 1 |
| (2 rows) |
| 1<: <... completed> |
| myfunc |
| -------- |
| 70 |
| (1 row) |
| |
| -- Now that the first transaction has finished, VACUUM can recycle. |
| 2: VACUUM ao; |
| VACUUM |
| 2: SELECT segno, tupcount, state FROM gp_ao_or_aocs_seg('ao'); |
| segno | tupcount | state |
| -------+----------+------- |
| 0 | 0 | 1 |
| 1 | 50 | 1 |
| (2 rows) |