繁体   English   中英

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

[英]NodeJS How To Handle Concurrent Request To MySQL

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

  • One balance
  • One account
  • 来自Two different users帖子
  • at the same time.

例:

t_account表的示例

我的ExpressJS具有API,用于将数据发布到t_account表中,如下所示。

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

我正在尝试获得400 NOT 300的余额

例如:

  1. 起始余额= 100
  2. 第一个新职位= 100,=>余额= 200
  3. 第二个新职位= 200,=>余额= 400

代码示例:

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控制台日志

在此处输入图片说明 在此处输入图片说明

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

这是怎么了?

您需要锁定正在读取的行,以便在其他任何人都可以读取它之前更新此行。 查看innodb-locking-reads ,专门for update

来自文档

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

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

检查基础

  1. 尽管实际上这很愚蠢,但有许多未知因素。

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

    之后,请检查:

检查saveBalance功能

  1. 您的saveBalance',async function可能是双重SELECT...SELECT双重INSERT...INSERT
    • 我的胆量告诉我这是基于图像的问题,顺序错误。

检查数据库设置

  1. 如果saveBalance',async function很好。 我会根据您的MySQL控制台日志和您正在使用localhost来检查Database settings

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

    • 请检查您的隔离级别。 要检查这一点,请在您的MySQL中运行

SQL代码:

SELECT @@GLOBAL.TX_ISOLATION;

另外,您可能会喜欢使用START TRANSACTIONS; 但是请确保在配置中启用语句。 并且这也直接与TX_ISOLATION绑定。

我的示例将像这样修改您的查询:

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

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

最后,我还建议阅读“使用Node.js到多个MySQL查询的方法-应该避免厄运金字塔”

我希望这有帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM