【问题标题】:Nodejs - How to kill a running SQLite queryNodejs - 如何杀死正在运行的 SQLite 查询
【发布时间】:2022-02-03 17:42:11
【问题描述】:

可能的类似问题:

SQL: Interrupting a query

Is there a way to abort an SQLite call?

大家好, 我实际上是使用 socket.io 和 sqlite3 模块在 SQLite 数据库上执行 SELECT 查询。当用户点击 OpenLayers 地图时,它会向服务器发送一个信号(通过 socket.io),通过执​​行空间请求(如交集、联合......使用 Spatialite 扩展)来收集信息,然后最终将数据发送回客户端(这些是长时间运行的查询(取决于几何图形的数量))以在用户点击的地图上显示一个弹出窗口。

问题是:如果一个用户在地图上点击了很多次,向服务器发送了很多请求,只有最后一个是重要的。想象一下,如果执行一个查询需要 5 秒,并且用户在地图上每秒点击 3 次(他只想使用他点击的最后一个位置),那么服务器将执行 3 个查询,然后发送回3 个通过 socket.io 的信号(并打开 3 个弹出窗口,我们只需要打开最后一个)!是否有任何解决方案可以使用 nodejs 终止/中止正在运行的 sqlite 查询?

示例代码:

socket.on('askForInfo', function (data) {
    sendInfo(socket, data.latitude, data.longitude);
});

sendInfo 定义:

function sendInfo(socket, lat, lng) {
    // Database connection
    var db = new sqlite.Database('some file.sqlite', sqlite.OPEN_READONLY);

    // Load Spatialite extension
    db.loadExtension('mod_spatialite', function(err) {
        // Query doing spatial request
        db.get("VERY LONG SQL QUERY", function(err, row) {
            // Send the data gathered from database
            socket.emit('sendData', row['some sql column']);
        });
    });
}

我想做类似的事情:

if ("sendInfo didn't finished to emit any signal through socket"
    AND "user did another resquest") 
then
    "kill all running sendInfo function execution and sql query"

我知道如果有很多用户连接,这不会像那样工作(我可能需要使用会话来知道该功能实际上是为哪个用户收集数据)。但是即使只有一个用户,我也找不到任何解决方案。

我尝试使用 AJAX(jquery) 而不是 socket.io。我可以中止 xhr 请求,但即使请求被中止直到她完成,SQL 查询仍在运行(无用地使用大量资源)

提前感谢您的回答。

【问题讨论】:

  • 如果您不怕浪费资源并且只想将最新的输出提供给用户,而不是“取消”请求(这可能很复杂),只需并行触发多个请求,每个都有一个唯一的标识符,然后我们得到响应丢弃所有那些 id 与最后一个请求不同的人。
  • 您可以使用debounce 函数等待执行,直到用户交互和正在执行的实际查询之间经过一段时间,这也可能是部分解决方案

标签: ajax node.js sqlite sockets socket.io


【解决方案1】:

感谢您的回答 Qualcuno。

我找到了一个解决方案,使用 child_process 从另一个进程查询数据库,如果用户执行另一个请求,则终止该进程。

var cp = require('child_process');
// more stuff ...

socket.on('askForInfo', function (data) {
    // if process is connected, kill it (query isn't terminated)
    if (child.connected) {
        child.kill();
    }

    // create a new process executing 'query_database.js'
    child = cp.fork('./query_database.js', [
        data.latitude, data.longitude
    ]);

    // when invoking [ process.send(some_data_here) ] in child process, fire this event to send data to the user
    child.on('message', function(d) {
        socket.emit('sendData', d)
    };
});

【讨论】:

  • 我也想不出更好的办法,除了你不一定需要第二个 .js 脚本,相反,你也可以调用可能更快的 sqlite 二进制可执行文件 (?)
  • @phil294 SQLite nodejs 库有中断方法(参见兄弟答案),这意味着您不需要子进程。
【解决方案2】:

Nodejs 的 SQLite 有中断方法,虽然目前没有记录:https://github.com/mapbox/node-sqlite3/issues/1205#issuecomment-559983976

【讨论】:

    猜你喜欢
    • 2019-12-14
    • 2018-10-28
    • 2018-12-10
    • 2012-03-21
    • 2019-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多