[英]How to use database transactions in JavaScript with async functions?
考慮下面的代碼,它從外部服務獲取一些數據並將其插入到數據庫中的某個表中。 它啟動事務並在插入所有數據時提交它,如果發生錯誤則將其回滾:
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;');
}
}
}
但是,如果有另一個異步方法updateSomething
使用單個更新查詢更新某個表中的一行,並且客戶端在insertSomeRowsIntoSomeTable
方法仍在運行時調用它,該怎么辦? 顯然,如果insertSomeRowsIntoSomeTable
發生錯誤,更新的數據將會丟失。
如果有另一種方法發起自己的事務,例如,我們意外地得到了嵌套事務。
例如,我目前唯一的想法是通過將所有事務邏輯移動到存儲過程來使數據庫的所有操作成為原子操作,但這看起來像是一種解決方法,但不是解決方案。
出於顯而易見的原因,在每個異步方法中都有一個單獨的數據庫連接不是一種選擇。
有沒有人有更好的主意?
可能最簡單的解決方案是使用池:
const mysql = require('mysql2/promise');
class SomeClass
{
async connect(params)
{
this.db = mysql.createPool(params);
}
async insertSomeRowsIntoSomeTable()
{
const connection = await this.db.getConnection();
await connection.execute('START TRANSACTION;');
try {
for (let i = 0; i < 100; i++) {
//get the values to insert from an external service, for example.
const values = await service.getValues();
await conn.execute('INSERT SomeTable .... <the values>...');
}
await connection.execute('COMMIT');
await connection.release();
}
catch (e) {
await connection.execute('ROLLBACK');
await connection.release();
}
}
}
在這里,您從insertSomeRowsIntoSomeTable()
中的池中借用連接,如果其他異步函數遵循相同的模式,則此連接將僅由一個事務代碼路徑獨占使用,直到釋放
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.