Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequelize Transactions : ER_LOCK_WAIT_TIMEOUT

i've problem with sequelize transactions with mysql(5.6.17),i've one insert statement and two updates which should all done or none,howerver in the end transactions.create seems rolling back but driver.update executes and doesn't rollback and third update which is trip.update statement without any changes or rollback,the console hangs and after a few seconds throw this error:

Executing (42a68c8e-8347-45af-b9a2-7b0e7a89606b): START TRANSACTION;
Executing (42a68c8e-8347-45af-b9a2-7b0e7a89606b): SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
Executing (42a68c8e-8347-45af-b9a2-7b0e7a89606b): SET autocommit = 1;
Executing (42a68c8e-8347-45af-b9a2-7b0e7a89606b): INSERT INTO `transactions` (`id`,`tId`,`total_price`,`company_share`,`driver_share`,`at`) VALUES (DEFAULT,'13',1000,100,900,'2016-07-04 10:44:43');
Executing (default): UPDATE `driver` SET `balance`=`balance` - 100 WHERE `id` = '1'
Executing (default): UPDATE `trip` SET `paid`=1 WHERE `id` = '13'
Executing (42a68c8e-8347-45af-b9a2-7b0e7a89606b): ROLLBACK;
5---SequelizeDatabaseError: ER_LOCK_WAIT_TIMEOUT: Lock wait timeout exceeded; try restarting transaction

the transaction section is:

var Sequelize = require('sequelize');
var config = {};
config.sequelize = new Sequelize('mydb', 'root', null, {
    host: 'localhost',
    port: 3306,
    dialect: 'mysql',
    logging: true,
    pool: {
        max: 100,
        min: 0,
        idle: 10000
    },
    define: {
        timestamps: false
    }
});
require('sequelize-isunique-validator')(Sequelize);
var driver = require('./../models/driver.js')(config.sequelize, Sequelize);
var transactions = require('./../models/transactions.js')(config.sequelize, Sequelize);
var trip = require('./../models/trip.js')(config.sequelize, Sequelize);


return config.sequelize.transaction({isolationLevel:Sequelize.Transaction.ISOLATION_LEVELS.READ_COMMITTED},function (t) {
return transactions.create({tId: tripId, total_price: totalPrice, company_share: companyShare, driver_share: driverShare}, {transaction: t})
    .then(function (result) {
    return driver.update({balance: config.sequelize.literal('`balance` - '+companyShare)}, {where: {id: dId}}, {transaction: t})
        .then(function (result) {
            return trip.update({paid: 1}, {where: {id: tripId}}, {transaction: t});
        });
});

}).then(function (result) {
    RequestQueue.hmset(ticket,"ticketState",value.Paid);
    res.json({'status': 'success','change':(-company_share)});
}).catch(function (err) {
    global.console.log('5---'+err);
    res.json({'status': 'failed'});
});

I'm sure my models are correct because I used them somewhere else without any problem on crud and not putting them here in order to keeps the question clean and on topic but if it helps ask in comments,tnx!

like image 965
A.R.H Avatar asked Jul 04 '16 11:07

A.R.H


People also ask

What does error 1205 lock wait timeout exceeded mean?

SQLSTATE [HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction The above simply means the transaction has reached the innodb_lock_wait_timeout while waiting to obtain an exclusive lock which defaults to 50 seconds. The common causes are:

What does lock wait timeout exceeded mean in InnoDB?

One of the most popular InnoDB’s errors is InnoDB lock wait timeout exceeded, for example: SQLSTATE [HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction The above simply means the transaction has reached the innodb_lock_wait_timeout while waiting to obtain an exclusive lock which defaults to 50 seconds.

How to set query timeout in Sequelize V5?

If someone stumbles here looking for Postgres specific config (i.e. node-postgres) for query timeout, it looks like this in sequelize v5: dialectOptions: { statement_timeout: 1000, idle_in_transaction_session_timeout: 5000 } This will set statement_timeout to 1s and idle_in_transaction_session_timeout to 5s.

How can I Pass native Sequelize errors to the match array?

This behaviour can be natively enabled by adding a retry object to the list of options provided when initializing Sequelize: As you can see, we can pass native Sequelize errors to the match array. Now you might be thinking "Ok, but the deadlock error is actually a “SequelizeDatabaseError” - so how can we specifically filter that one out?"


1 Answers

You should pass the transaction parameter inside the options object.

    .then(function (result) {
        return driver.update({balance: config.sequelize.literal('`balance` - ' + companyShare)}, {
                    where: {id: dId},
                    transaction: t
                })
                .then(function (result) {
                    return trip.update({paid: 1}, {where: {id: tripId}, transaction: t});
                });

http://docs.sequelizejs.com/en/latest/api/model/#update

like image 118
Adam Avatar answered Oct 11 '22 14:10

Adam