nodejs如何处理mysql的并发请求

6xfqseft  于 2021-06-21  发布在  Mysql
关注(0)|答案(2)|浏览(430)

我对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。
这里出了什么问题?
oyjwcjzk

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代码:

SELECT @@GLOBAL.TX_ISOLATION;

它也可能会引起你的兴趣 START TRANSACTIONS; 但一定要在配置中启用多语句。这也与 TX_ISOLATION 也。
我的示例将修改您的查询,如下所示:

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

尝试其他可接受的代码作为您自己的代码

最后,我还建议阅读“使用node.js处理多个mysql查询的方法-应该避免金字塔式的厄运”
我希望这有帮助。

qvk1mo1f

qvk1mo1f2#

您需要锁定正在读取的行,以便在其他人可以读取该行之前更新该行。具体来看innodb锁定读取 for update 来自文档
使用select for update锁定更新行仅在禁用autocommit时适用(通过使用start transaction开始事务或将autocommit设置为0)。如果启用了autocommit,则与规范匹配的行不会被锁定。

相关问题