2012-03-23 3 views
1

Я хочу извлечь инкрементное обновление из таблицы MySQL. В рассматриваемой таблице есть поле с автоматически увеличивающимся идентификатором и поле updated_at, которое обновляется до текущей метки времени при каждом изменении (INSERT/UPDATE). Записи никогда не удаляются из этой таблицы.Извлечение инкрементного обновления из таблицы MySQL

Я хотел бы извлечь все вновь созданные и обновленные записи из этой таблицы с момента последнего запуска скрипта. Я знаю самое высокое значение update_at от последнего прогона. Таким образом, основной запрос на извлечение записей будет примерно таким:

SELECT * FROM table WHERE updated_at >= :last_seen_updated_at 

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

  • Несколько записей могут быть обновлены в течение той же секунды, некоторые из которых, возможно, были включены в предыдущий цикл извлечения, некоторые из которых не были. (например: экстрактор работает в первой половине второго, тогда как запись может быть обновлена ​​во второй половине второй.
  • Должен ли я использовать один большой запрос SELECT или использовать несколько запросов для извлечения партий X-записей Обратите внимание, что объем данных, которые нужно извлечь, может быть большим. Если я использую партии, записи могут обновляться между разными запросами.
  • Предпочтительно, чтобы он не извлекал дубликаты записей, но это не большая проблема. имеет смысл начать сумму X времени до последнего видели обновления, «на всякий случай»? (например, updated_at >= :last_seen_updated_at - INTERVAL 1 MINUTE)
  • Какой режим изоляции я должен выполнять эти запросы в? REPEATABLE READ? SERIALIZABLE?
  • для MySQL d atabase - это реплицированное подчиненное устройство, которое иногда несколько отстает от основной DB. Может ли это повлиять на включенные строки или нет?

ответ

1

Это не полный ответ, но это надежный способ избежать дубликатов. Во-первых, при запуске сценария обновления не запускайте его в течение текущей секунды. Запустите его во всем, что больше, чем, скажем, 5 секунд. Таким образом, вы знаете, что если у вас есть одна запись за определенную секунду, у вас есть все записи за эту секунду. Сделав это, вы сможете использовать updated_at > :last_seen_updated_at и избегать дублирования между циклами обновления.

В этот момент вы должны без проблем извлекать партии или один большой запрос. По крайней мере, как вы описали таблицу, данные, которые вы будете извлекать, в этот момент будут в значительной степени статичными - вполне могут быть другие записи, добавленные в таблицу, когда вы идете, но все они будут после любых ваших произвольных последнее сокращение второе, и поэтому не будет частью вашего запроса.

Что касается проблемы с ведомым/ведущим устройством, это может быть немного опасно, но до тех пор, пока мастер сначала обновит старые записи, это все еще довольно легко решить. При настройке обрезания обновления найдите самый последний временной интервал в локальной записи и вычтите одну секунду.

По-прежнему существует проблема, когда запись, которая была добавлена ​​или обновлена ​​в разделе времени, на которое вы обращали внимание, может быть обновлена ​​снова во время извлечения. Единственный способ строго запретить это - отключиться от изменения сервера и буфера при извлечении, но вы можете значительно сократить частоту, вернувшись и запустив скрипт еще раз после того, как вы закончите для относительно небольшого количества добавлений и измените которые произошли, когда вы извлекали большую группу. Вы можете повторять это столько раз, сколько вы считаете паранойей. В качестве альтернативы вы можете подсчитать количество строк предварительного извлечения, извлечь и подсчитать количество извлеченных. Если есть какая-либо разница, вы можете снова запустить процесс, пока не получите тот же номер до и после.