[英]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
Two different users
来自Two different users
帖子 at the same time.
Example: 例:
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: 例如:
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或您的操作系统,版本,设置等的更多信息。这就是我所看到的每个问题的思考过程。
As silly as this may actually be, there are so many unknown factors. 尽管实际上这很愚蠢,但有许多未知因素。
After that is out of the way check: 之后,请检查:
saveBalance',async function
Maybe the cause of the double SELECT...SELECT
double INSERT...INSERT
您的saveBalance',async function
可能是双重SELECT...SELECT
双重INSERT...INSERT
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
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;";
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.