NodeJS Как обрабатывать параллельный запрос к MySQL - PullRequest
0 голосов
/ 05 мая 2018

У меня проблема с NodeJS. Когда я пытаюсь опубликовать / обновить

  • One balance
  • One account
  • сообщение от Two different users
  • at the same time.

Пример:

example of t_account table

У меня есть API с ExpressJS для отправки данных в таблицу t_account следующим образом.

Мне нужно сначала получить последний баланс из max(id) после каждой транзакции.

Я пытаюсь получить баланс 400 NOT 300

Например:

  1. Начальный баланс = 100
  2. 1-й новый пост = 100, => баланс = 200
  3. 2-й новый пост = 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 Журналы консоли

enter image description here enter image description here

Последний баланс неверен, показывая 300 вместо 400.

Что здесь не так?

Ответы [ 2 ]

0 голосов
/ 05 мая 2018

Уходя от предоставленной вами информации и не зная больше о NodeJS или вашей ОС, версиях, настройке и т. Д. Это мой мыслительный процесс, так как каждую проблему я вижу.

Проверьте основы

  1. Как бы глупо это ни было на самом деле, существует так много неизвестных факторов.

    • Я вижу, вы запускаете это на своем компьютере,
    • Если вы запустите это более 10 раз подряд, будет ли поведение таким же?
      • Если конечный результат отличается, проверьте процессы, работающие близко.
    • Если возможно,
      • пожалуйста, проверьте ваш базовый компьютер (перезагрузите компьютер, закройте другие программы)
      • если возможно, проверьте и на другом компьютере

    После этого проверьте:

Проверка функции сохранения баланса

  1. Ваш saveBalance',async function Может быть причина двойного SELECT...SELECT двойного INSERT...INSERT
    • My Gut говорит мне, что это проблема, основанная на изображениях, неправильный порядок.

Проверка настроек базы данных

  1. Если saveBalance',async function в порядке. Я бы проверил ваш Database settings на основе ваших журналов консоли MySQL и того, что вы используете localhost

    • Ваше изображение показывает SELECT ... SELECT ... INSERT ... INSERT ...
    • Но это должен быть SELECT ... INSERT ... ** SELECT ... ** INSERT ...
  2. Это может произойти из-за проблемы с настройками базы данных 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;";

Попробуйте другой принятый код как собственный

Наконец, я также рекомендую прочитать 'Подход к нескольким запросам MySQL с Node.js - нужно избегать пирамиды гибели'

Надеюсь, это поможет.

0 голосов
/ 05 мая 2018

Вам нужно заблокировать строку, которую вы читаете, чтобы вы могли обновить эту строку, прежде чем кто-либо другой сможет ее прочитать. Посмотрите на innodb-lock-reads , в частности for update

Из документов

Блокировка строк для обновления с помощью SELECT FOR UPDATE применяется только тогда, когда автокоммит отключен (либо путем начала транзакции с помощью START TRANSACTION или установив autocommit на 0. Если autocommit включен, строки, соответствующие спецификации, не заблокированы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...