NodeJS How To Handle Concurrent Request To MySQL

隐身守侯 提交于 2020-08-08 05:24:01

问题


I am having a problem with NodeJS. When I am trying to post/update

  • One balance
  • One account
  • posting from Two different users
  • at the same time.

Example:

I have API with ExpressJS for post data to the t_account table like this.

I need to get latest balance first from max(id) after each transaction.

I'm trying to get balance of 400 NOT 300

For Example:

  1. Starting Balance = 100
  2. 1st new post = 100, => balance =200
  3. 2nd new post = 200, => balance =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

The last balance not right showing 300 instead of 400.

What is going wrong here?


回答1:


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

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.




回答2:


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.

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?
      • 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

  1. Your saveBalance',async function Maybe the cause of the double SELECT...SELECT double 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. I would check your Database settings as based on your MySQL Console Logs & that you are using localhost

    • Your image shows SELECT...SELECT...INSERT...INSERT...
    • But it should be SELECT...INSERT...**SELECT...**INSERT...
  2. This Might be due to an issue with your MySQL Database Settings.

    • Please check your Isolation Level. To Check this run this in your MySQL

SQL Code:

SELECT @@GLOBAL.TX_ISOLATION;

It also, might interest you to use START TRANSACTIONS; But be sure to enable multistatements in your config. and this is also directly tied to the TX_ISOLATION as well.

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'

I hope this helps.



来源:https://stackoverflow.com/questions/50185816/nodejs-how-to-handle-concurrent-request-to-mysql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!