SQL (mySQL) обновляет некоторое значение во всех записях, обработанных выбором - PullRequest
1 голос
/ 21 января 2010

Я использую mySQL из их C API, но это не должно относиться к делу. Мой код должен обрабатывать записи из таблицы, которые соответствуют некоторым критериям, а затем обновлять указанные записи, чтобы пометить их как обработанные. Строки в таблице изменены / вставлены / удалены другим процессом, который я не контролирую. Я боюсь в следующем, ОБНОВЛЕНИЕ может пометить некоторые записи ошибочно, так как набор соответствия записей мог измениться между шагом 1 и шагом 3.

SELECT * FROM myTable WHERE <CONDITION>; # step 1
<iterate over the selected set of lines. This may take some time.> # step 2
UPDATE myTable SET processed=1 WHERE <CONDITION> # step 3

Какой разумный способ обеспечить, чтобы ОБНОВЛЕНИЕ обновляло все обработанные строки и только их? Кажется, что транзакция не соответствует требованиям, так как она не обеспечивает такого рода изоляцию: недавно измененная запись, не входящая в первоначально выбранный набор, все еще может быть целью оператора UPDATE. По той же причине, SELECT ... FOR UPDATE, похоже, не помогает, хотя звучит многообещающе: -)

Единственный способ увидеть это - использовать временную таблицу для запоминания набора строк, которые нужно обработать, делая что-то вроде:

CREATE TEMPORARY TABLE workOrder (jobId INT(11));
INSERT INTO workOrder SELECT myID as jobId FROM myTable WHERE <CONDITION>;
SELECT * FROM myTable WHERE myID IN (SELECT * FROM workOrder);
<iterate over the selected set of lines. This may take some time.>
UPDATE myTable SET processed=1 WHERE myID IN (SELECT * FROM workOrder);
DROP TABLE workOrder;

Но это кажется расточительным и не очень эффективным.

Есть ли что-нибудь умнее?

Большое спасибо новичку в SQL.

Ответы [ 2 ]

1 голос
/ 21 марта 2010

Я в конце концов решил эту проблему, используя столбец в этой таблице, который помечает строки в соответствии с их статусом. Этот столбец позволяет мне реализовать простой конечный автомат. Концептуально, у меня есть два возможных значения для этого статуса:

kNoProcessingPlanned = 0; #default "idle" value
kProcessingUnderWay = 1;

Теперь мой алгоритм работает примерно так:

UPDATE myTable SET status=kProcessingUnderWay WHERE <CONDITION>; # step 0

SELECT * FROM myTable WHERE status=kProcessingUnderWay; # step 1
    <iterate over the selected set of lines. This may take some time.> # step 2
UPDATE myTable SET processed=1, status=kNoProcessingPlanned WHERE status=kProcessingUnderWay # step 3

Эта идея иметь строки в нескольких состояниях может быть расширена до необходимого количества состояний.

1 голос
/ 21 января 2010

Есть несколько вариантов:

  1. Вы можете заблокировать стол

  2. Вы можете добавить AND foo_id IN (all_the_ids_you_processed) в качестве условия обновления.

  3. вы можете обновить перед выбором и затем выбирать только обновленные строки (т.е. по дате обработки)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...