`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 TABLE
和INSERT
语句会并行运行。 他们会一个接一个地快速启动, 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()
。)