我遇到NodeJS问题。 当我尝试发布/更新时
One balance
One account
Two different users
at the same time.
示例:
我有ExpressJS的API用于将数据发布到这样的t_account
表。
我需要在每笔交易后首先从max(id)
获得最新余额。
我正试图平衡400 NOT
300
例如:
代码示例:
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。
这里出了什么问题?
答案 0 :(得分:2)
您需要锁定正在阅读的行,以便在其他人可以阅读之前更新此行。请innodb-locking-reads,特别是for update
来自docs
使用SELECT FOR UPDATE锁定行以进行更新仅适用于 自动提交被禁用(通过START开始事务 TRANSACTION或通过将自动提交设置为0.如果启用了自动提交, 与规范匹配的行未锁定。
答案 1 :(得分:0)
取消您提供的信息,不了解更多有关NodeJS或您的操作系统,版本,设置等信息。 这是我的思考过程,就像我看到的每个问题一样。
实际上可能很愚蠢,但有很多未知因素。
之后检查:
saveBalance',async function
可能是双倍SELECT...SELECT
加倍INSERT...INSERT
的原因
如果saveBalance',async function
没问题。我会根据您的MySQL控制台日志和&amp ;;检查您的Database settings
。您正在使用localhost
这可能是由于您的MySQL数据库设置出现问题。
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'
我希望这会有所帮助。