`db.serialize`如何在`node-sqlite3`中工作

最近我正在学习使用节点和节点sqlite3来操纵sqlite3,这里是一个示例。

var sqlite3 = require('sqlite3'); var db = new sqlite3.Database(':memory:'); db.serialize(function() { db.run("CREATE TABLE test(info TEXT)"); db.run("INSERT INTO test (info) VALUES ('info1')"); }) db.close(); 

该文件说, db.serialized是用来确保SQL行按顺序执行,但我很困惑,为什么不按顺序执行没有db.serialize ,毕竟他们将被从事件队列中拉出并执行订购? 它在这里如何工作?

如果只有一个sql被执行,是否安全地运行它没有db.serialize如下?

 var sqlite3 = require('sqlite3'); var db = new sqlite3.Database(':memory:'); db.run("CREATE TABLE test(info TEXT)"); db.close(); 

serialize()函数中的每个命令都保证在下一个启动之前完成执行。

在你的例子中, CREATE TABLE将在INSERT运行之前完成。 如果你没有使用serialize()那么CREATE TABLEINSERT语句会并行运行。 他们会一个接一个地快速启动, INSERT实际上可能会在创build表之前完成,给您一个尝试将数据插入到不存在的表的错误。

这就是所谓的竞争条件 ,因为每次运行你的程序,你都可能得到不同的胜利者。 如果CREATE TABLE赢得比赛,那么该程序将正常工作。 但是如果INSERT赢得比赛,程序将会打破一个错误。 由于您无法控制谁赢了比赛,因此serialize()将会停止INSERT ,直到CREATE TABLE达到结束为止,确保您每次都获得相同的结果。

在只有一个语句的第二个例子中, serialize()仍然是必需的。 这是因为run()启动SQL查询,但立即返回 ,使查询在后台运行。 由于你的下一个命令是close()数据库的命令,所以在查询仍在运行的时候,你可以关掉它。

由于serialize()直到最后一个内部查询完成才返回,所以使用它将阻塞close()直到查询完成。

如果你正在使用不同types的查询(比如说用户单击网页上的一个button(数据库在调用之间保持打开状态),那么你可能不需要serialize() 。 这取决于每个查询之后的代码是否需要查询之前的查询完成。

在决定是否使用serialize() ,将任何非序列化的查询视为已被注释掉,然后查看代码是否仍然有效可能会很有帮助。 在上面的第一个示例中,删除CREATE TABLE命令将会破坏下面的INSERT语句(因为这样就没有可以插入的表),因此需要对其进行序列化。 但是如果你有两个CREATE TABLE命令,那么删除一个不会影响另一个,所以这两个命令不需要被序列化。

(但是,这个提示并不适用于close() ,只要一切运行完成,只需要调用close() 。)