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

Sea*_*ene 20 database sqlite node.js node-sqlite3

最近我学习使用node和node-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();
Run Code Online (Sandbox Code Playgroud)

文档说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();
Run Code Online (Sandbox Code Playgroud)

Mal*_*ous 26

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

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

这被称为竞争条件,因为每次运行程序时,您都可能获得不同的胜利者.如果CREATE TABLE赢得比赛,那么该计划将正常运作.但如果INSERT赢得比赛,该计划将打破错误.既然你无法控制谁赢得比赛,那么即使从开始到结束serialize()也会停止,确保你每次都获得相同的结果.INSERTCREATE TABLE

在第二个只有一个语句的例子中,serialize()仍然需要.这是因为run()启动SQL查询但立即返回,使查询在后台运行.由于您的下一个命令是close()数据库的一个命令,因此您将在查询仍在运行时将其截断.

由于serialize()直到最后一个内部查询完成才返回,因此使用它将close()一直保持到查询完成为止.

如果您使用的是不同类型的查询(例如,响应用户单击网页上的按钮,数据库在调用之间保持打开状态),那么您可能不需要serialize().它取决于每个查询后面的代码是否要求在它完成之前的查询.

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

(这个提示不适用于close()- 经验法则只有close()在一切都运行完毕后才会调用.)


小智 7

我在SQLite 文档中找到了这个:

Database#close 方法将始终以独占模式运行,这意味着它将等待所有先前的查询完成,并且在关闭挂起时,node-sqlite3 将不会运行任何其他查询。

所以看起来你最后一个问题的答案是肯定的。如果您只需要运行一个查询,则不需要序列化函数。您无需担心数据库在查询完成之前关闭,因为 SQLite 足够聪明,不会这样做!:)