question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

mariadb transaction deadlock does not release connection

See original GitHub issue

Issue 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:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:12 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
tmontcommented, Oct 29, 2019

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.

0reactions
github-actions[bot]commented, Jan 27, 2021

🎉 This issue has been resolved in version 6.5.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found