Как в SQL сделать сразу несколько запросов в одном действии

Поддержка
  • @Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:

    @sergerdn Жесть, а зачем всю таблицу то лочить? Я привел пример с полем, когда вообще ничего не лочится. Просто запись выподает из выборки остальных запросов...

    Ну оно вот так работает, точнее работало когда то. Сейчас не могу ручаться на 100%. В сфере применения BAS это будет незаметно, так как лок таблицы на наносекунду по время выполнения запроса не повлияет ни на что.
    Таблица лочится ТОЛЬКО на время выполнения одного запроса, чтобы взять запись и поменять у нее поле. Как раз, чтобы другие потоки не схватили ее же. Вариантов тут нет, надо лочить.
    Может сейчас лочится только конкретная запись, не вся таблица. Пойду как я сам доки почитаю.

    Ты дал вариант, при котором другие потоки все таки могут схватить нужную запись.
    Поток 1:

    1. взял запись
    2. изменил у нее флаг

    А между этими пунктами поток 2 успел схватить ее. Это все ненадежно и добавляет свою логику, вместо SELECT FOR UPDATE, который был придуман ради этого.

  • @sergerdn Жесть, один поток повис, а вся таблица залочена. Это прям майсами какое то...

  • @Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:

    @sergerdn Жесть, один поток повис, а вся таблица залочена. Это прям майсами какое то...

    Сам запрос повис что ли? В честь чего он "повиснет"? И блокировки делаются во время выполнения запроса, когда сам БД его выполняет, а не когда ты его послал.

  • Спорить не буду, но по мне, проще запись лочить в отдельном поле. Сразу записали, что она не доступна, и дальше делаем что хотим. Переодически после остановки чистить, чтоб хвостов при отвалах не было.

  • @Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:

    Спорить не буду, но по мне, проще запись лочить в отдельном поле. Сразу записали, что она не доступна, и дальше делаем что хотим. Переодически после остановки чистить, чтоб хвостов при отвалах не было.

    Логика, что ты предложил, работает не так, как ты от нее ожидаешь. Другие потоки могут схватить запись в ненужный тебе момент. Я отредактировал комментарий выше, где описал ситуацию. Ты фактически пытаешься сделать в коде то, что было уже придумано разработчиками БД.
    Все мы строим велосипеды, это частое явление.

  • @sergerdn В смысле? Если запрос идёт с проверкой на поле Лок? Каждый запрос многопотока - проверяет есть ли в поле Лок 1 - они все в очереди. Первый записал, второй не взял....

  • @Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:

    @sergerdn В смысле? Если запрос идёт с проверкой на поле Лок? Каждый запрос многопотока - проверяет есть ли в поле Лок 1 - они все в очереди. Первый записал, второй не взял....

    Есть вариант, что я неправильно тебя понял. Напиши последовательность sql запросов.

  • Обновляем запись в которой поле Лок =0 меняем на 1, в ответе получили айди записи? Все делаем с ней что хотим. Другой поток ее уже не трогает, так как она не попадает в условие выборки.

  • @Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:

    Обновляем запись в которой поле Лок 0 меняем на 1, в ответе получили айди записи? Все делаем с ней что хотим. Другой поток ее уже не трогает, так как она не попадает в условие выборки.

    Дай пример запроса UPDATE, где ты в ответе получаешь id обновленной записи. Потому что у меня какая-то другая БД.

    MariaDB [wordpress]> select * from wp_users;
    +----+------------+------------------------------------+---------------+--------------------+-------------------------+---------------------+---------------------+-------------+--------------+
    | ID | user_login | user_pass                          | user_nicename | user_email         | user_url                | user_registered     | user_activation_key | user_status | display_name |
    +----+------------+------------------------------------+---------------+--------------------+-------------------------+---------------------+---------------------+-------------+--------------+
    |  1 | moderator  | $P$B/qpWWZ5C./khtr3h03W5S2sEbvW/ | moderator     | ghtrhgtrhtrhtr@gmail.com | https://coolwp.com | 2021-11-12 21:16:43 |                     |           0 | moderator    |
    +----+------------+------------------------------------+---------------+--------------------+-------------------------+---------------------+---------------------+-------------+--------------+
    1 row in set (0.000 sec)
    
    MariaDB [wordpress]> update wp_users set user_email="blaaaa@local";
    Query OK, 1 row affected (0.001 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    MariaDB [wordpress]>
    
  • @sergerdn индекс есть? Тут по модулю надо смотреть

  • @Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:

    @sergerdn индекс есть?

    CREATE TABLE `wp_users` (
      `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
      `user_login` varchar(60) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
      `user_pass` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
      `user_nicename` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
      `user_email` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
      `user_url` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
      `user_registered` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
      `user_activation_key` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
      `user_status` int(11) NOT NULL DEFAULT 0,
      `display_name` varchar(250) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
      PRIMARY KEY (`ID`),
      KEY `user_login_key` (`user_login`),
      KEY `user_nicename` (`user_nicename`),
      KEY `user_email` (`user_email`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    
  • @sergerdn Завтра гляну, с телефона сам понимаешь.

  • @Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:

    @sergerdn Завтра гляну, с телефона сам понимаешь.

    Не понимаю, так как мне неизвестно, чтобы UPDATE возвращал что-то сверх того, что я дал выше. Я понимаю, что я не DBA и легко могу не знать что-то и это прям нормально. Всего знать невозможно. Поэтому я и попросил пример запроса UPDATE , где он возвращает id обновленных записей.
    Следующим запросом можно получить инфу, что обновилось, но это будет следующий запрос и мы опять наткнулись, что другой поток может между двумя запросами вмешаться и сделать свою работу. Тогда мы получим не то, что ожидаем.

  • Щас глянуть не могу, что он возвращает в ответ, но можно писать ведь не 1, а номер потока к примеру, или рендом. И по этому числу искать запись. Проверю завтра.

  • @Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:

    Щас глянуть не могу, что он возвращает в ответ, но можно писать ведь не 1 а номер потока к примеру, или рендом. И по этому числу искать запись. Проверю завтра.

    Да многое можно, а потом посмотреть на свой код и понять, что ты сделал функционал SELECT FOR UPDATE.
    P.S.
    У меня была такая история.

  • @sergerdn Как ты уже написал, она лочит всю таблицу, имей это ввиду.

  • @Bigma said in Как в SQL сделать сразу несколько запросов в одном действии:

    @sergerdn Как ты уже написал, она лочит всю таблицу, имей это ввиду.

    Я же сам это написал, конечно я имею в виду. И так же добавил, что эта информация может быть устаревшая и надо ее проверять. Может у современных реализаций INNODB немного не так. Может лочится только одна запись в таблице на чтение. Чтобы другой поток не захватил ее.
    Под капотом БД многое что делается, другое дело, что ты не знаешь об этом и "спишь спокойно".

  • Друзья, вопрос же не в частном случае. В справке написано что можно несколько строк, вот мой вопрос и сводится к тому - как сделать чтобы в кубике работало несколько строк. А вы в какие то дербри полезли

  • @Shogo, многострочный запрос и несколько запросов в одном, это не одно и тоже, модуль поддерживает многострочные запросы, но не поддерживает несколько запросов в одном, так как либо они не поддерживаются в конкретном диалекте или отключены по умолчанию. Например в MySQL и MariaDB, несколько запросов в одном отключены по умолчанию, а чтобы их включить нужно добавить multipleStatements: true в настройки диалекта.

  • @GhostZ а где у нас настройки диалекта? А то ни разу с этим не сталкивался