首页 > 解决方案 > Knex+MySQL UPDATE 然后 SELECT 有时会返回旧值

问题描述

以下代码有时会使用 Knex.js 从 MySQL 返回旧值:

await db.knex('table')
  .where('id', '=', table_id)
  .update({
    last_opening: db.knex.fn.now(),
  });

// ... removed another db.knex('table')...update() here for brevity, updating different fields

const updated_data = await db.knex('table')
  .where('id', '=', table_id)
  .select('last_opening')
  .first();

// At this point updated_data.last_opening randomly contains either the old or the new date

db.knex来自像这样的另一个模块:

// package.json has "knex": "^0.21.1",
const knex_factory = require('knex');

exports.knex = knex_factory({
  client: 'mysql',
  connection: {
    host : conf.DB_HOST,
    user : conf.DB_USER,
    password : conf.DB_PASSWORD,
    database : conf.DB_NAME,
  }
});

它似乎只发生在生产环境中。根本无法在本地复制,并且不记得我是否在登台环境中看到过。

$ SELECT @@TX_ISOLATION;
REPEATABLE-READ

$ SELECT VERSION();
5.7.32-0ubuntu0.16.04.1

这个问题InnoDB / MySQL - new transaction using old data on SELECT 而不是返回更新的数据让我怀疑这与事务隔离级别和 Knex 的连接池有关,但我不了解足以轻松更改任何内容。

任何人都可以帮助解释发生了什么吗?

标签: mysqlknex.js

解决方案


我认为代码不应该/永远不会返回旧值,除非您同时多次运行该代码,例如,当 2 个请求处理程序可能一个接一个地更新该行,然后两者都从数据库中读取最后一个更新时。

此外,如果您有多个进程运行该代码,它也可能导致这种行为。

如果您将两个查询包装在一个事务中,即使更新同时运行也不应该发生。


推荐阅读