why writes in a table prevent vacuums in another?

百般思念 提交于 2019-12-07 03:52:28

cant reproduce:

first session script:

-bash-4.2$ cat prim.sql
create table a (v int);
create table b (v int);
insert into a values (generate_series(1,1000));
update a set v = v + 1;
vacuum verbose a;
begin;
  insert into b values (generate_series(1,1000));
  select pg_sleep(9);
  select e'I\'m still open transaction'::text prim;

second session and check state:

-bash-4.2$ cat 1.sh
(sleep 3; psql t -c "vacuum verbose a;") &
(sleep 5; psql t -c "select state,query from pg_stat_activity where state != 'idle' and pid <> pg_backend_pid()") &
psql t -f prim.sql

and run:

-bash-4.2$ bash 1.sh
CREATE TABLE
CREATE TABLE
INSERT 0 1000
UPDATE 1000
psql:prim.sql:5: INFO:  vacuuming "public.a"
psql:prim.sql:5: INFO:  "a": removed 1000 row versions in 5 pages
psql:prim.sql:5: INFO:  "a": found 1000 removable, 1000 nonremovable row versions in 9 out of 9 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
VACUUM
BEGIN
INSERT 0 1000
INFO:  vacuuming "public.a"
INFO:  "a": found 0 removable, 1000 nonremovable row versions in 9 out of 9 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 1000 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
VACUUM
 state  |        query
--------+---------------------
 active | select pg_sleep(9);
(1 row)

 pg_sleep
----------

(1 row)

            prim
----------------------------
 I'm still open transaction
(1 row)

As you can see the first session was active before, while and after the vacuum in different session took place.

the version I tried at is:

t=# select version();
                                                   version
--------------------------------------------------------------------------------------------------------------
 PostgreSQL 9.3.14 on x86_64-redhat-linux-gnu, compiled by gcc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9), 64-bit
(1 row)

It is important to generate the dead rows again in a transaction started AFTER the transaction that remains open.

I have been able to reproduce the problem with the following versions:

  • PostgreSQL 9.3.19 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4, 64-bit

  • PostgreSQL 9.5.9 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4, 64-bit'

Following this question up via Twitter.

Current (at least up to PostgreSQL 9.6) behavior is:

Live transactions performing a write operation in any table will prevent vacuuming dead rows generated by commited transactions that started after first live transaction in any other table.

Even this limitation is not required from the conceptual point of view, it is how current algorithm is implemented for performance on checking dead rows reasons.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!