简体   繁体   English

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

[英]NodeJS How To Handle Concurrent Request To MySQL

I am having a problem with NodeJS. 我在使用NodeJS时遇到问题。 When I am trying to post/update 当我尝试发布/更新时

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

Example: 例:

t_account表的示例

I have API with ExpressJS for post data to the t_account table like this. 我的ExpressJS具有API,用于将数据发布到t_account表中,如下所示。

I need to get latest balance first from max(id) after each transaction. 我需要在每次交易后首先从max(id)获取最新余额。

I'm trying to get balance of 400 NOT 300 我正在尝试获得400 NOT 300的余额

For Example: 例如:

  1. Starting Balance = 100 起始余额= 100
  2. 1st new post = 100, => balance =200 第一个新职位= 100,=>余额= 200
  3. 2nd new post = 200, => balance =400 第二个新职位= 200,=>余额= 400

Code Example: 代码示例:

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",
        })
 }})

The problem is when two user post data in the same time, I get the incorrect balance. 问题是当两个用户同时发布数据时,我得到了不正确的余额。

Code Example of Initializing my Transactions: 初始化我的交易的代码示例:

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

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

The last balance not right showing 300 instead of 400. 最后一个余额显示300,而不是400。

What is going wrong here? 这是怎么了?

You need to lock the row that you are reading so that you can update this row before anyone else can read it. 您需要锁定正在读取的行,以便在其他任何人都可以读取它之前更新此行。 Look at innodb-locking-reads , specifically for update 查看innodb-locking-reads ,专门for update

From docs 来自文档

Locking of rows for update using SELECT FOR UPDATE only applies when autocommit is disabled (either by beginning transaction with START TRANSACTION or by setting autocommit to 0. If autocommit is enabled, the rows matching the specification are not locked. 使用SELECT FOR UPDATE锁定更新行仅在禁用自动提交时才适用(通过以START TRANSACTION开始事务或将autocommit设置为0。如果启用了自动提交,则不锁定与规范匹配的行。

Going off of your provided info, and not knowing more about NodeJS or your OS, Versions, setup etc. This is my thought process as what each issue I see. 不再提供您提供的信息,并且不了解有关NodeJS或您的操作系统,版本,设置等的更多信息。这就是我所看到的每个问题的思考过程。

Check The Basics 检查基础

  1. As silly as this may actually be, there are so many unknown factors. 尽管实际上这很愚蠢,但有许多未知因素。

    • I see you are running this on your own computer, 我看到您正在自己的计算机上运行它,
    • If you run this 10+ times in a row, is the behaviour the same? 如果您连续运行10次以上,行为是否相同?
      • If the end result is different, Check processes running close. 如果最终结果不同,请检查正在运行的进程是否关闭。
    • If possible, 如果可能的话,
      • please do your basic computer check (reboot, close other programs) 请进行基本计算机检查(重新启动,关闭其他程序)
      • if possible, check it on another computer too 如果可能,也请在另一台计算机上检查

    After that is out of the way check: 之后,请检查:

Check saveBalance Function 检查saveBalance功能

  1. Your saveBalance',async function Maybe the cause of the double SELECT...SELECT double INSERT...INSERT 您的saveBalance',async function可能是双重SELECT...SELECT双重INSERT...INSERT
    • My Gut tells me this is the issue based on the images, the order is wrong. 我的胆量告诉我这是基于图像的问题,顺序错误。

Check Database Settings 检查数据库设置

  1. If the saveBalance',async function is fine. 如果saveBalance',async function很好。 I would check your Database settings as based on your MySQL Console Logs & that you are using localhost 我会根据您的MySQL控制台日志和您正在使用localhost来检查Database settings

    • Your image shows SELECT...SELECT...INSERT...INSERT... 您的图像显示SELECT ... SELECT ... INSERT ... INSERT ...
    • But it should be SELECT... INSERT...**SELECT...**INSERT... 但这应该是SELECT ... INSERT ... ** SELECT ... ** INSERT ...
  2. This Might be due to an issue with your MySQL Database Settings. 这可能是由于您的MySQL数据库设置有问题。

SQL Code: SQL代码:

SELECT @@GLOBAL.TX_ISOLATION;

It also, might interest you to use START TRANSACTIONS; 另外,您可能会喜欢使用START TRANSACTIONS; But be sure to enable multistatements in your config. 但是请确保在配置中启用语句。 and this is also directly tied to the TX_ISOLATION as well. 并且这也直接与TX_ISOLATION绑定。

My example would modify your Query like so: 我的示例将像这样修改您的查询:

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

Try Other Accepted Code as your own 尝试将其他接受的代码作为自己的代码

Lastly, I also recommend reading 'Approach to multiple MySQL queries with Node.js - One should avoid the pyramid of doom' 最后,我还建议阅读“使用Node.js到多个MySQL查询的方法-应该避免厄运金字塔”

I hope this helps. 我希望这有帮助。

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

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