Конференция "Базы" » Access+Delphi+Ado - про транзакции [D7, Access]
 
  • Николай2010 (27.05.10 14:39) [0]
    Здравствуйте!
    Существует программа на D7, работает с БД Access, для связи используется ADO. В БД порядка 100 таблиц и нескольких десятков тысяч записей. БД используется локально.
    Программа находится в интенсивной эксплуатации и, как всегда, возникают пожелания пользователей - это вернуть, как было, а это - сделать по-новому. В общем, без модификации структуры БД и наполнения системных справочников (информацию в которых не может поменять простой пользователь) не обходиться. До этого все было просто - событие AdoConnection.AfterConnect, по нему прогоняется автомодификция БД до последней версии (присутствует удаление и добавление столбцов, вставка данных с предварительной проверкой - все через отдельную ADOQuery). Потом старт транзакции - пользователь может работать с новой версией.

    Сейчас (когда кол-во таких модификаций неуклонно растет, остановиться нельзя), хочу сделать перестраховку, которую не предусмотрели с  самого начала (рассчитывали на строго конечное кол-во модификаций). А именно, т.к. баз наплодили дикое кол-во, могу допустить, что в 1 случае из 200-300 система предварительного апгрейда до новой версии БД может дать сбой.

    В связи с этим решение - как только срабатывает событие AdoConnection.AfterConnect делать апгрейд БД, но весь код апгрейда начинать и завершать (соответственно) началом и фиксацией (или откатом с выдачей сообщения) транзакции. Только потом в случае успеха пользователь может работать с программой, в случае сбоя – должен сообщить об ошибке. Естественно, весь апгрейд БД ставится в try…except… со всеми необходимыми действиями.
    “Обрамление” немаленькой (уже примерно 5500 строк) процедуры модификации структуры БД тремя строчками
    Adoconnection1.BeginTrans; Adoconnection1.CommitTrans; Adoconnection1.RollbackTrans;
    привело, собственно, к моему вопросу.

    Отмечу сразу, что БД и прототип приложения на Delphi, содержащий всего лишь требуемый ADOConnection и событие после подключения (чтобы отвязаться от всего остального) были вынесены мной в отдельный проект. Не помогло.  Проблема состоит в следующем – на определенных действиях (повторяется раз от раза), а именно команде добавления столбца в таблицу (ALTER через ADOQuery) получаю сообщение “Таблица такая-то не может быть заблокирована ядром БД, т.к. используется другим пользователем или процессом”. При этом проект, кроме апгрейда, полностью “голый”, без обрамления апгрейда транзакцией – все работает. Единственно, на что можно подумать, “выше” ALTER по коду стоят  SELCT и два INSERT’а в эту таблицу. Там, где были объекты ADOQuery, создаваемые в runtime, все уничтожается вовремя (а потом и от них избавился почти), чтобы не было подозрений, что кто-то неуничтоженный продолжает блокировать таблицу. В каком направлении можно двигаться (кроме минимизации кода и всего того, что уже попробовал)?

    В процедуре апгрейда присутствуют следующие приемы модификации:
    alter table test add column test tinyint;
    Select * from <table_name> where…. (для проверок)
    alter table drop column test;
    insert и update…. (вставка и модификация данных)
    create (drop) table…

    Еще есть изменение проверочных условий на столбцы Access с помощью ADOX.Catalog, но нечасто и с описанной выше ошибкой не пересекаются.

    Что можно попробовать?
    С уважением, Николай
  • turbouser © (27.05.10 15:51) [1]
    нет ничего надежнее, чем делать резервную копию базы перед применением глобальных модификаций. С проверкой "правильности" резервной копии. И с восстановлением бд из резервной в случае сбоя.
  • Smile (27.05.10 16:14) [2]
    Проблема состоит в следующем – на определенных действиях (повторяется раз от раза), а именно команде добавления столбца в таблицу

    Если не слишком секретно, то хотя бы примерно о задаче, в которой любой пользователь "по своему усмотрению" может добавлять какие-то (про количество не спрашиваю) поля в таблицы?
  • turbouser © (27.05.10 16:18) [3]

    > Smile   (27.05.10 16:14) [2]

    Это же апгрейд. При чем тут "любой пользователь"
  • Sergey13 © (27.05.10 16:28) [4]
    > [0] Николай2010   (27.05.10 14:39)

    Т.е. у вас много пользователей юзают каждый свою копию программы и БД?
  • Николай2010 (27.05.10 17:48) [5]
    2 Sergey13

    По постановке много пользователей юзают последнюю версию программы (не любую) и свои БД. Причем БД может быть хоть месячной, хоть двухгодичной давности - программа при первом подлючении проапдейтит ее до последней версии. В плане данных апдейтятся внутренние и служебные таблицы, правка данных в которых обычным пользователям запрещена.
  • Sergey13 © (27.05.10 17:57) [6]
    > [5] Николай2010   (27.05.10 17:48)

    Странная постановка задачи. Сети что ли нет? Тогда откуда берутся последние версии программы? Есть сеть - тогда почему бы не юзать одну БД всем вместе?
    Инначе ИМХО можно до абсурда дойти, когда программа будет по пол дня проверять и осуществлять обновление БД.
  • Николай2010 (27.05.10 21:03) [7]
    2 Sergey13
    организация очень распределенная по городам, сети нет, глючные локалки в паре офисов не в счет. Пользователи с комплектом программ локально работают. Наша часть работает норм.
    в общем, причина в alter, http://msdn.microsoft.com/en-us/library/aa141499(office.10).aspx
  • sniknik © (27.05.10 22:56) [8]
    > в общем, причина в alter, http://msdn.microsoft.com/en-us/library/aa141499(office.10).aspx
    а ссылка про не поддерживаемость транзакциями внешних (прилинкованных) источников. т.е. если например меняется подключенная dbf таблица.

    alter не виноват...
  • turbouser © (27.05.10 23:22) [9]
    см. [1]
    а как, собственно, происходит процесс апгрейда? просто, предполагается, что обновляемые бд какой-то предпоследней версии и на них накатывается скрипт с дополнениями от последней версии? если так, то это не верный подход.
  • Anatoly Podgoretsky © (28.05.10 07:23) [10]
    Надо освоить репликации и поддержание целостности при обновлениях структуры.
 
Конференция "Базы" » Access+Delphi+Ado - про транзакции [D7, Access]
Есть новые Нет новых   [134433   +22][b:0][p:0]