-
Прога, соединившись с БД по инету (через GSM-модем), периодически обновляет её примерно так: pFIBDatabase.Execute('insert into ...').
Если Execute даёт false, он повторяется с теми же параметрами после восстановления и проверки связи.
Разрывы связи бывают часто.
Изредка в БД получаются дубли записей, т.е. в каждом таком случае Execute даёт false, несмотря на то, что запись упешно добавлена в БД.
Как можно решить эту проблему?
-
> [0] Николай 2 (09.09.08 16:19)
> Изредка в БД получаются дубли записей
Значит в БД не стоит ограничение на уникальность.
Я с ФИБ-ами не работал, но наврняка там есть работа с транзакциями. Почему надо именно так pFIBDatabase.Execute('insert into ...')? Почему нельзя просто кверик создать и делать ему execute с отловом исключения?
-
Как можно решить эту проблему?
не инсертить по мопеду, а передавать блоб со скриптом в хранимку.
в ней делать все инсерты.
либо в два присеста.
передать блоб, проверить что все ок (например сравнить crc32), затем вызвать хранимку на выполнение инсертов
-
1. Не слушать маньяков с хранимками.
2. Слушать, а точнее ЧИТАТЬ, про транзакции и управление ими.
-
Изредка в БД получаются дубли записей, т.е. в каждом таком случае Execute даёт false, несмотря на то, что запись упешно добавлена в БД.
Как можно решить эту проблему?
-
добавить уникальное поле и проверяться по нему, если значение уже есть не добавлять... т.е. чтото типа самопальной репликации, поле репликации либо гуид, либо какой нибудь естественный ключ (если есть).
-
sniknik © (09.09.08 22:24) [5]
А зачем такие сложности?
Я хоть сам старый маньяк с хранимками но тут управления транзакциями вполне хватит.
-
хватит, особенно если нужно сделать коммит/роллбак а мопед уже потух.
-
когда потухает мопед, происходит как бы роллбак
-
> А зачем такие сложности?
вовсе не сложности, постоянно с таким работаю, обычно по естественному ключу, например составному -> подразделение-магазин-отдел-касса-z отчет-чек-номер позиции
однозначно идентифицирует запись в общей базе хоть со всего города, и разных фирм... позволит обновлять даже задним числом. исправлять, если проблема с первоисточником (сломалась фискалка, z отчет неправильный, закрыли не видя части продаж... цто исправило, локальную базу восстановило. в глобальной что тоже искать, совмещать, и восстанавливать? нет. просто перепослать отчет и все. все что пришло частично станет полным.)
правда в реальных базах обычно чуток посложнее, там еще заголовки по документам с суммами, что позволяет делать проверку целостности по суммам автоматом, и другая фигня.
но это вовсе не сложно.
не сложнее чем делать после проверку все ли дошло не имея подобного "якоря" по которому можно связать записи. ну пример с обоих концов по миллиону записей, все правильно? а может одна запись не дошла и одна задублировалась? ты говоришь у меня все правильно, а бухгалтер, "это у меня суммы не бьют", и тоже уверен что у него все правильно. и?
> Я хоть сам старый маньяк с хранимками
не путай маньячество с целесообразностью... хранимка сама по себе ничего не дает. как самоцель вообще вред только от нее. а поле связи только выгоды.
-
когда потухает мопед, происходит как бы роллбак
Ага. А чувак уже внял советам ограничится управлением транзакциями и делал коммит когда связь прервалась.
-
> и делал коммит когда связь прервалась
попытка коммита без связи ни к чему не приведет
-
Всем спасибо за ответы.
Медвежонок Пятачок
Короче, просто управление транзакциями не поможет?
Каким способом лучше передать блоб?
Johnmen
Дык, вроде, TpFIBDatabase в этом случае сам управляет транзакцией: DefaultTransaction и DefaultUpdateTransaction заполнены - на форме есть компонент TpFIBTransaction с TimeoutAction=TARollback.
-
попытка коммита без связи ни к чему не приведет
Это на тему ограничься управлением транзакциями.
Мне вот интересно как он в такой среде будет это делать.
-
попытка коммита без связи ни к чему не приведет
Ситуация:
Связь есть.
Посылаем коммит.
Он (команда) долетает до сервера.
Сервер выполнил коммит и хочет вернуть результат клиенту.
А связи уже нет.
-
Медвежонок Пятачок © (10.09.08 13:52) [14]
Это шутка или полное незнакомство с работой клиентского протокола?
Если нетрудно назовите СУБД в которой такая ситуация возможна.
-
Какая именно ситуация?
-
Sergey Masloff (10.09.08 14:36) [15]
Хотя что-то подобное возможно в СУБД где commit можно на сервере делать.
Например в Oracle - но это другая песня.
-
Медвежонок Пятачок © (10.09.08 14:38) [16]
Что коммит сделается на сервере а до клиента это не дойдет? Там же с установкой соединения сессия. Пока все не отрапортуют никакого реального коммита нет. Атомарная операция
-
При чем здесь коммит на сервере/не на сервере?
Чем с точки зрения тсп и ненадежного модема отличаются инсерт от коммита?
Ничем.
Клиентская либа посылает в тсп соединение данные и ждет ответа.
И если у автора нарушается этот цикл на инсерте (запись вставлена, а exec говорит что нет), то то же самое может случиться и с коммитом.
-
Пока все не отрапортуют никакого реального коммита нет. Атомарная операция
Ой ли?
То есть я вызвал коммит, сервер мне ответил, все окей, убедился, что я принял его ответ, затем приступил к реальному закоммичиванию?
А если он при этом обломается?
-
Атомарная операция
Если бы она была атомарной, у автора не возникали бы описанные симптомы.
Она атомарна логически, в категориях реляционной теории.
А этажом ниже передаются биты и байты (не один байт) по неустойчивым каналам связи.
-
Медвежонок Пятачок © (10.09.08 14:43) [19]
Нет. Она получает ответ и посылает чек что она его получила. И если сервер этот чек не получил то реального коммита нет. Чтобы убедиться 100% надо смотреть исходники FB (я в этой части не смотрел) но ситуации когда коммит не прошел на клиенте а запись вставилась мне добиться не удалось при проведении стресс-тестов.
-
И как тогда объяснить случай со свершившейся вставкой на сервере и тем что exec на клиенте вернул false?
-
Медвежонок Пятачок © (10.09.08 14:50) [21]
>Если бы она была атомарной, у автора не возникали бы описанные >симптомы.
Симптомы пока только у автора ;-)
Если бы все было так плохо они были бы у всех и постоянно.
-
Уникальное поле - пока не нужно.
Заменил pFIBDatabase.Execute на pFIBQuery с ручным управлением транзакциями. Похоже, помогло.
Не зря в одном факе настоятельно рекомендовали управлять вручную.