Подтвердить что ты не робот

MySQL UPDATE и SELECT за один проход

У меня есть таблица задач MySQL для выполнения, каждая строка имеет параметры для одной задачи.
Существует множество рабочих приложений (возможно, на разных компьютерах), выполняющих задачи в цикле.
Приложения получают доступ к базе данных с помощью API-интерфейсов API, основанных на MySQL.

Чтобы выполнить задачу, приложение делает что-то вроде этого:

  • Создайте глобально уникальный идентификатор (для простоты, допустим, это число)

  • UPDATE tasks
    SET guid = %d
    WHERE guid = 0 LIMIT 1

  • SELECT params
    FROM tasks
    WHERE guid = %d

  • Если последний запрос возвращает строку, мы владеем ею и имеем параметры для запуска

Есть ли способ добиться такого же эффекта (т.е. "собственный" ряд и получить его параметры) в одном вызове на сервер?

4b9b3361

Ответ 1

попробуйте это

UPDATE `lastid` SET `idnum` =  (SELECT `id` FROM `history` ORDER BY `id` DESC LIMIT 1);

выше код работал у меня

Ответ 2

Вы можете создать процедуру, которая делает это:

CREATE PROCEDURE prc_get_task (in_guid BINARY(16), OUT out_params VARCHAR(200))
BEGIN

  DECLARE task_id INT;

  SELECT id, out_params
  INTO task_id, out_params
  FROM tasks
  WHERE guid = 0
  LIMIT 1
  FOR UPDATE;

  UPDATE task
  SET guid = in_guid
  WHERE id = task_id;

END;

BEGIN TRANSACTION;

CALL prc_get_task(@guid, @params);

COMMIT;

Ответ 3

Если вы ищете один запрос, тогда этого не может быть. Функция UPDATE возвращает только количество обновленных элементов. Аналогично, функция SELECT не изменяет таблицу, а возвращает только значения.

Использование процедуры действительно превратит ее в одну функцию, и это может быть удобно, если блокировка является для вас проблемой. Если ваша самая большая проблема связана с сетевым трафиком (то есть: передача слишком большого количества запросов), используйте эту процедуру. Если вы беспокоитесь о перегрузке сервера (то есть: DB работает слишком усердно), то дополнительные накладные расходы процедуры могут ухудшить ситуацию.

Ответ 4

Я не знаю об одной части вызова, но то, что вы описываете, является блокировкой. Замки являются важным элементом реляционных баз данных.

Я не знаю специфики блокировки строки, ее чтения, а затем ее обновления в MySQL, но с небольшим чтением mysql заблокировать документацию, вы можете делать всевозможные манипуляции с блокировкой.

У публикации postgres locks есть отличный пример, описывающий то, что вы хотите сделать: заблокируйте таблицу, прочитайте таблицу, измените таблица.

Ответ 5

UPDATE tasks
SET guid = %d, params = @params := params
WHERE guid = 0 LIMIT 1;

Он вернет 1 или 0, в зависимости от того, были ли значения эффективно изменены.

SELECT @params AS params;

Это просто выбирает переменную из соединения.

От: здесь

Ответ 6

У меня такая же проблема. Вместо этого мы использовали PostreSQL и UPDATE ... RETURNING:

Дополнительное предложение RETURNING заставляет UPDATE вычислять и возвращать значения (значения) на основе каждой реально обновленной строки. Любое выражение, использующее столбцы таблицы и/или столбцы других таблиц, упомянутых в FROM, может быть вычислено. Используются новые (пост-обновления) значения столбцов таблицы. Синтаксис списка RETURNING идентичен синтаксису выходного списка SELECT.

Пример: UPDATE 'my_table' SET 'status' = 1 WHERE 'status' = 0 LIMIT 1 RETURNING *;

Или, в вашем случае: UPDATE 'tasks' SET 'guid' = %d WHERE 'guid' = 0 LIMIT 1 RETURNING 'params';

Извините, я знаю, что это не отвечает на вопрос с MySQL, и было бы непросто просто переключиться на PostgreSQL, но это лучший способ, который мы нашли для этого. Еще через 6 лет MySQL по-прежнему не поддерживает UPDATE ... RETURNING. Он может быть добавлен в какой-то момент в будущем, но на данный момент MariaDB имеет только для операторов DELETE.

Изменить. Задача (низкий приоритет) - добавить UPDATE ... RETURNING поддержку MariaDB.