Потеря данных при репликации, IB 7.5
-
- Сообщения: 35
- Зарегистрирован: 16 авг 2007, 15:13
Потеря данных при репликации, IB 7.5
Столкнулся с потерей данных при репликации. Не решал ли кто-либо подобную проблему? Вот описание:
IB 7.5, режиим SuperServer, Win Server 2003, HyperThread включен.
Есть две базы - Оперативная и Аналитическая. В Оперативной данные текущего дня, в Аналитческой базе данные за год. Нынешний объем Аналитической базы 8 гигов. Ведется непрерываная репликация данных с Оперативной на Аналитическую. Кол-во перекачиваемых записей в сутки ~500.000. Пиковая нагрузка при перекачке ~30-50 записей/сек. Одновременных соединений с базой Оперативной ~50. С Аналитической ~10-15. Backup-restore Аналитической базы выполняется крайне редко, слишком долгая процедура.
Описание структуры данных базы на пальцах.
Есть таблица T_BENTITY (состояние бизнес-объекта, primary key field BEID). На эту таблицу ссылаются все таблицы с бизнес-объектами, у них тоже есть ссылочное поле BEID. Все изменения во всех таблицах Оперативной базы через механизм триггеров попадают в очередь репликации (одно изменение-одна запись в очереди). В очередь репликации записи обычно вываливаются небольшими блоками (1-1000 записей). Оттуда репликатор их последовательно проталкивает в Аналитическую базу.
Репликатор свой, работает непрерывно, режим работы транзакций ReadComitted, Wait. Использует компоненты IBX 6.08. На каждую запись в очереди репликации в обоих базах (Аналитике и в Оперативной) открывается по отдельной транзакции. Успешно прокачанной запись считается, если:
а) соотв. запрос в Аналитике прошел без exception. Если запрос типа update и закончился без exception, но ничего в Аналитической базе не поменял, то запись считается ошибочной;
б) запись успешно удалена из очереди репликации.
Поcле успешного окончания запись удаляется из очереди репликации.
По каждой записи ведётся лог - прошла или не прошла - во внешнем текстовом файле. Примечание: кол-во изменных записей в update запросах считывается через свойствo RowsAffected компонента TIBSQL.
Теперь описание проблемы.
Один из типичных случаев, выдран из лог-файла репликатора, как пример.
Рассматриваем две таблицы T_BENTITY (бизнес-сущность), T_RGOODS (прибывший товар). T_RGOODS ссылается на T_BEID по полю BEID.
16.08 3:09:58 Тип: Ok
SEQID: 27711
SQL: INSERT INTO T_BENTITY (BTIME,BCLASSID,BOWNERBEID,BSTATEID,BUSERBEID,BEID) VALUES ('2007-08-15 23:38:13.0000',310,1,11,1,2072261010057931)
SQLCHECK:
ЗЫ: INSERT INTO T_BENTITY в Аналитическую базу прошел успешно,
транзакция закрыта нормально.
16.08 3:09:58 Тип: Ok
SEQID: 27712
SQL: INSERT INTO T_RGOODS (RSALES,DUMMY,BARCODE,BEID,GDATE,GTIME,RECELINEID,UNKNOWNF,WDATE,RGOODSID,LOTID,UnMarked,MDATE,PARTNERID) VALUES (0,0,951763070814,2072261010057931,'2007-08-15','23:38:00.0000',2072261000000838,0,'2007-08-15',2072261000014885,1,0,'2007-08-15',2061861000000052)
SQLCHECK:
ЗЫ: INSERT INTO T_RGOODS прошел успешно, эта запись ссылается на только что вставленную запись в T_BENTITY
далее разрыв в пять часов, ссылок и обращений в логе на эту запись не было, т.е. репликатор удалить её не мог.
16.08 8:50:24 Тип: Внимание!
SEQID: 180354
SQL: UPDATE T_BENTITY SET BTIME='2007-08-16 08:50:07.0000', BCLASSID=310, BOWNERBEID=1, BSTATEID=15, BUSERBEID=1 WHERE BEID=2072261010057931
SQLCHECK: SELECT BEID FROM T_BENTITY WHERE BEID=2072261010057931
Update(delete) запрос не подействовал
ЗЫ попытка update записи в T_BENTITY. НО!!!! запись не найдена, update не выполнен, выдана ошибка. Репликатор сразу пытается исправить ошибку в базе и заново вставить пропавшую запись, есть у него такое умение. Вставка проходит успешно. Т.е. записи в Аналитической базе действительно не было, т.к. при исправляющей вставке не было ошибки по главному ключу. В предыдущих версиях репликатора исправляющей вставки не было, и обычно далее следовали ошибки при update-ах записей ссылающихся на T_BENTITY (в рассматриваемом случае это T_RGOODS)
Странная какая-то картинка. Такая ситуация была бы допустима, если какое-то рабочее место удалит запись в T_BENTITY из Аналитики, но это возможно только в том случае, если удалят ссылающуюся на неё T_RGOODS. А её никто не удалял, она в базе есть, это проверено.
Ошибок в логе IB за рассматриваемы промежуток времени не было. Были только INET/inet_error: read errno = 10054 - потеря коннекта с клиентом.
И еще IB был перезапущен за три минуты перед первоначальной вставкой, вот сообщение в логе
DC-DBS2 (Server) Thu Aug 16 03:03:11 2007
SERVER/set_process_affinity: hyper-threading ProcessAffinityMask is 3
DC-DBS2 (Server) Thu Aug 16 03:03:11 2007
SERVER/set_process_affinity: setting ProcessAffinityMask to 3
DC-DBS2 (Server) Thu Aug 16 03:03:11 2007
Server: setting SWEEP_QUANTUM to 250, USER_QUANTUM to 500,
SWEEP_YIELD_TIME to 0 ms, and MAX_THREADS to 1000
SQL_COMPILER_RECURSION to 2000
В-общем, прошу помощи!
IB 7.5, режиим SuperServer, Win Server 2003, HyperThread включен.
Есть две базы - Оперативная и Аналитическая. В Оперативной данные текущего дня, в Аналитческой базе данные за год. Нынешний объем Аналитической базы 8 гигов. Ведется непрерываная репликация данных с Оперативной на Аналитическую. Кол-во перекачиваемых записей в сутки ~500.000. Пиковая нагрузка при перекачке ~30-50 записей/сек. Одновременных соединений с базой Оперативной ~50. С Аналитической ~10-15. Backup-restore Аналитической базы выполняется крайне редко, слишком долгая процедура.
Описание структуры данных базы на пальцах.
Есть таблица T_BENTITY (состояние бизнес-объекта, primary key field BEID). На эту таблицу ссылаются все таблицы с бизнес-объектами, у них тоже есть ссылочное поле BEID. Все изменения во всех таблицах Оперативной базы через механизм триггеров попадают в очередь репликации (одно изменение-одна запись в очереди). В очередь репликации записи обычно вываливаются небольшими блоками (1-1000 записей). Оттуда репликатор их последовательно проталкивает в Аналитическую базу.
Репликатор свой, работает непрерывно, режим работы транзакций ReadComitted, Wait. Использует компоненты IBX 6.08. На каждую запись в очереди репликации в обоих базах (Аналитике и в Оперативной) открывается по отдельной транзакции. Успешно прокачанной запись считается, если:
а) соотв. запрос в Аналитике прошел без exception. Если запрос типа update и закончился без exception, но ничего в Аналитической базе не поменял, то запись считается ошибочной;
б) запись успешно удалена из очереди репликации.
Поcле успешного окончания запись удаляется из очереди репликации.
По каждой записи ведётся лог - прошла или не прошла - во внешнем текстовом файле. Примечание: кол-во изменных записей в update запросах считывается через свойствo RowsAffected компонента TIBSQL.
Теперь описание проблемы.
Один из типичных случаев, выдран из лог-файла репликатора, как пример.
Рассматриваем две таблицы T_BENTITY (бизнес-сущность), T_RGOODS (прибывший товар). T_RGOODS ссылается на T_BEID по полю BEID.
16.08 3:09:58 Тип: Ok
SEQID: 27711
SQL: INSERT INTO T_BENTITY (BTIME,BCLASSID,BOWNERBEID,BSTATEID,BUSERBEID,BEID) VALUES ('2007-08-15 23:38:13.0000',310,1,11,1,2072261010057931)
SQLCHECK:
ЗЫ: INSERT INTO T_BENTITY в Аналитическую базу прошел успешно,
транзакция закрыта нормально.
16.08 3:09:58 Тип: Ok
SEQID: 27712
SQL: INSERT INTO T_RGOODS (RSALES,DUMMY,BARCODE,BEID,GDATE,GTIME,RECELINEID,UNKNOWNF,WDATE,RGOODSID,LOTID,UnMarked,MDATE,PARTNERID) VALUES (0,0,951763070814,2072261010057931,'2007-08-15','23:38:00.0000',2072261000000838,0,'2007-08-15',2072261000014885,1,0,'2007-08-15',2061861000000052)
SQLCHECK:
ЗЫ: INSERT INTO T_RGOODS прошел успешно, эта запись ссылается на только что вставленную запись в T_BENTITY
далее разрыв в пять часов, ссылок и обращений в логе на эту запись не было, т.е. репликатор удалить её не мог.
16.08 8:50:24 Тип: Внимание!
SEQID: 180354
SQL: UPDATE T_BENTITY SET BTIME='2007-08-16 08:50:07.0000', BCLASSID=310, BOWNERBEID=1, BSTATEID=15, BUSERBEID=1 WHERE BEID=2072261010057931
SQLCHECK: SELECT BEID FROM T_BENTITY WHERE BEID=2072261010057931
Update(delete) запрос не подействовал
ЗЫ попытка update записи в T_BENTITY. НО!!!! запись не найдена, update не выполнен, выдана ошибка. Репликатор сразу пытается исправить ошибку в базе и заново вставить пропавшую запись, есть у него такое умение. Вставка проходит успешно. Т.е. записи в Аналитической базе действительно не было, т.к. при исправляющей вставке не было ошибки по главному ключу. В предыдущих версиях репликатора исправляющей вставки не было, и обычно далее следовали ошибки при update-ах записей ссылающихся на T_BENTITY (в рассматриваемом случае это T_RGOODS)
Странная какая-то картинка. Такая ситуация была бы допустима, если какое-то рабочее место удалит запись в T_BENTITY из Аналитики, но это возможно только в том случае, если удалят ссылающуюся на неё T_RGOODS. А её никто не удалял, она в базе есть, это проверено.
Ошибок в логе IB за рассматриваемы промежуток времени не было. Были только INET/inet_error: read errno = 10054 - потеря коннекта с клиентом.
И еще IB был перезапущен за три минуты перед первоначальной вставкой, вот сообщение в логе
DC-DBS2 (Server) Thu Aug 16 03:03:11 2007
SERVER/set_process_affinity: hyper-threading ProcessAffinityMask is 3
DC-DBS2 (Server) Thu Aug 16 03:03:11 2007
SERVER/set_process_affinity: setting ProcessAffinityMask to 3
DC-DBS2 (Server) Thu Aug 16 03:03:11 2007
Server: setting SWEEP_QUANTUM to 250, USER_QUANTUM to 500,
SWEEP_YIELD_TIME to 0 ms, and MAX_THREADS to 1000
SQL_COMPILER_RECURSION to 2000
В-общем, прошу помощи!
Последний раз редактировалось Kabaev Sergey 16 авг 2007, 17:02, всего редактировалось 1 раз.
Re: Потеря данных при репликации, IB 7.5
Похоже на повреждённые индексы в аналитической базе. ТогдаKabaev Sergey писал(а): Backup-restore Аналитической базы выполняется крайне редко, слишком долгая процедура.
ЗЫ: INSERT INTO T_BENTITY в Аналитическую базу прошел успешно,
транзакция закрыта нормально.
SQL: UPDATE T_BENTITY SET BTIME='2007-08-16 08:50:07.0000', BCLASSID=310, BOWNERBEID=1, BSTATEID=15, BUSERBEID=1 WHERE BEID=2072261010057931
SQLCHECK: SELECT BEID FROM T_BENTITY WHERE BEID=2072261010057931
Update(delete) запрос не подействовал
ЗЫ попытка update записи в T_BENTITY. НО!!!! запись не найдена, update не выполнен, выдана ошибка. Репликатор сразу пытается исправить ошибку в базе и заново вставить пропавшую запись, есть у него такое умение. Вставка проходит успешно. Т.е. записи в Аналитической базе действительно не было, т.к. при исправляющей вставке не было ошибки по главному ключу.
Код: Выделить всё
SELECT BEID FROM T_BENTITY WHERE BEID=2072261010057931+0
Re: Потеря данных при репликации, IB 7.5
репликатор просто инсертит(апейтит) в БД Аналитики или имеет право при каких-либо условиях там и удалять?Kabaev Sergey писал(а): Оттуда репликатор их последовательно проталкивает в Аналитическую базу.
Репликатор свой, работает непрерывно, режим работы транзакций !
база аналитики только на чтение для пользователей или нет?
поскольку вы редко делаете бакап/рестор для аналитики (если вообще делали?), возможно и проверки над данной базой не запускали?
я к тому, что могли появиться ошибки (как сказал Merlin), которые вы проглядели
ЗЫ
Возможно лог при бакап/ресторе аналитики даст дополнительную информацию, несмотря на потраченное время, но только НЕ рестор в рабочую аналитику, а в новую базу
Последний раз редактировалось stix-s 16 авг 2007, 17:11, всего редактировалось 1 раз.
-
- Сообщения: 35
- Зарегистрирован: 16 авг 2007, 15:13
Не понял про T_RGOODS. Там у тебя FK или нет?
Если нет - почему нельзя удалить мастер-запись?
Так же я не понял, откуда очевидно, что "ЗЫ: INSERT INTO T_BENTITY в Аналитическую базу прошел успешно". Только из лога репликатора?
На случай, если с базой и индексами всё ок - первым делом лезем в код репликатора, и смотрим, а не проглотит ли он по try...except какую-нибудь хитровывернутую ошибку вставки/коммита.
Если нет - почему нельзя удалить мастер-запись?
Так же я не понял, откуда очевидно, что "ЗЫ: INSERT INTO T_BENTITY в Аналитическую базу прошел успешно". Только из лога репликатора?
На случай, если с базой и индексами всё ок - первым делом лезем в код репликатора, и смотрим, а не проглотит ли он по try...except какую-нибудь хитровывернутую ошибку вставки/коммита.
-
- Сообщения: 35
- Зарегистрирован: 16 авг 2007, 15:13
stix-s: репликатор просто инсертит(апейтит) в БД Аналитики или имеет право при каких-либо условиях там и удалять?
база аналитики только на чтение для пользователей или нет?
Репликатор может удалить запись если соотв. запрос будет в очереди репликации. Но в данном случае для того чтобы удалить T_BENTITY нужно сперва удалить ссылающуюся на него запись в T_RGOODS. Там стоит огранчение целостности. Удаления T_RGOODS не было.
база аналитики только на чтение для пользователей или нет?
Репликатор может удалить запись если соотв. запрос будет в очереди репликации. Но в данном случае для того чтобы удалить T_BENTITY нужно сперва удалить ссылающуюся на него запись в T_RGOODS. Там стоит огранчение целостности. Удаления T_RGOODS не было.
-
- Сообщения: 35
- Зарегистрирован: 16 авг 2007, 15:13
Да стоит FK.WildSery писал(а):Не понял про T_RGOODS. Там у тебя FK или нет?
Если нет - почему нельзя удалить мастер-запись?
Так же я не понял, откуда очевидно, что "ЗЫ: INSERT INTO T_BENTITY в Аналитическую базу прошел успешно". Только из лога репликатора?
На случай, если с базой и индексами всё ок - первым делом лезем в код репликатора, и смотрим, а не проглотит ли он по try...except какую-нибудь хитровывернутую ошибку вставки/коммита.
Только из лога. При любом исключении программа не доходит до выведения в лог сообщения об успешной прокачки и вываливается на обработчик. Вот фрагмент кода
try{
if ( DM->TAC->Active == false)
DM->TAC->StartTransaction();
if ( DM->TOC->Active == false )
DM->TOC->StartTransaction();
// выполним запрос в АС
applyTrLogRecordToAC( sTrLog );
// удалить запись из очереди репликации
deleteRecordFormTrLog( sTrLog );
// подтвердить транзакции в АС
DM->TAC->Commit();
trRecordApplyedToAC = true;
// ... и ОС
DM->TOC->Commit();
// вывод в лог сообщения
saveMessageToLog( sTrLog, lmtRegular, "");
}
catch ( Exception & ex )
{
..... // обработка ошибок
}
-
- Сообщения: 35
- Зарегистрирован: 16 авг 2007, 15:13
Да. При условии, что не было исправляющей вставки. На старых версия репликатора за такой пропавшей записью следовали кучи ошибок, если были попытки update любых ссылающихся на неё записей.WildSery писал(а):Т.е. сейчас запись в T_RGOODS ссылается вникуда?Kabaev Sergey писал(а):Там стоит огранчение целостности
Тогда у тебя точно битый индекс.
-
- Сообщения: 35
- Зарегистрирован: 16 авг 2007, 15:13
Господи, да при чём тут макс. Проверить надо конкретную запись запросом, не использующим индекс.Kabaev Sergey писал(а):GFIX-ом БД Аналитики проверяли, ошибок не было.
Если индексы кривые, то вроде бы должна помочь проверка на поиск максимального значения (или я неправ?)
Сейчас выполнил
SELECT max(BEID) FROM T_RGOODS
и
SELECT max(BEID) FROM T_BENTITY
ошибок не было.
Радикальное средство - b/r. Но он в такой ситуации может не пройти.
-
- Сообщения: 35
- Зарегистрирован: 16 авг 2007, 15:13
Последнее жутко заинтересовалоMerlin писал(а):
Радикальное средство - b/r. Но он в такой ситуации может не пройти.
1 при битом индексе, если я правильно понял, можем поиметь дубли, несмотря на FK
2 путем танцев с бубном вокруг БД мы эти дубли находим
3 корежим вручную некое поле, дабы однозначно убить одну запись из дублей
4 убиваем ее
5 делаем b/r (в другую базу естессно)
6 вопрос - почему в данном случае рестор не отработает? ведь дубль по FK мы уже убили?
Этта... слово на... пишется раздельно, а зае...сь - с мягким знаком (С). Вредные дубли - они по PK, а не по FK. Это раз. О том и речь, что это сначала надо сделать, иначе можно напороться. Два - это таки FK. То есть, при повреждённых индексах в подчинённых таблицах могут оказаться записи-сИроты, а не дубликаты. Их тоже надобно будет выявить и, анализируя нарушения, принимать по ним решения - грохать, переводить на другого родителя или вставлять этого исчезнувшего после других нарушений, не связанных с индексами, родителя. Последнее бывает после лечения некоторых серьёзных повреждений через gfix -verify и gfix -mend. Единственная в моей практике база, на которую я таки плюнул и восстановил суточный бакап содержала около сотни тысяч таких сирот, руками в обозримое время было не разгрести.stix-s писал(а):Последнее жутко заинтересовалоMerlin писал(а):
Радикальное средство - b/r. Но он в такой ситуации может не пройти.
1 при битом индексе, если я правильно понял, можем поиметь дубли, несмотря на FK
2 путем танцев с бубном вокруг БД мы эти дубли находим
3 корежим вручную некое поле, дабы однозначно убить одну запись из дублей
4 убиваем ее
5 делаем b/r (в другую базу естессно)
6 вопрос - почему в данном случае рестор не отработает? ведь дубль по FK мы уже убили?
-
- Заслуженный разработчик
- Сообщения: 1436
- Зарегистрирован: 15 сен 2005, 09:05
-
- Сообщения: 35
- Зарегистрирован: 16 авг 2007, 15:13
-
- Сообщения: 35
- Зарегистрирован: 16 авг 2007, 15:13
выполнил, выборка пустаяПрощения прошу, сглючил второпях. Надо
SELECT BEID FROM T_BENTITY WHERE BEID+0=2072261010057931
SELECT BEID FROM T_BENTITY WHERE BEID=2072261010057931
PLAN (T_BENTITY NATURAL)
Также пустая выборка
SELECT BEID FROM T_BENTITY WHERE BEID=2072261010057931+0
т.е. тот же запрос что выполнял вчера. Вчера была выбрана одна запись. Сегодня выборка пустая. Похоже финиш.
вообще-то Merlin вещал
SELECT BEID FROM T_BENTITY WHERE BEID+0=2072261010057931
бэкап/рестор, я так понимаю не пробовал?
я понимаю, что при размере БД 8 Г такое предложение выглядит страшновато, но:
если база аналитики долгое время была бесхозна, то возможно из-за мусора ее реальный размер гораздо меньше (нездоровый оптимизм), но на нормальном железе - это часа 2 не более, может стоит попробовать?
у мена игровая база 2Г (в смысле для экспериментов создал скриптом)
на машинке типа Целерон 2000 с Мб 512 - 30 мин бакап+40мин рестор, если канешно ничего другого не делать
SELECT BEID FROM T_BENTITY WHERE BEID+0=2072261010057931
бэкап/рестор, я так понимаю не пробовал?
я понимаю, что при размере БД 8 Г такое предложение выглядит страшновато, но:
если база аналитики долгое время была бесхозна, то возможно из-за мусора ее реальный размер гораздо меньше (нездоровый оптимизм), но на нормальном железе - это часа 2 не более, может стоит попробовать?
у мена игровая база 2Г (в смысле для экспериментов создал скриптом)
на машинке типа Целерон 2000 с Мб 512 - 30 мин бакап+40мин рестор, если канешно ничего другого не делать