我对nodejs有意见。当我试图发布/更新
One balance One account
过帐来源
Two different users at the same time.
例子:
我有一个带有expressjs的api,用于将数据发布到 t_account
像这样的table。
我要先从银行拿到最新余额 max(id)
每次交易后。
我想得到400英镑的余额 NOT
300
例如:
起始余额=100
第一个新职位=100,=>余额=200
第二个新职位=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` 控制台日志
![](https://i.stack.imgur.com/Apdf6.png)
![](https://i.stack.imgur.com/pPqRJ.png)
最后的余额不正确显示300而不是400。
这里出了什么问题?
2条答案
按热度按时间oyjwcjzk1#
离开你提供的信息,不知道更多关于nodejs或你的操作系统,版本,设置等。这是我的思想过程,因为我看到的每一个问题。
检查基本情况
尽管这可能真的很愚蠢,但还有很多未知的因素。
我看到你在自己的电脑上运行这个,
如果连续运行10多次,行为是否相同?
如果最终结果不同,请检查正在关闭的进程。
如果可能的话,
请进行基本的计算机检查(重新启动,关闭其他程序)
如果可能的话,也可以在另一台计算机上进行检查
在这之后,请检查:
检查savebalance功能
你的
saveBalance',async function
可能是双重原因SELECT...SELECT
双倍INSERT...INSERT
我的直觉告诉我这是基于图像的问题,顺序是错误的。检查数据库设置
如果
saveBalance',async function
很好。我会检查你的Database settings
基于您正在使用的mysql控制台日志localhost
您的图像显示选择…选择…插入…插入。。。但它应该是select…insert…**select…**insert。。。
这可能是由于mysql数据库设置的问题造成的。
请检查你的隔离等级。要检查这个,请在mysql中运行这个
sql代码:
它也可能会引起你的兴趣
START TRANSACTIONS;
但一定要在配置中启用多语句。这也与TX_ISOLATION
也。我的示例将修改您的查询,如下所示:
尝试其他可接受的代码作为您自己的代码
最后,我还建议阅读“使用node.js处理多个mysql查询的方法-应该避免金字塔式的厄运”
我希望这有帮助。
qvk1mo1f2#
您需要锁定正在读取的行,以便在其他人可以读取该行之前更新该行。具体来看innodb锁定读取
for update
来自文档使用select for update锁定更新行仅在禁用autocommit时适用(通过使用start transaction开始事务或将autocommit设置为0)。如果启用了autocommit,则与规范匹配的行不会被锁定。