我正在使用带有 async/await 的 javascript 和 Node Express。所以只有一个线程/进程在运行,但它的执行方式并不简单。
异步方法可能会从 sqllite 数据库请求行。我正在使用这个 npm 包。 https://www.npmjs.com/package/sqlite
如果只是在异步方法中打开和关闭数据库,就像这样
async function request() {
var db = await sqlite.open({
filename: "filename.db",
mode: sqlite3.OPEN_READONLY,
driver: sqlite3.Database
})
//-- do something, like this
const stmt = await db.prepare("SELECT 1");
const rows = await stmt.all();
await stmt.finalize();
//-- then close
await actualDb.close();
}
这会引发“SQLITE_BUSY”错误。所以我做了这样的函数来打开/关闭数据库:
var inUse = false;
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function openDb() {
while (inUse) {
await timeout(50)
}
inUse = true;
return await sqlite.open({
filename: "filename.db",
mode: sqlite3.OPEN_READONLY,
driver: sqlite3.Database
})
}
async function closeDb(db) {
await db.close();
inUse = false;
}
然后调用这些函数来打开/关闭数据库。但这一次只允许一个异步方法使用数据库,而其他请求需要等待。我认为可能允许多个“线程”以某种方式通过引用计数共享数据库,但不知道具体如何做到这一点。
要使用引用计数管理 SQLite 的并发数据库访问,您可以实现 引用计数 方法。
let referenceCount = 0;
let dbInstance = null;
async function openDb() {
while (referenceCount > 0 && dbInstance === null) {
await new Promise(resolve => setTimeout(resolve, 50)); // Wait if DB is in use
}
if (dbInstance === null) {
dbInstance = await sqlite.open({
filename: "filename.db",
mode: sqlite3.OPEN_READONLY,
driver: sqlite3.Database
});
}
referenceCount++;
return dbInstance;
}
async function closeDb() {
referenceCount--;
if (referenceCount === 0 && dbInstance) {
await dbInstance.close();
dbInstance = null;
}
}
async function request() {
const db = await openDb();
const stmt = await db.prepare("SELECT 1");
const rows = await stmt.all();
await stmt.finalize();
console.log(rows);
await closeDb();
}
这允许多个并发读取(或操作),并确保数据库仅在所有操作完成后才关闭。