Consider the code below that gets some data from an external service and inserts it into some table in a database. It starts the transactions and commits it when all the data is inserted or rolls it back if an error occurres:
const mysql = require('mysql2/promise');
class SomeClass
{
async connect(params)
{
this.db = await mysql.createConnection(params);
}
async insertSomeRowsIntoSomeTable()
{
await this.db.execute('START TRANSACTION;');
try {
for (let i = 0; i < 100; i++) {
//get the values to insert from an external service, for example.
await const values = service.getValues();
await this.db.execute('INSERT SomeTable .... <the values>...');
}
await this.db.execute('COMMIT;');
}
catch (e) {
await this.db.execute('ROLLBACK;');
}
}
}
but what if there is another async method updateSomething that updates a row in some table with a single update query and the client calls it while insertSomeRowsIntoSomeTable method is still running? Obviously, the updated data will be lost if the an error occurres in insertSomeRowsIntoSomeTable.
If there is another method that initiates its own transaction, for example, we unexpectedly get the nested transaction.
The only idea I have at the moment is to make all the operations with the database atomic by moving all the transaction logic to the stored procedures, for example, but it look like a workaround but not a solution.
Having a separate database connection in each async method is not an option, for the obvious reasons.
Does anyone have a better idea?
db) for all methods of your instance. Use on connection per transaction/method, and pool them.