knexjs,打字稿和mariadb的交易问题

时间:2019-01-14 10:27:42

标签: typescript mariadb knex.js

我想用打字稿进行交易,以刷新表中的某些数据。为此,需要执行以下步骤:

  1. 截断表中的所有记录
  2. 将AUTO_INCREMENT设置为1
  3. 将新记录插入表中

如果出现问题,我想回滚事务,而不更改db表中的现有记录。

我尝试了不同的方法,但我想我缺少了一些东西,希望有人能发现我做错了什么。

第一次尝试

await knex.transaction(async (trx) => {
  await knex(tableName).truncate().transacting(trx);
  await knex.raw(`ALTER TABLE ${tableName} AUTO_INCREMENT=1;`).transacting(trx);
  await knex(tableName).insert(data).transacting(trx);
  await trx.commit();
});

第二次尝试

await knex.transaction(async (trx) => {
  try {
    await knex(table).truncate().transacting(trx);
    await knex.raw(`ALTER TABLE ${table} AUTO_INCREMENT=1;`).transacting(trx);
    await knex(table).insert(data).transacting(trx);
    await trx.commit();
  } catch (e) {
    await trx.rollback();
  }
});

第三次尝试

const promisify = (fn: any) => new Promise((resolve, reject) => fn(resolve));
const trx: knex.Transaction  = <knex.Transaction> await promisify(this.knex.transaction);
try {
  await this.knex(this.table).truncate().transacting(trx);
  await this.knex.raw(`ALTER TABLE ${this.table} AUTO_INCREMENT=1;`).transacting(trx);
  await this.knex(this.table).insert(data).transacting(trx);
  await trx.commit();
  return Promise.resolve(data);
} catch (e) {
  await trx.rollback();
  return Promise.reject(e);
}

任何想法都会非常有用。

2 个答案:

答案 0 :(得分:1)

使用mysql时,所有更改DDL查询的架构都会隐式提交,因此无法回滚。因此,您需要更改实现,以其他方式保证db的完整性。

https://dev.mysql.com/doc/refman/8.0/en/cannot-roll-back.html https://dev.mysql.com/doc/refman/8.0/en/implicit-commit.html

答案 1 :(得分:1)

不要那样做。相反:

CREATE TABLE new LIKE real;
populate `new`
RENAME TABLE real TO old, new TO real;
DROP TABLE old;

如果CREATEpopulate失败,则放弃任务。没有伤害。 (嗯,需要DROP TABLE real。)

RENAME TABLE非常快,原子且不会失败。

这种方法的优势在于,对于其他查询,real表是可用的,并且在整个时间内都已完全填充。