mirror of https://github.com/postgres/postgres
This clause changes the behavior of SELECT locking clauses in the presence of locked rows: instead of causing a process to block waiting for the locks held by other processes (or raise an error, with NOWAIT), SKIP LOCKED makes the new reader skip over such rows. While this is not appropriate behavior for general purposes, there are some cases in which it is useful, such as queue-like tables. Catalog version bumped because this patch changes the representation of stored rules. Reviewed by Craig Ringer (based on a previous attempt at an implementation by Simon Riggs, who also provided input on the syntax used in the current patch), David Rowley, and Álvaro Herrera. Author: Thomas Munropull/14/head
parent
c421efd213
commit
df630b0dd5
@ -0,0 +1,31 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* lockwaitpolicy.h |
||||
* Header file for LockWaitPolicy enum. |
||||
* |
||||
* Copyright (c) 2014, PostgreSQL Global Development Group |
||||
* |
||||
* src/include/utils/lockwaitpolicy.h |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#ifndef LOCKWAITPOLICY_H |
||||
#define LOCKWAITPOLICY_H |
||||
|
||||
/*
|
||||
* This enum controls how to deal with rows being locked by FOR UPDATE/SHARE |
||||
* clauses (i.e., NOWAIT and SKIP LOCKED clauses). The ordering here is |
||||
* important, because the highest numerical value takes precedence when a |
||||
* RTE is specified multiple ways. See applyLockingClause. |
||||
*/ |
||||
typedef enum |
||||
{ |
||||
/* Wait for the lock to become available (default behavior) */ |
||||
LockWaitBlock, |
||||
|
||||
/* Skip rows that can't be locked (SKIP LOCKED) */ |
||||
LockWaitSkip, |
||||
|
||||
/* Raise an error if a row cannot be locked (NOWAIT) */ |
||||
LockWaitError |
||||
} LockWaitPolicy; |
||||
|
||||
#endif /* LOCKWAITPOLICY_H */ |
||||
@ -0,0 +1,49 @@ |
||||
Parsed test spec with 2 sessions |
||||
|
||||
starting permutation: s1a s2a s2b s1b s2c |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR SHARE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR SHARE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1b: COMMIT; |
||||
step s2c: COMMIT; |
||||
|
||||
starting permutation: s2a s1a s2b s1b s2c |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR SHARE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR SHARE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1b: COMMIT; |
||||
step s2c: COMMIT; |
||||
|
||||
starting permutation: s2a s2b s1a s1b s2c |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR SHARE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR SHARE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1b: COMMIT; |
||||
step s2c: COMMIT; |
||||
@ -0,0 +1,19 @@ |
||||
Parsed test spec with 3 sessions |
||||
|
||||
starting permutation: s1a s2a s3a s1b s2b s3b |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE LIMIT 1; <waiting ...> |
||||
step s3a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1b: COMMIT; |
||||
step s2a: <... completed> |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2b: COMMIT; |
||||
step s3b: COMMIT; |
||||
@ -0,0 +1,21 @@ |
||||
Parsed test spec with 2 sessions |
||||
|
||||
starting permutation: s2a s1a s2b s2c s2d s2e s1b s2f |
||||
step s2a: SELECT pg_advisory_lock(0); |
||||
pg_advisory_lock |
||||
|
||||
|
||||
step s1a: SELECT * FROM foo WHERE pg_advisory_lock(0) IS NOT NULL ORDER BY id LIMIT 1 FOR UPDATE SKIP LOCKED; <waiting ...> |
||||
step s2b: UPDATE foo SET data = data WHERE id = 1; |
||||
step s2c: BEGIN; |
||||
step s2d: UPDATE foo SET data = data WHERE id = 1; |
||||
step s2e: SELECT pg_advisory_unlock(0); |
||||
pg_advisory_unlock |
||||
|
||||
t |
||||
step s1a: <... completed> |
||||
id data |
||||
|
||||
2 x |
||||
step s1b: COMMIT; |
||||
step s2f: COMMIT; |
||||
@ -0,0 +1,19 @@ |
||||
Parsed test spec with 2 sessions |
||||
|
||||
starting permutation: s2a s1a s2b s2c s2d s2e s1b s2f |
||||
step s2a: SELECT pg_advisory_lock(0); |
||||
pg_advisory_lock |
||||
|
||||
|
||||
step s1a: SELECT * FROM foo WHERE pg_advisory_lock(0) IS NOT NULL ORDER BY id LIMIT 1 FOR UPDATE SKIP LOCKED; <waiting ...> |
||||
step s2b: UPDATE foo SET data = data WHERE id = 1; |
||||
step s2c: BEGIN; |
||||
step s2d: UPDATE foo SET data = data WHERE id = 1; |
||||
step s2e: SELECT pg_advisory_unlock(0); |
||||
pg_advisory_unlock |
||||
|
||||
t |
||||
step s1a: <... completed> |
||||
error in steps s2e s1a: ERROR: could not serialize access due to concurrent update |
||||
step s1b: COMMIT; |
||||
step s2f: COMMIT; |
||||
@ -0,0 +1,401 @@ |
||||
Parsed test spec with 2 sessions |
||||
|
||||
starting permutation: s1a s1b s1c s2a s2b s2c |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1c: COMMIT; |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2c: COMMIT; |
||||
|
||||
starting permutation: s1a s1b s2a s1c s2b s2c |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1c: COMMIT; |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2c: COMMIT; |
||||
|
||||
starting permutation: s1a s1b s2a s2b s1c s2c |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1c: COMMIT; |
||||
step s2c: COMMIT; |
||||
|
||||
starting permutation: s1a s1b s2a s2b s2c s1c |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2c: COMMIT; |
||||
step s1c: COMMIT; |
||||
|
||||
starting permutation: s1a s2a s1b s1c s2b s2c |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1c: COMMIT; |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2c: COMMIT; |
||||
|
||||
starting permutation: s1a s2a s1b s2b s1c s2c |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1c: COMMIT; |
||||
step s2c: COMMIT; |
||||
|
||||
starting permutation: s1a s2a s1b s2b s2c s1c |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2c: COMMIT; |
||||
step s1c: COMMIT; |
||||
|
||||
starting permutation: s1a s2a s2b s1b s1c s2c |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1c: COMMIT; |
||||
step s2c: COMMIT; |
||||
|
||||
starting permutation: s1a s2a s2b s1b s2c s1c |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2c: COMMIT; |
||||
step s1c: COMMIT; |
||||
|
||||
starting permutation: s1a s2a s2b s2c s1b s1c |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2c: COMMIT; |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1c: COMMIT; |
||||
|
||||
starting permutation: s2a s1a s1b s1c s2b s2c |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1c: COMMIT; |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2c: COMMIT; |
||||
|
||||
starting permutation: s2a s1a s1b s2b s1c s2c |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1c: COMMIT; |
||||
step s2c: COMMIT; |
||||
|
||||
starting permutation: s2a s1a s1b s2b s2c s1c |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2c: COMMIT; |
||||
step s1c: COMMIT; |
||||
|
||||
starting permutation: s2a s1a s2b s1b s1c s2c |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1c: COMMIT; |
||||
step s2c: COMMIT; |
||||
|
||||
starting permutation: s2a s1a s2b s1b s2c s1c |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2c: COMMIT; |
||||
step s1c: COMMIT; |
||||
|
||||
starting permutation: s2a s1a s2b s2c s1b s1c |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2c: COMMIT; |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1c: COMMIT; |
||||
|
||||
starting permutation: s2a s2b s1a s1b s1c s2c |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1c: COMMIT; |
||||
step s2c: COMMIT; |
||||
|
||||
starting permutation: s2a s2b s1a s1b s2c s1c |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2c: COMMIT; |
||||
step s1c: COMMIT; |
||||
|
||||
starting permutation: s2a s2b s1a s2c s1b s1c |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
2 bar NEW |
||||
step s2c: COMMIT; |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1c: COMMIT; |
||||
|
||||
starting permutation: s2a s2b s2c s1a s1b s1c |
||||
step s2a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s2c: COMMIT; |
||||
step s1a: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1b: SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; |
||||
id data status |
||||
|
||||
1 foo NEW |
||||
step s1c: COMMIT; |
||||
@ -0,0 +1,41 @@ |
||||
# Test SKIP LOCKED with multixact locks. |
||||
|
||||
setup |
||||
{ |
||||
CREATE TABLE queue ( |
||||
id int PRIMARY KEY, |
||||
data text NOT NULL, |
||||
status text NOT NULL |
||||
); |
||||
INSERT INTO queue VALUES (1, 'foo', 'NEW'), (2, 'bar', 'NEW'); |
||||
} |
||||
|
||||
teardown |
||||
{ |
||||
DROP TABLE queue; |
||||
} |
||||
|
||||
session "s1" |
||||
setup { BEGIN; } |
||||
step "s1a" { SELECT * FROM queue ORDER BY id FOR SHARE SKIP LOCKED LIMIT 1; } |
||||
step "s1b" { COMMIT; } |
||||
|
||||
session "s2" |
||||
setup { BEGIN; } |
||||
step "s2a" { SELECT * FROM queue ORDER BY id FOR SHARE SKIP LOCKED LIMIT 1; } |
||||
step "s2b" { SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; } |
||||
step "s2c" { COMMIT; } |
||||
|
||||
# s1 and s2 both get SHARE lock, creating a multixact lock, then s2 |
||||
# tries to update to UPDATE but skips the record because it can't |
||||
# acquire a multixact lock |
||||
permutation "s1a" "s2a" "s2b" "s1b" "s2c" |
||||
|
||||
# the same but with the SHARE locks acquired in a different order, so |
||||
# s2 again skips because it can't acquired a multixact lock |
||||
permutation "s2a" "s1a" "s2b" "s1b" "s2c" |
||||
|
||||
# s2 acquires SHARE then UPDATE, then s1 tries to acquire SHARE but |
||||
# can't so skips the first record because it can't acquire a regular |
||||
# lock |
||||
permutation "s2a" "s2b" "s1a" "s1b" "s2c" |
||||
@ -0,0 +1,36 @@ |
||||
# Test SKIP LOCKED with tuple locks. |
||||
|
||||
setup |
||||
{ |
||||
CREATE TABLE queue ( |
||||
id int PRIMARY KEY, |
||||
data text NOT NULL, |
||||
status text NOT NULL |
||||
); |
||||
INSERT INTO queue VALUES (1, 'foo', 'NEW'), (2, 'bar', 'NEW'); |
||||
} |
||||
|
||||
teardown |
||||
{ |
||||
DROP TABLE queue; |
||||
} |
||||
|
||||
session "s1" |
||||
setup { BEGIN; } |
||||
step "s1a" { SELECT * FROM queue ORDER BY id FOR UPDATE LIMIT 1; } |
||||
step "s1b" { COMMIT; } |
||||
|
||||
session "s2" |
||||
setup { BEGIN; } |
||||
step "s2a" { SELECT * FROM queue ORDER BY id FOR UPDATE LIMIT 1; } |
||||
step "s2b" { COMMIT; } |
||||
|
||||
session "s3" |
||||
setup { BEGIN; } |
||||
step "s3a" { SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; } |
||||
step "s3b" { COMMIT; } |
||||
|
||||
# s3 skips to the second record because it can't obtain the tuple lock |
||||
# (s2 holds the tuple lock because it is next in line to obtain the |
||||
# row lock, and s1 holds the row lock) |
||||
permutation "s1a" "s2a" "s3a" "s1b" "s2b" "s3b" |
||||
@ -0,0 +1,36 @@ |
||||
# Test SKIP LOCKED with an updated tuple chain. |
||||
|
||||
setup |
||||
{ |
||||
CREATE TABLE foo ( |
||||
id int PRIMARY KEY, |
||||
data text NOT NULL |
||||
); |
||||
INSERT INTO foo VALUES (1, 'x'), (2, 'x'); |
||||
} |
||||
|
||||
teardown |
||||
{ |
||||
DROP TABLE foo; |
||||
} |
||||
|
||||
session "s1" |
||||
setup { BEGIN; } |
||||
step "s1a" { SELECT * FROM foo WHERE pg_advisory_lock(0) IS NOT NULL ORDER BY id LIMIT 1 FOR UPDATE SKIP LOCKED; } |
||||
step "s1b" { COMMIT; } |
||||
|
||||
session "s2" |
||||
step "s2a" { SELECT pg_advisory_lock(0); } |
||||
step "s2b" { UPDATE foo SET data = data WHERE id = 1; } |
||||
step "s2c" { BEGIN; } |
||||
step "s2d" { UPDATE foo SET data = data WHERE id = 1; } |
||||
step "s2e" { SELECT pg_advisory_unlock(0); } |
||||
step "s2f" { COMMIT; } |
||||
|
||||
# s1 takes a snapshot but then waits on an advisory lock, then s2 |
||||
# updates the row in one transaction, then again in another without |
||||
# committing, before allowing s1 to proceed to try to lock a row; |
||||
# because it has a snapshot that sees the older version, we reach the |
||||
# waiting code in EvalPlanQualFetch which skips rows when in SKIP |
||||
# LOCKED mode, so s1 sees the second row |
||||
permutation "s2a" "s1a" "s2b" "s2c" "s2d" "s2e" "s1b" "s2f" |
||||
@ -0,0 +1,28 @@ |
||||
# Test SKIP LOCKED when regular row locks can't be acquired. |
||||
|
||||
setup |
||||
{ |
||||
CREATE TABLE queue ( |
||||
id int PRIMARY KEY, |
||||
data text NOT NULL, |
||||
status text NOT NULL |
||||
); |
||||
INSERT INTO queue VALUES (1, 'foo', 'NEW'), (2, 'bar', 'NEW'); |
||||
} |
||||
|
||||
teardown |
||||
{ |
||||
DROP TABLE queue; |
||||
} |
||||
|
||||
session "s1" |
||||
setup { BEGIN; } |
||||
step "s1a" { SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; } |
||||
step "s1b" { SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; } |
||||
step "s1c" { COMMIT; } |
||||
|
||||
session "s2" |
||||
setup { BEGIN; } |
||||
step "s2a" { SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; } |
||||
step "s2b" { SELECT * FROM queue ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; } |
||||
step "s2c" { COMMIT; } |
||||
Loading…
Reference in new issue