Skip to content

sql: transactions that enter the "aborted" state due to SQL-level errors should relinquish locks #140234

@mgartner

Description

@mgartner

Since 719b702, which added support for savepoints, SQL-level errors that cause a transaction to enter the "aborted" state do not cause the transaction to end or rollback. As a result, any locks acquired in the transaction prior to the error remain held, blocking concurrent queries.

Here's an example:

CREATE TABLE t (k INT PRIMARY KEY, v INT);
-- CREATE

INSERT INTO t VALUES (1, 0);
-- INSERT 1

-- Session 1
BEGIN;
-- BEGIN

-- Session 1
UPDATE t SET v = 10 WHERE k = 1;
-- UPDATE 1

-- Session 1
SELECT 1/0;
-- ERROR: division by zero
-- SQLSTATE: 22012

-- Session 2
UPDATE t SET v = 100 WHERE k = 1;
-- Blocked by the "aborted" txn above.

-- Session 1
SELECT 1;
-- ERROR: current transaction is aborted, commands ignored until end of transaction block
-- SQLSTATE: 25P02

Once the transaction enters the "aborted" state, I believe it can never successfully commit, so holding the locks has no benefit and increases the chance of contention. This may only be true for transactions without savepoints—we should think through all possible cases here.

This creates some major rough edges with the transaction_timeout session setting. The docs state about this setting:

Aborts an explicit transaction when it runs longer than the configured duration. Stored in milliseconds; can be expressed in milliseconds or as an INTERVAL.

The name of the setting and this description make it sound like transaction_timeout is the perfect safeguard against a misbehaving application that fails to commit or rollback a transaction. However, due to the behavior described above, it actually provides no additional safety—while the transaction will be automatically aborted, any locks acquired will remain held and will not be released until the connection is closed.

Here's an example:

CREATE TABLE t (k INT PRIMARY KEY, v INT);
-- CREATE

-- Session 1
SET transaction_timeout = '8s';
-- SET

-- Session 1
BEGIN;
-- BEGIN

-- Session 1
UPDATE t SET v = 33 WHERE k =3;
-- UPDATE 1

-- Session 2
UPDATE t SET v = 333 WHERE k =3;
-- Hangs until the transaction in Session 1 is manually COMMITed or ABORTed.

-- Session 1
SELECT pg_sleep(100);
-- ERROR: query execution canceled due to transaction timeout
-- SQLSTATE: 57014

-- Session 1
SELECT 1;
-- ERROR: current transaction is aborted, commands ignored until end of transaction block

Jira issue: CRDB-47066

Metadata

Metadata

Assignees

Labels

C-enhancementSolution expected to add code/behavior + preserve backward-compat (pg compat issues are exception)T-sql-foundationsSQL Foundations Team (formerly SQL Schema + SQL Sessions)branch-release-20.1Used to mark GA and release blockers, technical advisories, and bugs for 20.1branch-release-20.2Used to mark GA and release blockers, technical advisories, and bugs for 20.2branch-release-21.1Used to mark GA and release blockers, technical advisories, and bugs for 21.1branch-release-21.2Used to mark GA and release blockers, technical advisories, and bugs for 21.2branch-release-22.1Used to mark GA and release blockers, technical advisories, and bugs for 22.1branch-release-22.2Used to mark GA and release blockers, technical advisories, and bugs for 22.2branch-release-23.1Used to mark GA and release blockers, technical advisories, and bugs for 23.1branch-release-23.2Used to mark GA and release blockers, technical advisories, and bugs for 23.2branch-release-24.1Used to mark GA and release blockers, technical advisories, and bugs for 24.1branch-release-24.2Used to mark GA and release blockers, technical advisories, and bugs for 24.2branch-release-24.3Used to mark GA and release blockers, technical advisories, and bugs for 24.3branch-release-25.1v25.2.0-prerelease

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions