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!
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:
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.
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.
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?"
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With