postgresql/src/test/regress/expected/prepared_xacts_1.out
Alvaro Herrera d42358efb1 Have TRUNCATE update pgstat tuple counters
This works by keeping a per-subtransaction record of the ins/upd/del
counters before the truncate, and then resetting them; this record is
useful to return to the previous state in case the truncate is rolled
back, either in a subtransaction or whole transaction.  The state is
propagated upwards as subtransactions commit.

When the per-table data is sent to the stats collector, a flag indicates
to reset the live/dead counters to zero as well.

Catalog version bumped due to the change in pgstat format.

Author: Alexander Shulgin
Discussion: 1007.1207238291@sss.pgh.pa.us
Discussion: 548F7D38.2000401@BlueTreble.com
Reviewed-by: Álvaro Herrera, Jim Nasby
2015-02-20 12:10:01 -03:00

311 lines
7.2 KiB
Plaintext

--
-- PREPARED TRANSACTIONS (two-phase commit)
--
-- We can't readily test persistence of prepared xacts within the
-- regression script framework, unfortunately. Note that a crash
-- isn't really needed ... stopping and starting the postmaster would
-- be enough, but we can't even do that here.
-- create a simple table that we'll use in the tests
CREATE TABLE pxtest1 (foobar VARCHAR(10));
INSERT INTO pxtest1 VALUES ('aaa');
-- Test PREPARE TRANSACTION
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
UPDATE pxtest1 SET foobar = 'bbb' WHERE foobar = 'aaa';
SELECT * FROM pxtest1;
foobar
--------
bbb
(1 row)
PREPARE TRANSACTION 'foo1';
ERROR: prepared transactions are disabled
HINT: Set max_prepared_transactions to a nonzero value.
SELECT * FROM pxtest1;
foobar
--------
aaa
(1 row)
-- Test pg_prepared_xacts system view
SELECT gid FROM pg_prepared_xacts;
gid
-----
(0 rows)
-- Test ROLLBACK PREPARED
ROLLBACK PREPARED 'foo1';
ERROR: prepared transaction with identifier "foo1" does not exist
SELECT * FROM pxtest1;
foobar
--------
aaa
(1 row)
SELECT gid FROM pg_prepared_xacts;
gid
-----
(0 rows)
-- Test COMMIT PREPARED
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
INSERT INTO pxtest1 VALUES ('ddd');
SELECT * FROM pxtest1;
foobar
--------
aaa
ddd
(2 rows)
PREPARE TRANSACTION 'foo2';
ERROR: prepared transactions are disabled
HINT: Set max_prepared_transactions to a nonzero value.
SELECT * FROM pxtest1;
foobar
--------
aaa
(1 row)
COMMIT PREPARED 'foo2';
ERROR: prepared transaction with identifier "foo2" does not exist
SELECT * FROM pxtest1;
foobar
--------
aaa
(1 row)
-- Test duplicate gids
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
UPDATE pxtest1 SET foobar = 'eee' WHERE foobar = 'ddd';
SELECT * FROM pxtest1;
foobar
--------
aaa
(1 row)
PREPARE TRANSACTION 'foo3';
ERROR: prepared transactions are disabled
HINT: Set max_prepared_transactions to a nonzero value.
SELECT gid FROM pg_prepared_xacts;
gid
-----
(0 rows)
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
INSERT INTO pxtest1 VALUES ('fff');
-- This should fail, because the gid foo3 is already in use
PREPARE TRANSACTION 'foo3';
ERROR: prepared transactions are disabled
HINT: Set max_prepared_transactions to a nonzero value.
SELECT * FROM pxtest1;
foobar
--------
aaa
(1 row)
ROLLBACK PREPARED 'foo3';
ERROR: prepared transaction with identifier "foo3" does not exist
SELECT * FROM pxtest1;
foobar
--------
aaa
(1 row)
-- Test serialization failure (SSI)
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
UPDATE pxtest1 SET foobar = 'eee' WHERE foobar = 'ddd';
SELECT * FROM pxtest1;
foobar
--------
aaa
(1 row)
PREPARE TRANSACTION 'foo4';
ERROR: prepared transactions are disabled
HINT: Set max_prepared_transactions to a nonzero value.
SELECT gid FROM pg_prepared_xacts;
gid
-----
(0 rows)
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT * FROM pxtest1;
foobar
--------
aaa
(1 row)
-- This should fail, because the two transactions have a write-skew anomaly
INSERT INTO pxtest1 VALUES ('fff');
PREPARE TRANSACTION 'foo5';
ERROR: prepared transactions are disabled
HINT: Set max_prepared_transactions to a nonzero value.
SELECT gid FROM pg_prepared_xacts;
gid
-----
(0 rows)
ROLLBACK PREPARED 'foo4';
ERROR: prepared transaction with identifier "foo4" does not exist
SELECT gid FROM pg_prepared_xacts;
gid
-----
(0 rows)
-- Clean up
DROP TABLE pxtest1;
-- Test subtransactions
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
CREATE TABLE pxtest2 (a int);
INSERT INTO pxtest2 VALUES (1);
SAVEPOINT a;
INSERT INTO pxtest2 VALUES (2);
ROLLBACK TO a;
SAVEPOINT b;
INSERT INTO pxtest2 VALUES (3);
PREPARE TRANSACTION 'regress-one';
ERROR: prepared transactions are disabled
HINT: Set max_prepared_transactions to a nonzero value.
CREATE TABLE pxtest3(fff int);
-- Test shared invalidation
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
DROP TABLE pxtest3;
CREATE TABLE pxtest4 (a int);
INSERT INTO pxtest4 VALUES (1);
INSERT INTO pxtest4 VALUES (2);
DECLARE foo CURSOR FOR SELECT * FROM pxtest4;
-- Fetch 1 tuple, keeping the cursor open
FETCH 1 FROM foo;
a
---
1
(1 row)
PREPARE TRANSACTION 'regress-two';
ERROR: prepared transactions are disabled
HINT: Set max_prepared_transactions to a nonzero value.
-- No such cursor
FETCH 1 FROM foo;
ERROR: cursor "foo" does not exist
-- Table doesn't exist, the creation hasn't been committed yet
SELECT * FROM pxtest2;
ERROR: relation "pxtest2" does not exist
LINE 1: SELECT * FROM pxtest2;
^
-- There should be two prepared transactions
SELECT gid FROM pg_prepared_xacts;
gid
-----
(0 rows)
-- pxtest3 should be locked because of the pending DROP
set statement_timeout to 2000;
SELECT * FROM pxtest3;
fff
-----
(0 rows)
reset statement_timeout;
-- Disconnect, we will continue testing in a different backend
\c -
-- There should still be two prepared transactions
SELECT gid FROM pg_prepared_xacts;
gid
-----
(0 rows)
-- pxtest3 should still be locked because of the pending DROP
set statement_timeout to 2000;
SELECT * FROM pxtest3;
fff
-----
(0 rows)
reset statement_timeout;
-- Commit table creation
COMMIT PREPARED 'regress-one';
ERROR: prepared transaction with identifier "regress-one" does not exist
\d pxtest2
SELECT * FROM pxtest2;
ERROR: relation "pxtest2" does not exist
LINE 1: SELECT * FROM pxtest2;
^
-- There should be one prepared transaction
SELECT gid FROM pg_prepared_xacts;
gid
-----
(0 rows)
-- Commit table drop
COMMIT PREPARED 'regress-two';
ERROR: prepared transaction with identifier "regress-two" does not exist
SELECT * FROM pxtest3;
fff
-----
(0 rows)
-- There should be no prepared transactions
SELECT gid FROM pg_prepared_xacts;
gid
-----
(0 rows)
CREATE TABLE pxtest5 (a SERIAL);
INSERT INTO pxtest5 DEFAULT VALUES;
SELECT * FROM pxtest5;
a
---
1
(1 row)
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
INSERT INTO pxtest5 DEFAULT VALUES;
INSERT INTO pxtest5 DEFAULT VALUES;
TRUNCATE pxtest5;
INSERT INTO pxtest5 DEFAULT VALUES;
PREPARE TRANSACTION 'trunc-and-pgstat';
ERROR: prepared transactions are disabled
HINT: Set max_prepared_transactions to a nonzero value.
SELECT pg_sleep(0.5);
pg_sleep
----------
(1 row)
SELECT n_tup_ins, n_tup_upd, n_tup_del, n_live_tup, n_dead_tup
FROM pg_stat_user_tables
WHERE relname='pxtest5';
n_tup_ins | n_tup_upd | n_tup_del | n_live_tup | n_dead_tup
-----------+-----------+-----------+------------+------------
3 | 0 | 0 | 1 | 2
(1 row)
COMMIT PREPARED 'trunc-and-pgstat';
ERROR: prepared transaction with identifier "trunc-and-pgstat" does not exist
SELECT pg_sleep(0.5);
pg_sleep
----------
(1 row)
SELECT n_tup_ins, n_tup_upd, n_tup_del, n_live_tup, n_dead_tup
FROM pg_stat_user_tables
WHERE relname='pxtest5';
n_tup_ins | n_tup_upd | n_tup_del | n_live_tup | n_dead_tup
-----------+-----------+-----------+------------+------------
3 | 0 | 0 | 1 | 2
(1 row)
SELECT * FROM pxtest5;
a
---
1
(1 row)
-- Clean up
DROP TABLE pxtest2;
ERROR: table "pxtest2" does not exist
DROP TABLE pxtest3; -- will still be there if prepared xacts are disabled
DROP TABLE pxtest4;
ERROR: table "pxtest4" does not exist
DROP TABLE pxtest5;