it-roy-ru.com

MySQL ОБНОВЛЕНИЕ и ВЫБОР в один проход

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

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

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

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

  • SELECT params
    FROM tasks
    WHERE guid = %d 

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

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

18
Paul Oyster

попробуй вот так

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

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

9
charles

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

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;
6
Quassnoi

У меня точно такая же проблема. Вместо этого мы использовали 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 .

1
Marco Roy

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

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

1
Paulo

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

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

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

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

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

SELECT @params AS params;

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

От: здесь

0
jogaco