Transaction Retry¶
When using serializable transactions, it's often necessary to employ a retry strategy in case of serialization failure.
The algorthms
are fairly typical, so repeating them manually doesn't always make a lot of sense. omni_txn
provides retry
procedure
to handle such typical cases.
Parameter | Type | Description |
---|---|---|
stmts | text | Statement(s) to execute. Multiple statements separated by semicolon. |
max_attempts | int | Max number of times to retry. 0 means no retries. 10 by default. |
repeatable_read | boolean | Use REPEATABLE READ instead of SERIALIZABLE . False by default. |
collect_backoff_values | boolean | Collect actual backoff values for inspection. False by default. |
params | record | A record of parameters to pass to the statement. NULL by default |
linearize | boolean | If a transaction should be linearized (experimental). False by default. |
Retry attempt¶
There is a helper function omni_txn.current_retry_attempt()
that provides retry attempt during the retry()
call. 0
stands
for the first run, 1 for the first retry, etc.
Example¶
Let's consider the following schema:
create table inventory
(
id serial primary key,
product_name text,
quantity int
);
insert into inventory (product_name, quantity)
values ('Widget', 100);
Now, if we have these two simultaneous transactions happening, the second one may have committed first:
--- Transaction (1)
begin;
select quantity
from inventory
where product_name = 'Widget';
--- and here (2) will happen
update inventory
set quantity = quantity + 20
where product_name = 'Widget';
commit;
-- ERROR: could not serialize access due to read/write dependencies among transactions
--- Transaction (2)
begin;
update inventory
set quantity = quantity - 10
where product_name = 'Widgert';
commit;
If we use omni_txn.retry
, the failed transaction can be driven to completion:
--- (1)
call omni_txn.retry($$
select quantity from inventory where product_name = 'Widget';
update inventory set quantity = quantity + 20
where product_name = 'Widget'
$$);
--- (2)
call omni_txn.retry($$
update inventory set quantity = quantity - 10
where product_name = 'Widgert'
$$);
Parameterized statements¶
Statement(s) passed to omni_txn.retry
can be parameterized with the params
argument:
Debugging¶
omni_txn.retry
will cache prepared statement plans for every new statement provided. To see the list of currently
cached planned statements, query omni_txn.retry_prepared_statements
view. If you want to reset the cache, query
select omni_txn.reset_retry_prepared_statements()
.