Node中如何实现事务(临时版)

2,207 阅读2分钟

群里有学生提出要一个事务的例子。。比较急 我就先把试验放出来概念和其他的后面再补充

事务是什么

简单的说A表和B表操作属于同一个事务,A表和B表操作需要同时成功同时失败。

Node实现

创建两个表accountA 、accountB

CREATE TABLE IF NOT EXISTS accountB (
id INT NOT NULL AUTO_INCREMENT,
amount INT NULL,
PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS accountA (
id INT NOT NULL AUTO_INCREMENT,
amount INT NULL,
PRIMARY KEY (id)
);

代码实现

我们对两个表都插入一条数据,中间通过执行一个错误的SQL故意制造一个异常。

module.exports = async (pool,isAutoCommit) => {
  const conn = await pool.getConnection()

  // 开启事务
  isAutoCommit && await conn.beginTransaction()
  try {
    // 操作表A
    let res = await conn.query(`
      INSERT INTO accountA (amount) VALUES (1)
    `)

    // 人为制造异常
    res = await conn.query(`
      KKB 
   `)

    // 操作表B
    res = await conn.query(`
      INSERT INTO accountB (amount) VALUES (1)
    `)
    // console.log('INSERT ACCOUNT B ', res)

    isAutoCommit && await conn.commit()
  } catch (error) {
    // console.log('发生error...', error)
    await conn.rollback()
  }
  conn.release()
}



测试用例

这里面分成两个用例分别测试有事务和没有事务的情况

  • 有事务的时候 出错会回滚 两个表都不会插入数据
  • 没有事务的时候 不会回滚 出错前的表插入还将生效
const callback = require('../index')

// get the client
const mysql = require('mysql2/promise');
// 连接配置
const cfg = {
    host: "localhost",
    user: "root",
    password: "example", // 修改为你的密码
    database: "test", // 请确保数据库存在
    connectionLimit: 5,
    // debug:true
}

test('Test 使用事务', async (done) => {
    const pool = await mysql.createPool(cfg)

    // 准备环境
    // 所有表数据清空
    const conn = await pool.getConnection()
    // 清理表数据
    await conn.query(`
      TRUNCATE TABLE accountA 
    `)
    await conn.query(`
      TRUNCATE TABLE accountB
    `)

    await callback(pool, true)

    // 查询结果
    const [countA] = await conn.execute(`SELECT count(*) as count FROM accountA`)
    const [countB] = await conn.execute(`SELECT count(*) as count FROM accountB`)
    console.log('AmountA', countA[0].count)
    console.log('AmountB', countB[0].count)
    done()
    // setTimeout(done,4000)
})

test('Test 未使用事务', async (done) => {
    const pool = await mysql.createPool(cfg)

    // 准备环境
    // 所有表数据清空
    const conn = await pool.getConnection()
    // 清理表数据
    await conn.query(`
      TRUNCATE TABLE accountA 
    `)
    await conn.query(`
      TRUNCATE TABLE accountB
    `)

    await callback(pool, false)

    // 查询结果
    const [countA] = await conn.execute(`SELECT count(*) as count FROM accountA`)
    const [countB] = await conn.execute(`SELECT count(*) as count FROM accountB`)
    console.log('AmountA', countA[0].count)
    console.log('AmountB', countB[0].count)
    done()
    // setTimeout(done,4000)
})

测试结果

代码放在 github.com/su37josephx…

大家可以试试 保持关注 后面我会完善