Nodejs事务处理速度太快导致数据出错?

发布于 1周前 作者 ionicwang 来自 nodejs/Nestjs

Nodejs事务处理速度太快导致数据出错?
有两个 MySQL 数据库表 a 和 b
a 有一个整型字段 a_count(此字段某些情况下归 0)
b 有一个整型字段 b_count

事务处理:
1 、 select 表 a ,得到 a_count ,然后计算 count = a_count + 1
2 、 update 表 a , a_count = count
3 、 insert 一条记录到表 b , b_count = count

想实现的的情况 count : 1 2 3 4 5 6 7 1 2 3 4 5 6 (第二个 1 是因为 a_count 归零了)
得到的真实情况 count : 1 2 2 2 3 3 4 1 1 2 3 3 3 (操作的速度太快导致数据重复)

问题一:有什么方式可以解决这样的问题?
问题二:解决了第一个问题,如果我想限制一个时间内(如:一秒)只能一次操作有哪些方式?

上代码(语言 Node.js ,用得 orm 是 sequelize )

models.sequelize.transaction(function (t) {


// 查询表 a 数据
return models.A.findOne({
where: {
id: user_id,
},
transaction: t,
}).then(function (a) {


var count = a.a_count + 1;


// 事务:新增表 b 记录
return models.B.create({
b_count: count,
}, {transaction: t}).then(function () {


// 事务:更新表 a 数据
return models.A.update({
a_count: count,
}, {
where: {
id: user_id,
},
transaction: t,
}).then(function () {
res.json({success: ‘success’});
});
});
});
});


7 回复

第二个问题有什么好的解决方式吗?

count = a_count + 1
这个不能直接在 sql 里面做么?

拿着锁 sleep 1000ms

多个地方用注意统一

在Node.js中进行事务处理时,如果处理速度过快导致数据出错,这通常是由于并发控制不当或事务隔离级别设置不合理所致。以下是一些可能的解决方案,包括代码示例:

  1. 确保事务的原子性: 使用数据库提供的事务功能来确保操作的原子性。例如,在MySQL中,你可以使用BEGIN, COMMIT, ROLLBACK来管理事务。

    const mysql = require('mysql');
    const connection = mysql.createConnection({/* config */});
    
    connection.beginTransaction((err) => {
      if (err) throw err;
      connection.query('INSERT INTO ...', (error, results, fields) => {
        if (error) {
          return connection.rollback(() => {
            throw error;
          });
        }
        connection.commit((err) => {
          if (err) throw err;
          console.log('Transaction committed');
        });
      });
    });
    
  2. 设置合适的隔离级别: 数据库隔离级别(如READ COMMITTED, REPEATABLE READ, SERIALIZABLE)会影响并发事务的行为。选择适当的隔离级别可以避免数据竞争和脏读。

    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    
  3. 使用锁: 在必要时,使用数据库锁(如行锁、表锁)来控制并发访问。

  4. 检查并处理并发逻辑: 确保应用逻辑正确处理并发事务,例如使用唯一约束、乐观锁等机制。

总之,Node.js本身并不会导致事务处理速度过快而数据出错,关键在于如何合理管理和控制事务的并发和隔离。务必确保你的数据库操作和事务管理逻辑正确无误。

回到顶部