如何获得 firebird 数据库上的独占锁以执行架构更改?
更具体地说,我正在使用 firebird 2.1 和 Visual Studio 的 DDEX Provider,并且我正在使用 c# 工作。
我遇到了一种情况,我试图将模式更改从 C# 应用到数据库,以“更新”我的数据库。在此过程中,我从 firebird 得到以下异常:
FirebirdSql.Data.FirebirdClient.FbException: 元数据更新对象 INDEX 正在使用中失败
我将其解释为并发问题,其中有另一个进程同时访问数据库。我不知道这是某种原因,但它“似乎”是最有可能的情况。我认为这可能与删除和添加约束有关,因为它们不可添加,因为约束不正确,但我能够在本地系统上运行命令而不会出现错误,只是不能在客户端站点上运行。无论如何,我目前使用隔离级别“可序列化”将许多命令包装到一个事务中,并一次提交所有命令。由于这是升级,因此可以根据需要阻止所有其他用户。
示例:
// 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:违反表“TYPE”上的 FOREIGN KEY 约束“INTEG_72”
这很清楚,所以我将修复此问题并在现场尝试一下。
这似乎已经解决了。
因此,总而言之,我在客户端系统上遇到异常:
FirebirdSql.Data.FirebirdClient.FbException:元数据更新对象 INDEX 正在使用中失败
我将数据带到本地系统并得到了不同的异常:
FirebirdSql.Data.FirebirdClient .FbException:违反表“TYPE”上的外键约束“INTEG_72”
这确实是外键约束违规。我能够更正更新程序以包括对数据的更正,并且客户端站点已正确更新。由于某种原因,我似乎在客户端站点上收到了不正确的初始异常。
注意:我还接受了 jachguate 在这个帖子中的回答,因为他提供了我认为是我原来问题的正确答案。
To be more specific, I am using firebird 2.1 and the DDEX Provider for visual studio, and I'm working in c#.
I have a situation where I'm trying to apply schema changes to the database from c# in an effort to "update" my database. During this process I get the following exception from firebird :
FirebirdSql.Data.FirebirdClient.FbException: unsuccessful metadata update object INDEX is in use
I've interpreted this as a concurency issue where there is another processess accessing the database at the same time. I do not know this is the cause for certian, but it "seems" the most likely case. I thought it might be related to the deleting and adding of constraints, as in they are not addable because the constraint is not correct, but I am able to run the commands on my local system without error, just not on the client site. At any rate, I currently have a number of commands wrapped into one transaction using isolation level "Serializable", and commit them all at once. As this is an upgrade, the thinking is it can block all other users as needed.
Example:
// 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();
My thought was to try and use the "manual" way of specifying a transaction to perhaps get more exclusive access to the tables, but I can't seem to get it to work as I don't understand what will and will not work together.
Example:
// 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
);
Anyway, my question is, how do I get exclusive access to the db to perform these updates? I'd almost like to be able to kick everyone off, and do them. Help and suggestions are much appricated!!!
New information:
I was able to bring the data to my local, and now the error is showing as:
FirebirdSql.Data.FirebirdClient.FbException: violation of FOREIGN KEY constraint "INTEG_72" on table "TYPE"
Which is clear, so I'll fix this one and try it on site.
That seems to have fixed it.
So, in summary, I got an exception on a client system say:
FirebirdSql.Data.FirebirdClient.FbException: unsuccessful metadata update object INDEX is in use
I brought the data to my local system and got a different exception:
FirebirdSql.Data.FirebirdClient.FbException: violation of FOREIGN KEY constraint "INTEG_72" on table "TYPE"
Which was indeed a foreign key constraint violation. I was able to correct the update program to include a correction to the data and the client site updated properly. For some reason, I seemed to recieve an incorrect inital exception on the client site.
Note: I also accepted an answer in this thread by jachguate as he provided what I believe is the correct answer to my original question.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以通过使用 gfix 命令行工具关闭数据库来获得数据库的独占访问权限以进行维护(您可以从 C# 程序中调用它,或使用其他工具执行所有维护,例如在服务器上执行的批处理脚本)。
来自数据库启动和关闭
从 firebird 2.0 开始,您还可以指定数据库关闭后的
状态
:例如,
将在 60 秒后断开所有活动用户的连接,之后数据库将只允许 sysdba 或数据库所有者建立一个连接。
You can get exclusive access on the database for maintenance by shutting it down using the gfix command line tool (you can call it from your c# program, or perform all the maintenance using another tool, for example a batch script executed on the server).
From Database Startup and Shutdown
Since firebird 2.0, you can also specify the
state
of the database after shutdown:For example
will disconnect all active users after 60 seconds, afterwards the database will allow only one connection for sysdba or database owner.