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.

Deadlock on multiple transactions

See original GitHub issue

What are you doing?

const Sequelize = require('sequelize');
const sequelize = new Sequelize('mysql://user:password@dburl:3306/test')

class TestUser extends Sequelize.Model {}
TestUser.init({
  username: Sequelize.STRING,
  birthday: Sequelize.DATE
}, { sequelize, modelName: 'testuser' })

for (var i = 0; i < 5; i++) {
    sequelize.transaction(t => {
        return TestUser.findOne({
            where: { username: 'janedoe' }
        }, { transaction: t })
        .then(user => {
            return TestUser.update(
                { birthday: new Date(1980, 1, 8) },
                {
                    where: { username: 'janedoe' }
                },
                { transaction: t }
            )
        })
    })
    .then(() => console.log('done'))
    .catch(err => console.log(err))
}

The loop is to mimic consecutive requests to a server. Adjusting the loop count below the connection pool max (default is 5) stops the problem.

To Reproduce Steps to reproduce the behavior:

  1. Run the quick example in the documentation (to create an entry)
  2. Run the code above
  3. See all of updates above fail

What do you expect to happen?

Update the entry successfully.

What is actually happening?

Executing (acafd742-e1e0-4181-be35-ded526d3d4d6): START TRANSACTION;
Executing (358028a0-3206-4262-b96a-f06f9359ecb8): START TRANSACTION;
Executing (eb448c6b-2098-499c-8d60-b6b4c83b2c23): START TRANSACTION;
Executing (cd0d76fc-78a0-4799-bcce-82451fcc38fd): START TRANSACTION;
Executing (23e9b61e-91ab-4764-85a3-98893e0d0f5a): START TRANSACTION;
Executing (acafd742-e1e0-4181-be35-ded526d3d4d6): ROLLBACK;
Executing (358028a0-3206-4262-b96a-f06f9359ecb8): ROLLBACK;
Executing (eb448c6b-2098-499c-8d60-b6b4c83b2c23): ROLLBACK;
Executing (cd0d76fc-78a0-4799-bcce-82451fcc38fd): ROLLBACK;
Executing (23e9b61e-91ab-4764-85a3-98893e0d0f5a): ROLLBACK;
{ SequelizeConnectionAcquireTimeoutError: Operation timeout
...

Environment

Dialect:

  • mysql
  • postgres
  • sqlite
  • mssql
  • any

Dialect library version: 1.6.5 Database version: 5.7.24 Sequelize version: 5.8.7 Node Version: 8.12.0 OS: Linux 4.19.23-gentoo (x86_64) If TypeScript related: TypeScript version: N/A

Tested with latest release:

  • No
  • Yes, specify that version: 5.8.7

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:4
  • Comments:17 (7 by maintainers)

github_iconTop GitHub Comments

7reactions
agirorncommented, Oct 31, 2019

I believe I have a workaround using p-queue.

const Sequelize = require('sequelize');
const {default: PQueue} = require('p-queue');
const sequelize = new Sequelize('mysql://user:password@dburl:3306/test')

const sequelize.queue = new PQueue({concurrency: (sequelize.connectionManager.pool.maxSize -1)});
const inTransaction = fn => sequelize.queue.add(
  () => sequelize.transaction((transaction) => fn(transaction)),
);

class TestUser extends Sequelize.Model {}
TestUser.init({
  username: Sequelize.STRING,
  birthday: Sequelize.DATE
}, { sequelize, modelName: 'testuser' })

for (var i = 0; i < 5; i++) {
    inTransaction(t => {
        return TestUser.findOne({
            where: { username: 'janedoe' }
        }, { transaction: t })
        .then(user => {
            return TestUser.update(
                { birthday: new Date(1980, 1, 8) },
                {
                    where: { username: 'janedoe' }
                },
                { transaction: t }
            )
        })
    })
    .then(() => console.log('done'))
    .catch(err => console.log(err))
}

Maybe this could be worked into Sequelize.transaction() so that it works out of the box.

3reactions
mycobococommented, Jul 30, 2019

Thanks for your reply, @papb. I’m glad to hear that you consider this what should be handled by Sequelize and looking forward to the day I can send a bunch of requests without worry about queueing.

Read more comments on GitHub >

github_iconTop Results From Across the Web

The Cause of Every Deadlock in SQL Server - Geek Speak
A deadlock happens when two (or more) transactions block each other by holding locks on resources that each of the transactions also need....
Read more >
Deadlock in Single Query Transactions
At least two transactions must be involved and one transaction must be modifying rows. ... Multiple transactions updating table data using ...
Read more >
Deadlock when multiple stored procedures are reading and ...
Transaction (Process ID XXX) was deadlocked on lock resources with another process and has been chosen as the deadlock victim.
Read more >
How to resolve deadlocks in SQL Server - SQLShack
A deadlock problem occurs when two (or more than two) operations already want to access resources locked by the other one. In this...
Read more >
MySQL - How can a deadlock b caused by the same ...
Transaction 2 gets a shared lock on single record · Transaction 1 takes an exclusive lock on range of records · Transaction 2...
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