Arhn - архитектура программирования

NodeJS: как обрабатывать параллельный запрос к MySQL

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

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

Пример:

пример таблицы t_account

У меня есть 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 Журналы консоли

введите здесь описание изображения введите здесь описание изображения

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

Что здесь происходит не так?


Ответы:


1

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

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

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

05.05.2018
  • о боже, ты мой спаситель... я думаю, что проблема в node.js (параллельный процесс).... на самом деле в mysql. я не знал о FOR UPDATE раньше .. большое спасибо 05.05.2018
  • Рад помочь!! Просто чтобы добавить больше контекста, что это не просто проблема асинхронности узла. Подумайте о сценарии, в котором ваше приложение работает на нескольких серверах, и вы можете войти в аналогичные условия гонки. 05.05.2018
  • Да, MySQL имеет массу ужасных готовых настроек. По умолчанию ваш уровень транзакции дает ЧИТАТЬ ВЫШЕ приоритет, чем запись, и поэтому это было частью моего ответа. Не забудьте проверить & ПОПРОБУЙТЕ использовать SET @@GLOBAL.SQL_MODE = TRADITIONAL; это действует более уместно и НЕ оставит вас в замешательстве. MySQL по умолчанию позволяет вставлять значения NULL в столбцы NOT NULL или предоставляет нулевые даты, если вы забыли использовать дату и время вместо метки времени или наоборот. 05.05.2018

  • 2

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

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

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

      • I see you are running this on your own computer,
      • If you run this 10+ times in a row, is the behaviour the same?
        • If the end result is different, Check processes running close.
      • If possible,
        • please do your basic computer check (reboot, close other programs)
        • если есть возможность, проверьте и на другом компе

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

    Проверить функцию saveBalance

    1. Your saveBalance',async function Maybe the cause of the double SELECT...SELECT double INSERT...INSERT
      • My Gut tells me this is the issue based on the images, the order is wrong.

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

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

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

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

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

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

    05.05.2018
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..