Извлечение инкрементного обновления из таблицы MySQL - PullRequest
1 голос
/ 23 марта 2012

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

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

SELECT * FROM table WHERE updated_at >= :last_seen_updated_at

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

  • Несколько записей могут быть обновлены в течение одной секунды, некоторые из которых могли быть включены в предыдущий прогон извлечения, а некоторые - нет. (Например: экстрактор запускается в первой половине второй, в то время как запись может обновляться во второй половине второй.
  • Должен ли я использовать один большой запрос SELECT или несколько запросов для извлечения пакетов из X записей? Обратите внимание, что объем извлекаемых данных может быть большим. Если я использую пакеты, записи могут обновляться между различными запросами.
  • Предпочтительно, он не должен извлекать дубликаты записей, но это не большая проблема. Имеет ли смысл начинать X раз до последнего увиденного обновления, «просто чтобы быть в безопасности»? (например, updated_at >= :last_seen_updated_at - INTERVAL 1 MINUTE)
  • В каком режиме изоляции мне следует запускать эти запросы? ПОВТОРЯЕМЫЙ ЧИТАТЬ? SERIALIZABLE
  • База данных MySQL является реплицированным ведомым устройством, которое иногда несколько отстает от главной базы данных. Может ли это повлиять на включение строк или нет?

1 Ответ

1 голос
/ 23 марта 2012

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

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

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

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

...