Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Проверка идентичности таблиц при репликации БД
|
|||
|---|---|---|---|
|
#18+
Прошу совета у гуру. Есть две БД одинаковой структуры и самописный репликатор. В процессе репликации нужно сверять таблицы (точнее, куски таблиц с фильтром по foreign key) на соответствие данных, и, при отличии, - реплицировать. При этом отличается обычно не более ~10% данных, т.е. большинство кусков пропускается без репликации. Нужен быстрый алгоритм сверки. Сверять все поля во всех записях - долго. Сверять ключи - недостаточно (update'ы пропустим). Пока в каждую таблицу добавлено поле lmts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; обновляемое триггером при каждом update'е. Есть идея брать хеш (например, CRC32) этого поля во всех записях, и считать разный хеш признаком отличия данных. Собсно, вопросы: 1) какова вероятность ошибки, т.е. одинакового хеша при разных данных, на ~10000 записях? 2) есть ли в PG быстрая хеш-функция для целых чисел, типа CRC32? (MD5 не катит) Или, может, кто-нибудь решал подобную задачу как-то иначе. Буду рад совету... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.10.2007, 12:57 |
|
||
|
Проверка идентичности таблиц при репликации БД
|
|||
|---|---|---|---|
|
#18+
Я бы, наверное, использовал sequence. При создании таблицы - Код: plaintext ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.10.2007, 14:22 |
|
||
|
Проверка идентичности таблиц при репликации БД
|
|||
|---|---|---|---|
|
#18+
Oleg Zhovtanyuk Есть две БД одинаковой структуры и самописный репликатор. В процессе репликации нужно сверять таблицы (точнее, куски таблиц с фильтром по foreign key) на соответствие данных, и, при отличии, - реплицировать. При этом отличается обычно не более ~10% данных, т.е. большинство кусков пропускается без репликации. ИМХО странный подход к репликации. Огромный объем обрабатываемых данных при каждой сессии репликации. Геморойно и долго. Советую поискать другой путь. Мы, например, ведем что-то на подобии лога транзакции, реализованный на триггерах. Объем передаваемых данных минимален. Oleg Zhovtanyuk Собсно, вопросы: 1) какова вероятность ошибки, т.е. одинакового хеша при разных данных, на ~10000 записях? 2) есть ли в PG быстрая хеш-функция для целых чисел, типа CRC32? (MD5 не катит) 1. Невысокая, но есть 2. А зачем для целых чисел хеш??? Да и для float не нужен. ИХМО: 1. Или идти по пути лога действий. 2. Идти по пути предложенному _Андрей_М , и сделать два поля - когда и где менялась запись. И потом уже выбирать такие записи самому - т.е. по сути ситуативная генерация лога измененных записей. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.10.2007, 14:37 |
|
||
|
Проверка идентичности таблиц при репликации БД
|
|||
|---|---|---|---|
|
#18+
Сначала объясню, почему выбран именно этот путь. В штатном режиме приложение пишет данные "зеркально" в 2 БД, а читает из них поочередно, балансируя нагрузку. Репликация же идет не в рантайме, а только в процессе восстановления, если одна из БД упала, и ее потом подняли. Т.е. фактически надо перенести из оставшейся рабочей БД в помершую, разницу - за несколько часов это не более 1-2% данных (10% - с запасом). Эдакий diff :-) Реплицировать кусками, соответствующими данным 1 пользователя, потому что приложение определяет пользователей, чьи данные разошлись и переводит их в read-only режим, а потом "пускает" по мере синхронизации соотв. кусков. В итоге теряем в скорости репликации (которая происходит чем реже, тем лучше :-) и выигрываем на отсутствии лога действий, который бы велся постоянно. Вариант с логом не катит, т.к. дает 3-кратный оверхед в рантайме. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.10.2007, 16:26 |
|
||
|
Проверка идентичности таблиц при репликации БД
|
|||
|---|---|---|---|
|
#18+
_Андрей_МЯ бы, наверное, использовал sequence. При создании таблицы - Код: plaintext Я, наверное, плохо объяснил: у нас уникальные ID и так есть. И триггер на апдейт поля lmts (Last Modification TimeStamp) тоже есть. Засада в том, что если тупо втягивать и сверять наборы ID и lmts из обоих таблиц, то это почти гарантирует вылет по памяти - их там дофига. И долго. Нужна функция внутри PG, которая быстро посчитает хеш от всех полей lmts (скажем, их 100000). Если он разный в 2 БД, значит и данные различаются - надо реплицировать. ИМХО, это соответствует проверке CRC для файлов, т.е. достаточно надежно. Или я что-то упустил? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.10.2007, 16:45 |
|
||
|
Проверка идентичности таблиц при репликации БД
|
|||
|---|---|---|---|
|
#18+
А зачем тупо проверять? Если нумерация инкрементная, смотрим макс. uniq_code у упавшей базы и восстанавливаем всё, что больше макс. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.10.2007, 16:59 |
|
||
|
Проверка идентичности таблиц при репликации БД
|
|||
|---|---|---|---|
|
#18+
Oleg ZhovtanyukСначала объясню, почему выбран именно этот путь. В штатном режиме приложение пишет данные "зеркально" в 2 БД, а читает из них поочередно, балансируя нагрузку. Репликация же идет не в рантайме, а только в процессе восстановления, если одна из БД упала, и ее потом подняли. Т.е. фактически надо перенести из оставшейся рабочей БД в помершую, разницу - за несколько часов это не более 1-2% данных (10% - с запасом). Эдакий diff :-) Реплицировать кусками, соответствующими данным 1 пользователя, потому что приложение определяет пользователей, чьи данные разошлись и переводит их в read-only режим, а потом "пускает" по мере синхронизации соотв. кусков. В итоге теряем в скорости репликации (которая происходит чем реже, тем лучше :-) и выигрываем на отсутствии лога действий, который бы велся постоянно. Вариант с логом не катит, т.к. дает 3-кратный оверхед в рантайме. Ну тогда можно: 1. Триггер логирующий в таблицу когда и где модифицирована запись. 2. Некую таблицу, в которой вести некое "отслеживание" жизнеспособности. Из серии "13:00", "полет нормальный", БД1. В которой этот полет нормальный и время отслеживались бы системой репликацией в фоновом режиме - раз в час, два - как захотите. Желательно перед бекапом. 3. При падении базы. Для простоты пусть рухнула БД2, жива БД1. 3.1 Поднимаем (из бекапа?) БД2. 3.2 В БД2 у нас есть время когда "было хорошо" ТА (п. 2) 3.3 В БД1 запрашиваются данные по всем таблицам, которые имеют дату модификации больше ТА, и модифицированы в БД 1. Если данные модифицируются только в одной БД или одновременно, то можно не вести лог БД. Вроде на правду похоже. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.10.2007, 17:05 |
|
||
|
Проверка идентичности таблиц при репликации БД
|
|||
|---|---|---|---|
|
#18+
_Андрей_МА зачем тупо проверять? Если нумерация инкрементная, смотрим макс. uniq_code у упавшей базы и восстанавливаем всё, что больше макс. Примерно так и было сделано, только вместо инкремента - lmts = now(). Выяснилось, что пропускаются: - удаление записей, т.к. оно не влияет на ID/lmts, - старые данные. Первая проблема решена отдельной таблицей с историей удалений и опять же триггером на DELETE. А вот вторая... Например, БД1 запущена месяц назад (боевой сервер), а БД2 - сегодня (резервный). Данные из БД1 с момента старта по вчерашний день таким образом не отловить. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.10.2007, 17:36 |
|
||
|
Проверка идентичности таблиц при репликации БД
|
|||
|---|---|---|---|
|
#18+
Andrey Daeron[quot Oleg Zhovtanyuk] ... Ну тогда можно: 1. Триггер логирующий в таблицу когда и где модифицирована запись. 2. Некую таблицу, в которой вести некое "отслеживание" жизнеспособности. Из серии "13:00", "полет нормальный", БД1. В которой этот полет нормальный и время отслеживались бы системой репликацией в фоновом режиме - раз в час, два - как захотите. Желательно перед бекапом. 3. При падении базы. Для простоты пусть рухнула БД2, жива БД1. 3.1 Поднимаем (из бекапа?) БД2. 3.2 В БД2 у нас есть время когда "было хорошо" ТА (п. 2) 3.3 В БД1 запрашиваются данные по всем таблицам, которые имеют дату модификации больше ТА, и модифицированы в БД 1. Если данные модифицируются только в одной БД или одновременно, то можно не вести лог БД. Вроде на правду похоже. Логично. БД2 и есть бекап для БД1 и наоборот - это классический RAIDb0 (mirroring). 1. Триггер как раз и пишет lmts = now(). 2. "Отслеживание жизнеспособности" возложено на драйвер, который пингует обе БД каждые 15 сек. 3. ... 3.1 Угу... 3.2 Это максимальный lmts по всем таблицам. Выведен через вьюху. 3.3. ... и благополучно пропускаются старые данные в БД1, если lmts(БД1) = lmts(БД2). Репликатор считает базы синхронными, о чем бодро и рапортует. Т.е. мне надо проверить не только последний ID/lmts, а соответствие всех lmts в таблице. Для чего и хочу хеш-функцию. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.10.2007, 17:51 |
|
||
|
Проверка идентичности таблиц при репликации БД
|
|||
|---|---|---|---|
|
#18+
Oleg Zhovtanyuk 1. Триггер как раз и пишет lmts = now(). 2. "Отслеживание жизнеспособности" возложено на драйвер, который пингует обе БД каждые 15 сек. 3. ... 3.1 Угу... 3.2 Это максимальный lmts по всем таблицам. Выведен через вьюху. 3.3. ... и благополучно пропускаются старые данные в БД1, если lmts(БД1) = lmts(БД2). Репликатор считает базы синхронными, о чем бодро и рапортует. Т.е. мне надо проверить не только последний ID/lmts, а соответствие всех lmts в таблице. Для чего и хочу хеш-функцию. 3.2 - ну пусть будет так Бррр. Не понял. А когда тогда и что навернулось? Откуда возьмется lmts(БД1) = lmts(БД2), если БД2 рухнула после "максимального lmts"? До этого момента гарантировано все хорошо. Если нет - то приведите пример такой модификации. В принципе - можно ли зафксировать момент когда "все хорощо" и данные на этот момент синхронны полностью? Удаление - согласен. У нас оно вообще многокаскадное - репликация на сетке филиалов разного уровня. Клиенту не отдаются записи если у них стоит признак удаленности + запись может быть восстановлена. Идеальное решение для Вас - это только синхронное удаление в двух базах, может тут двухфазный коммит поможет. ЗЫ И что Вы будете делать если будет нужно сравнить 10^6 записей? Даже по хешу? Это слишком много сравнений. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.10.2007, 20:49 |
|
||
|
Проверка идентичности таблиц при репликации БД
|
|||
|---|---|---|---|
|
#18+
Andrey Daeron Oleg Zhovtanyuk 1. Триггер как раз и пишет lmts = now(). 2. "Отслеживание жизнеспособности" возложено на драйвер, который пингует обе БД каждые 15 сек. 3. ... 3.1 Угу... 3.2 Это максимальный lmts по всем таблицам. Выведен через вьюху. 3.3. ... и благополучно пропускаются старые данные в БД1, если lmts(БД1) = lmts(БД2). Репликатор считает базы синхронными, о чем бодро и рапортует. Т.е. мне надо проверить не только последний ID/lmts, а соответствие всех lmts в таблице. Для чего и хочу хеш-функцию. 3.2 - ну пусть будет так Бррр. Не понял. А когда тогда и что навернулось? Откуда возьмется lmts(БД1) = lmts(БД2), если БД2 рухнула после "максимального lmts"? До этого момента гарантировано все хорошо. Если нет - то приведите пример такой модификации. В принципе - можно ли зафксировать момент когда "все хорощо" и данные на этот момент синхронны полностью? Удаление - согласен. У нас оно вообще многокаскадное - репликация на сетке филиалов разного уровня. Клиенту не отдаются записи если у них стоит признак удаленности + запись может быть восстановлена. Идеальное решение для Вас - это только синхронное удаление в двух базах, может тут двухфазный коммит поможет. ЗЫ И что Вы будете делать если будет нужно сравнить 10^6 записей? Даже по хешу? Это слишком много сравнений. Навернулся на взлете резервный сервер приложений вместе с репликатором, который подключили к основному, при этом БД осталась жива. Основной сервер (он нацелен на ту же пару БД) пустил пользователя и изменил одну из таблиц (не суть, какую, скажем - статистику логинов). Все, lmts одинаковы - они же считаются по последней обновленной записи. После починки упавшего сервера его снова запускают, стартует репликатор, видит, что БД синхронны и радостно говорит, что ему делать нечего. Все. На основном сервере данные за месяц. На резервном их нет. Под хешем я имею в виду функцию от всех записей, так что для любого их числа он 1. И сравнение, соответственно, одно. Стоимость его вычисления - другой вопрос ;-) Удаление из приложения у нас вообще асинхронное, чтобы балансировать нагрузку: ставим флаг, чтобы исключить записи из SELECT'ов, а потом в фоне потихоньку удаляем. Двухфазный коммит - не катит, слишком тормозит в рантайме, плюс тот, кто его осуществляет (скажем, JBoss) - это лишний сервер, который тоже может упасть. Не буду поминать Оккама всуе... Поэтому за синхронное обновление/удаление отвечает сам JDBC-драйвер. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2007, 13:21 |
|
||
|
Проверка идентичности таблиц при репликации БД
|
|||
|---|---|---|---|
|
#18+
Спасибо всем отозвавшимся за идеи и помощь. Проблема решена. Поковырявшись, окончательно убедился, что хеш не спасает. Выполненный из драйвера на паре БД now() дает различные данные из-за сетевого лага, так что по lmts хешировать нельзя. По ID - тоже, он не меняется при UPDATE'е. В итоге просто взял не только время последней (lmts), но и первой (fmts) модификации данных. Примерно так: Код: plaintext 1. 2. 3. 4. 5. 6. 7. Код: plaintext Код: plaintext БД считаю верными, если совпадают оба значения, если совпадает только lmts, то это как раз сбой на взлете, описанный в предыдущем посте. Тогда просто ругаюсь и требую очистки резервной БД и перезапуска. При этом идет полная репликация, которая переносит все данные. Работает долго, но это ведь и очень редкий случай. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2007, 13:36 |
|
||
|
Проверка идентичности таблиц при репликации БД
|
|||
|---|---|---|---|
|
#18+
Oleg Zhovtanyuk Навернулся на взлете резервный сервер приложений вместе с репликатором, который подключили к основному, при этом БД осталась жива. Основной сервер (он нацелен на ту же пару БД) пустил пользователя и изменил одну из таблиц (не суть, какую, скажем - статистику логинов). Все, lmts одинаковы - они же считаются по последней обновленной записи. После починки упавшего сервера его снова запускают, стартует репликатор, видит, что БД синхронны и радостно говорит, что ему делать нечего. Все. На основном сервере данные за месяц. На резервном их нет. Все равно не до конца понял :( То время коорое предлагал я - это время последнего момента когда репликация (т.е. внесение данных в обе базы) гарантированно работал. Живы БД или нет - не важно. Важно ослеживание момента когда все было еще хорошо. И что бы это было не начало времен max(lmts) действительно не дает таких гарантий. И тогда восстановление будет занимать гораздо меньше времени. А Ваше решение тоже мне не понятно. А fmts - проставляется триггером во время первого UPDATE или INSERT? А что если запись модифицировалась более одного раза? А потом "что-то" навернулось? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2007, 14:04 |
|
||
|
|

start [/forum/topic.php?fid=53&fpage=285&tid=2004971]: |
0ms |
get settings: |
7ms |
get forum list: |
11ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
32ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
36ms |
get tp. blocked users: |
1ms |
| others: | 211ms |
| total: | 316ms |

| 0 / 0 |
