Как получить эксклюзивную блокировку базы данных Firebird для изменения схемы? - PullRequest
3 голосов
/ 16 февраля 2011

Если говорить точнее, я использую Firebird 2.1 и провайдера DDEX для visual studio, и я работаю в c #.

У меня возникла ситуация, когда я пытаюсь применить изменения схемы к базе данных из c #, пытаясь "обновить" мою базу данных.Во время этого процесса я получаю следующее исключение из firebird:

FirebirdSql.Data.FirebirdClient.FbException: неудачный объект обновления метаданных INDEX используется

Я интерпретировал это как проблему параллелизма, где естьэто другой процесс, обращающийся к базе данных одновременно.Я не знаю, что является причиной для Certian, но это «кажется» наиболее вероятным случаем.Я подумал, что это может быть связано с удалением и добавлением ограничений, так как они не могут быть добавлены, потому что ограничение не корректно, но я могу запускать команды в своей локальной системе без ошибок, но не на клиентском сайте.Во всяком случае, в настоящее время у меня есть несколько команд, заключенных в одну транзакцию с использованием уровня изоляции «Serializable», и я фиксирую их все сразу.Поскольку это обновление, предполагается, что оно может блокировать всех других пользователей по мере необходимости.

Пример:

// note connection is pre-defined as a FbConnection, connected to the Database in question

FbTransaction transaction = Connection.BeginTransaction( IsolationLevel.Serializable );

// quite a bit of stuff gets done here, this is a sample
// I can run all the commands in this section in the isql tool and commit them all at once
// without error.  NOTE: I have not tried to run them all on the client enviroment, and likely can't

string commandString = "ALTER TABLE Product DROP CONSTRAINT ProductType;";
FbCommand command = new FbCommand(commandString, Connection, transaction);
command.ExecuteNonQuery();

commandString = "ALTER TABLE Product ADD CONSTRAINT ProductType " +
                "FOREIGN KEY ( TypeID ) REFERENCES Type ( TypeID ) " +
                "ON UPDATE CASCADE ON DELETE NO ACTION;";
command.CommandText = commandString;
command.ExecuteNonQuery();

// other commands include: 
// creating a new table
// creating 3 triggers for the new table

// commit the transaction
// this particular line actually "seems" to throw the exception mentioned

transaction.Commit();

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

Пример:

// Try to use FbTransactionOptions instead
// this statement complains about invalid options block when executing
FbTransaction transaction = Connection.BeginTransaction(
            FbTransactionOptions.Consistency |
            FbTransactionOptions.Exclusive |
            FbTransactionOptions.Wait |
            FbTransactionOptions.Write |
            FbTransactionOptions.LockWrite |
            FbTransactionOptions.NoRecVersion
            );

В любом случае, мой вопрос, как мне получить эксклюзивный доступ к БД для выполнения этих обновлений?Я почти хотел бы быть в состоянии пнуть всех и сделать их.Помощь и предложения очень важны !!!


Новая информация: мне удалось перенести данные на локальный компьютер, и теперь ошибка отображается как:

FirebirdSql.Data.FirebirdClient.FbException: нарушение ограничения FOREIGN KEY "INTEG_72" для таблицы "TYPE"

Что понятно, поэтому я исправлю это и попробую на месте.


Это, кажется, исправило это.
Итак, в итоге, я получил исключение в клиентской системе:

FirebirdSql.Data.FirebirdClient.FbException: неудачные метаданныеиспользуется объект обновления INDEX

Я перенес данные в локальную систему и получил другое исключение:

FirebirdSql.Data.FirebirdClient.FbException: нарушение ограничения FOREIGN KEY "INTEG_72" для таблицы"TYPE"

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


Примечание: я также принял ответ в этой теме от jachguate, поскольку он предоставил то, что я считаю правильным ответом на мойОригинальный вопрос.

Ответы [ 2 ]

2 голосов
/ 16 февраля 2011

Вы можете получить эксклюзивный доступ к базе данных для обслуживания, выключив ее с помощью инструмента командной строки gfix (вы можете вызвать его из вашей программы на c # или выполнить все обслуживание с помощью другого инструмента, например, пакетного сценария, выполняемого насервер).

С Запуск и завершение работы базы данных

Выключение базы данных Если для базы данных требуются ремонтные работы, вы можете закрыть ееэта база данных при определенных обстоятельствах.Это отличается от остановки сервера Firebird, так как на сервере могут работать другие базы данных, на которые вы не хотите влиять.Команда для закрытия базы данных:
gfix -shut OPTION TIMEOUT database_name
Параметр TIMEOUT - это время в секундах, в течение которого должно завершиться завершение работы. Если команда не может завершиться в указанное время, завершение работы прерывается.Существуют различные причины, по которым выключение может не завершиться в течение заданного времени, и они зависят от режима выключения и описаны ниже.Параметр OPTION является одним из следующих: * -at [tach] - предотвращает новые подключения.* -tr [an] - предотвращает новые транзакции.* -f [orce] - просто прерывает все соединения и транзакции.Когда база данных закрыта, SYSDBA или владелец базы данных могут все еще подключаться для выполнения операций обслуживания или даже запрашивать и обновлять таблицы базы данных.

Начиная с firebird 2.0, вы также можете указать state базы данных после завершения работы:

Например,

gfix -shut single -force 60 mydatabase.fdb

отключит всех активных пользователей через 60 секунд,после этого база данных разрешит только одно соединение для sysdba или владельца базы данных.

0 голосов
/ 16 февраля 2011
  1. Отключите сетевой кабель
  2. Выполнить транзакцию
  3. Подключите сетевой кабель
...