2015-06-21 4 views
1

Я столкнулся с проблемой и не могу выбрать правильное решение.MySQL - обновите определенный столбец сразу после выбора

У меня есть запрос SELECT, который выбирает записи из таблицы. Эти записи имеют состояние столбец, как показано ниже.

SELECT id, <...>, status FROM table WHERE something 

Теперь, сразу после этого ВЫБРАТЬ я должен UPDATE колонке статуса. Как я могу сделать это, чтобы избежать состояния гонки?

Что я хочу достичь, если кто-то (сессия) что-то выбрал, это не может быть выбрано кем-либо другим, пока я не выпущу его вручную (например, используя столбец статуса).

Мысли?

+0

Используйте процедуру для возврата результатов и добавьте обновление после столбца флажка. – Mihai

+0

Почему вы выбираете его? – Strawberry

+0

Я выбираю клиента и делаю автоматический вызов на основе поля phone_number. Проблема в том, что если я уже отправил клиента на звонок, я не хочу, чтобы этот клиент появлялся другому парню call-центра. Теперь происходит то, что тот же клиент появляется для двух или более парней call-центра, и это плохо. – daryqsyro

ответ

2

There - это некоторая документация по mysql, может быть интересно решить вашу задачу, не уверен, что она вам подходит, но она описывает правильный способ выбора, за которым следует обновление.

Описанная техника не предотвращает чтение других сессий, но предотвращает запись выбранной записи до конца транзакции.

Он содержит пример, аналогичный вашу проблему:

SELECT counter_field FROM child_codes FOR UPDATE; 
UPDATE child_codes SET counter_field = counter_field + 1; 

Это требуется, что вы таблицы используют Innodb двигатель и ваши программы используют транзакцию.

Если вам нужна блокировка только на короткое время, то есть один сеанс выберите строку с замком, обновить его и снять блокировку в одной сессии, то вам не нужно состояние поля на всех, просто используйте select ... for update и select ... lock in share mode так, если все сеансы будут использовать эти два совместно с транзакциями select... for update, а затем update, чтобы изменить, и select ... with shared lock, чтобы просто читать - это решит ваши требования.

Если вам нужно заблокировать в течение длительного времени, выберите и заблокируйте в течение одного сеанса, а затем обновите и отпустите в другом, а затем правильно используйте некоторое хранилище, чтобы сохранить статусы блокировки, и весь сеанс должен использоваться, как описано ниже: select ... for update и установить статус и статус владельца в один сеанс, затем в другом сеансе select for update проверить статус и владельца, обновить и удалить статус - для сценария обновления и для сценария чтения: select ... with shared lock проверить статус.

1

Вы можете сделать это с некоторыми препаратами. Добавьте столбец sessionId к вашему столу. Он должен быть NULL -able, и он будет содержать уникальный идентификатор сеанса, который получает строку. Также добавьте индекс в этот новый столбец; мы будем использовать столбец для поиска строк в таблице.

ALTER TABLE `tbl` 
    ADD COLUMN `sessionId` CHAR(32) DEFAULT NULL, 
    ADD INDEX `sessionId`(`sessionId`) 

Когда сеанс необходимо приобрести несколько строк (на основе некоторых критериев) работают:

UPDATE `tbl` 
SET `sessionId` = 'aaa' 
WHERE `sessionId` IS NULL 
    AND ... 
LIMIT bbb 

Заменить aaa с текущим идентификатором сеанса и ... с условиями, которые необходимо выбрать правильные строки. Замените bbb на количество строк, которые вам нужно приобрести.Добавьте предложение ORDER BY, если вам нужно обработать строки в определенном порядке (если некоторые из них имеют более высокий приоритет, чем другие). Вы также можете добавить status = ... в предложение UPDATE, чтобы изменить статус полученных строк (до pending f.e.), чтобы другие экземпляры кода знали, что эти строки обрабатываются прямо сейчас.

Вышеприведенный запрос содержит несколько строк. Затем запустите:

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

После каждой строки обрабатывается, вы либо DELETE строки или UPDATE его и установить sessionId к NULL (освободить строку) и status, чтобы отразить ее новый статус.

Также вы должны освободить строки (используя ту же процедуру, что и выше), когда сессия закрыта.

+0

Нет ли какой-либо красоты и удобного метода? Все, что мне нужно - это блокировать строки/строки, которые были/были выбраны в последнем объявлении, и иметь возможность выпускать его, когда мне это нужно. – daryqsyro

Смежные вопросы