mariadb transaction deadlock does not release connection
See original GitHub issueIssue Description
What are you doing?
Link to SSCCE PR: https://github.com/papb/sequelize-sscce/pull/15
"use strict";
const CONFIG = require("../config");
const Sequelize = require("sequelize");
async function main() {
const sequelize = new Sequelize(CONFIG.dbUrl, {
pool: { max: 2, acquire: 1000 },
keepDefaultTimezone: true, timezone: "" /* Suppress timezone warnings */
});
await sequelize.query("DROP TABLE IF EXISTS test1");
await sequelize.query("CREATE TABLE test1 (id INT NOT NULL PRIMARY KEY)");
await sequelize.query("DROP TABLE IF EXISTS test2");
await sequelize.query("CREATE TABLE test2 (id INT NOT NULL PRIMARY KEY)");
await sequelize.query("INSERT INTO test1 VALUES (1)");
await sequelize.query("INSERT INTO test2 VALUES (1)");
let t1 = await sequelize.transaction();
let t2 = await sequelize.transaction();
await sequelize.query("UPDATE test1 SET id = id WHERE id = 1", { transaction: t1 });
await sequelize.query("UPDATE test2 SET id = id WHERE id = 1", { transaction: t2 });
/* This query will wait on t2, don't block on it */
sequelize.query("UPDATE test2 SET id = id WHERE id = 1", { transaction: t1 });
try {
await sequelize.query("UPDATE test1 SET id = id WHERE id = 1", { transaction: t2 });
} catch (e) {
console.log(e.message);
console.log("t2 status is " + t2.finished);
/* Cannot `t2.rollback()` here because it is marked as finished */
}
try {
let t3 = await sequelize.transaction();
} catch (e) {
console.log(e.stack);
}
}
main().then(() => process.exit(0));
What do you expect to happen?
The second query in t1
will wait for t2
, and the second query of t2
will result in a deadlock. After this, t2
should be rolled back, so we should have one available connection to start t3
.
What is actually happening?
[...initial setup...]
Executing (68180761-6e97-443c-a070-9ca00810e563): START TRANSACTION;
Executing (50539931-2dd5-4b45-be57-6747c2af47e9): START TRANSACTION;
Executing (68180761-6e97-443c-a070-9ca00810e563): UPDATE test1 SET id = id WHERE id = 1
Executing (50539931-2dd5-4b45-be57-6747c2af47e9): UPDATE test2 SET id = id WHERE id = 1
Executing (68180761-6e97-443c-a070-9ca00810e563): UPDATE test2 SET id = id WHERE id = 1
Executing (50539931-2dd5-4b45-be57-6747c2af47e9): UPDATE test1 SET id = id WHERE id = 1
(conn=5493, no: 1213, SQLState: 40001) Deadlock found when trying to get lock; try restarting transaction
sql: UPDATE test1 SET id = id WHERE id = 1 - parameters:[]
t2 status is rollback
SequelizeConnectionAcquireTimeoutError: Operation timeout
at [project]/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:282:52
After one second of waiting, the timeout error is thrown for t3
.
Additional context
The problem seems to be these lines in mariadb/query.js
:
59 // MariaDB automatically rolls-back transactions in the event of a deadlock
60 if (options.transaction && err.errno === 1213) {
61 options.transaction.finished = 'rollback';
62 }
These mark the transaction as rolled back, but do not call cleanup
to release the connection. (Adding t2.cleanup()
in the catch seems to solve the problem.)
Environment
- Sequelize version:
sequelize@5.19.8
- Node.js version:
v12.11.1
- Operating System: Ubuntu
Issue Template Checklist
How does this problem relate to dialects?
- I think this problem happens regardless of the dialect.
- I think this problem happens only for the following dialect(s): mariadb and mysql
- I don’t know, I was using PUT-YOUR-DIALECT-HERE, with connector library version XXX and database version XXX
Tested with mariadb, but the same lines appear in mysql/query.js
.
Would you be willing to resolve this issue by submitting a Pull Request?
- Yes, I have the time and I know how to start.
- Yes, I have the time but I don’t know how to start, I would need guidance.
- No, I don’t have the time, although I believe I could do it if I had the time…
- No, I don’t have the time and I wouldn’t even know how to start.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:2
- Comments:12 (7 by maintainers)
Top Results From Across the Web
MariaDB Deadlocks | FromDual
connections do something ( INSERT , UPDATE , REPLACE , DELETE , SELECT FOR UPDATE ) on the same rows (which then are...
Read more >MariaDB Transactions and Isolation Levels for SQL Server ...
No data access is possible outside a transaction. ... by another transaction, our transaction is queued until that lock is released.
Read more >MariaDB (InnoDB) client disconnect release lock timeout
The session could be terminated normally or unexpectedly, but the locks will be released regardless. The session/client could of course also release the...
Read more >deadlock transaction hang up when connection is broken
Deadlcok hangup can be solved by turning dead lock check on. ... If connection is broken, monitor will mark the transaction unusable and...
Read more >MySQL/MariaDB - Identifying and Avoiding Deadlocks
A deadlock is a special blocking scenario when two or more competing transactions are waiting for each other to free locks.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
I ran into this same issue. I can confirm the same lack of cleanup occurs on MySQL 5.7 as well.
I can also confirm that it only seems to happen for deadlocks; other types of errors (lock wait timeouts, unique constraint errors) all cleaned up properly.
🎉 This issue has been resolved in version 6.5.0 🎉
The release is available on:
Your semantic-release bot 📦🚀