Javascript 并发sqlite3写入期间性能下降
为基于云的API编写测试套件。我需要使用伪造的用户数据(部分数据来自API服务器)为数据库种子,在注册伪造的生成的用户详细信息后,从API服务器接收API密钥和机密 当尝试使用sqlite3 with node将记录写入文件时,我尝试以一种朴素的方式编写逻辑,没有任何错误检查,但由于大量SQLITE_BUSY数据库锁定错误而失败 然后,我添加了代码,以便在出现错误时重试,但代码不足-最终导致表损坏,因此我添加了freenode上node.js中建议的事务 现在,它起作用了。然而问题是它的速度太慢了——大约50条记录需要5分钟。另外,我需要传入一个retries参数,该参数大约为\u of_users*2,以使进程成功完成,否则它将退出。有些地方不对劲,但我无法确定。SQLite3的性能不能这么慢 怎么了Javascript 并发sqlite3写入期间性能下降,javascript,node.js,performance,error-handling,sqlite,Javascript,Node.js,Performance,Error Handling,Sqlite,为基于云的API编写测试套件。我需要使用伪造的用户数据(部分数据来自API服务器)为数据库种子,在注册伪造的生成的用户详细信息后,从API服务器接收API密钥和机密 当尝试使用sqlite3 with node将记录写入文件时,我尝试以一种朴素的方式编写逻辑,没有任何错误检查,但由于大量SQLITE_BUSY数据库锁定错误而失败 然后,我添加了代码,以便在出现错误时重试,但代码不足-最终导致表损坏,因此我添加了freenode上node.js中建议的事务 现在,它起作用了。然而问题是它的速度太慢
TestController.prototype.connectToDb = function () {
var db = new sqlite3.Database(this.dbpath);
return db;
}
TestController.prototype.writeUserToLocalDatabase = function (retries,username,useremail,password,api_key,api_secret, callback_after_all_users_have_been_added) {
var dbase = this.connectToDb();
var controller = this;
if (retries < 0) {
console.log("Bailing out of writeUserToLocalDatabase after max retry attempts");
return;
}
dbase.run("BEGIN TRANSACTION");
//console.log("Try #"+retries);
var stmt = dbase.prepare("insert into user_table values(?,?,?,?,?)", function(err) {
if(err !== null) {
console.log("Error when trying to write user to database in prepare! "+err);
dbase.run("ROLLBACK");
dbase.close(function(err){if(err !== null) {console.log("Close failed in in prepare "+err);}});
controller.writeUserToLocalDatabase(--retries,username,useremail,password,api_key,api_secret, callback_after_all_users_have_been_added);
}
});
stmt.run(username,useremail,password,api_key,api_secret, function(err) {
if(err !== null) {
//console.log("Error when trying to write user to database in run! "+err);
stmt.finalize();
dbase.run("ROLLBACK");
dbase.close(function(err){if(err !== null) {console.log("Close failed in in run "+err);}});
controller.writeUserToLocalDatabase(--retries,username,useremail,password,api_key,api_secret, callback_after_all_users_have_been_added);
}
else {
stmt.finalize(function(err) {
if(err !== null && err !== undefined) {
console.log("Error when trying to write user to database in finalize ! "+err);
dbase.run("ROLLBACK");
dbase.close(function(err){if(err !== null) {console.log("Close failed in in finalize "+err);}});
controller.writeUserToLocalDatabase(--retries,username,useremail,password,api_key,api_secret, callback_after_all_users_have_been_added);
}
else {
dbase.run("COMMIT");
controller.appendToUserFile(useremail,password,api_key,api_secret);
controller.pending_db_writes_for_user--;
if (controller.pending_db_writes_for_user <= 0) {
console.log("Finished writing all users, now invoking db.close with callback");
dbase.close(callback_after_all_users_have_been_added);
}
else {
console.log("Remaining users to add: "+controller.pending_db_writes_for_user);
dbase.close(function(err){if(err !== null) {console.log("Close failed in after adding user "+err);}});
}
}
});
}
});
}
更新:获得正常性能的唯一方法是使用队列大小为1的async.queue限制sqlite3写入。一个字:我明白了。。。谢谢,我会调查的。但是sqlite3模块的默认行为是令人费解的。update:我能获得一些正常性能的唯一方法是使用队列大小为1的async.queue来限制db写入。鉴于sqlite是一个文件,这并不奇怪。据我所知,sqlite3节点模块只提供sqlite3,而不是任何额外的复杂数据库管理,因此它仍然是一个单独的文件,您需要在其中串行写入数据,而不是并行写入数据。这也是为什么sqlite非常适合于原型设计和经常读/偶尔写的存储。如果需要并发写入,可以使用“真实”数据库。