NodeJS如何处理对MySQL的并发请求

时间:2018-05-05 04:51:08

标签: mysql node.js database express async-await

我遇到NodeJS问题。 当我尝试发布/更新时

  • One balance
  • One account
  • Two different users
  • 发帖
  • at the same time.

示例:

example of t_account table

我有ExpressJS的API用于将数据发布到这样的t_account表。

我需要在每笔交易后首先从max(id)获得最新余额。

我正试图平衡400 NOT 300

例如:

  1. 起始余额= 100
  2. 第一个新帖子= 100,=> balance = 200
  3. 第二个新帖子= 200,=> balance = 400
  4. 代码示例:

    router.post('/saveBalance',async function (req, res) {
    try {
        let SQL="SELECT balance FROM t_account WHERE id=(SELECT max(id) FROM t_account WHERE no='"+req.body.no+"')";
        let queryResult=await db.myexec(SQL);
        let newBalance=queryResult[0].balance+req.body.balance;
        let SQL2="INSERT INTO t_account(no,balance) VALUES('"+req.body.no+"',"+newBalance+")";
        let queryResult2=await db.myexec(SQL2);
        res.status(200).json(  {
            error:"false",
            code:"00",
            message:"Balance Bank is saved",
            })
    } catch (error) {
        res.status(400).json(  {
            error:"true",
            code:"03",
            message:"Balance Bank failed to saved",
            })
     }})
    

    问题是当两个用户同时发布数据时,我得到了不正确的余额。

    初始化交易的代码示例:

    const axios = require('axios');
    axios.post('http://localhost:3000/rbank/saveBalance/', 
     {
        "no":"11",
        "balance":100
      }
     )
    axios.post('http://localhost:3000/rbank/saveBalance/', 
     {
        "no":"11",
        "balance":200
     }
    )
    

    MySQL控制台日志

    enter image description here enter image description here

    最后一个余额不正确显示300而不是400。

    这里出了什么问题?

2 个答案:

答案 0 :(得分:2)

您需要锁定正在阅读的行,以便在其他人可以阅读之前更新此行。请innodb-locking-reads,特别是for update

来自docs

  

使用SELECT FOR UPDATE锁定行以进行更新仅适用于   自动提交被禁用(通过START开始事务   TRANSACTION或通过将自动提交设置为0.如果启用了自动提交,   与规范匹配的行未锁定。

答案 1 :(得分:0)

取消您提供的信息,不了解更多有关NodeJS或您的操作系统,版本,设置等信息。 这是我的思考过程,就像我看到的每个问题一样。

检查基础知识

  1. 实际上可能很愚蠢,但有很多未知因素。

    • 我看到你在自己的电脑上运行它,
    • 如果连续运行10次以上,行为是否相同?
      • 如果最终结果不同,请检查正在运行的流程。
    • 如果可能,
      • 请进行基本的计算机检查(重启,关闭其他程序)
      • 如果可能的话,也可以在另一台计算机上查看

    之后检查:

  2. 检查saveBalance函数

    1. 您的saveBalance',async function可能是双倍SELECT...SELECT加倍INSERT...INSERT的原因
      • 我的肠道告诉我这是基于图像的问题,顺序是错误的。
    2. 检查数据库设置

      1. 如果saveBalance',async function没问题。我会根据您的MySQL控制台日志和&amp ;;检查您的Database settings。您正在使用localhost

        • 您的图片显示SELECT ... SELECT ... INSERT ... INSERT ...
        • 但它应该是SELECT ... INSERT ... ** SELECT ... ** INSERT ...
      2. 这可能是由于您的MySQL数据库设置出现问题。

      3. SQL代码:

        SELECT @@GLOBAL.TX_ISOLATION;
        

        您也可能感兴趣使用START TRANSACTIONS; 但请务必在配置中启用multistatements。这也与TX_ISOLATION直接相关。

        我的示例会修改您的查询,如下所示:

        let SQL2="START TRANSACTION; INSERT INTO t_account(no,balance) VALUES('"+req.body.no+"',"+newBalance+"); COMMIT;";
        

        尝试其他接受的代码作为您自己的

        最后,我还建议您阅读'Approach to multiple MySQL queries with Node.js - One should avoid the pyramid of doom'

        我希望这会有所帮助。