SQL Server:找不到句柄 x 的预准备语句
最近,我们的 QA 团队报告了我们的一个应用程序中的一个非常有趣的错误。我们的应用程序是一个基于 C# .Net 3.5 SP1 的应用程序,与 SQL Server 2005 Express Edition 数据库交互。
根据设计,该应用程序被开发为检测数据库脱机情况,如果是这样,则等待数据库联机(通过及时重试连接),一旦联机,重新连接并恢复功能。
我们的 QA 团队所做的是,当应用程序从数据库检索大量数据时,停止数据库服务器,等待一段时间并重新启动数据库。数据库重新启动后,应用程序重新连接到数据库,没有任何问题,但它开始连续报告异常“无法找到带有句柄 x 的准备好的语句”(x 是某个数字)。
我们的应用程序正在使用准备好的语句,并且它已经设计为当应用程序重新连接到数据库时再次对所有 SqlCommand 对象调用Prepare() 方法。例如,
在应用程序启动时,
SqlCommand _commandA = connection.CreateCommand();
_commandA.CommandText = @"SELECT COMPANYNAME FROM TBCOMPANY WHERE ID = @ID";
_commandA.CommandType = CommandType.Text;
SqlParameter _paramA = _commandA.CreateParameter();
_paramA.ParameterName = "@ID";
_paramA.SqlDbType = SqlDbType.Int;
_paramA.Direction = ParameterDirection.Input;
_paramA.Size = 0;
_commandA.Parameters.Add(_paramA);
_commandA.Prepare();
之后我们在此 _commandA 上使用 ExceuteReader(),并在应用程序的每个周期中使用不同的 @ID 参数值。
一旦应用程序检测到数据库脱机并重新联机,重新连接到数据库后,应用程序只会执行,
_commandA.Prepare();
我们注意到另外两个奇怪的事情。 1. 上述情况发生在代码中CommandType.Text类型的命令上。我们的应用程序也使用相同的逻辑来调用存储过程,但我们从未在存储过程中遇到此问题。 2. 到目前为止,无论我们在 Visual Studio 的调试模式下尝试了多少种不同的方法,都无法重现该问题。
提前致谢..
Recently our QA team reported a very interesting bug in one of our applications. Our application is a C# .Net 3.5 SP1 based application interacting with a SQL Server 2005 Express Edition database.
By design the application is developed to detect database offline scenarios and if so to wait until the database is online (by retrying to connect in a timely manner) and once online, reconnect and resume functionality.
What our QA team did was, while the application is retrieving a bulk of data from the database, stop the database server, wait for a while and restart the database. Once the database restarts the application reconnects to the database without any issues but it started to continuously report the exception "Could not find prepared statement with handle x" (x is some number).
Our application is using prepared statements and it is already designed to call the Prepare() method again on all the SqlCommand objects when the application reconnects to the database. For example,
At application startup,
SqlCommand _commandA = connection.CreateCommand();
_commandA.CommandText = @"SELECT COMPANYNAME FROM TBCOMPANY WHERE ID = @ID";
_commandA.CommandType = CommandType.Text;
SqlParameter _paramA = _commandA.CreateParameter();
_paramA.ParameterName = "@ID";
_paramA.SqlDbType = SqlDbType.Int;
_paramA.Direction = ParameterDirection.Input;
_paramA.Size = 0;
_commandA.Parameters.Add(_paramA);
_commandA.Prepare();
After that we use ExceuteReader() on this _commandA with different @ID parameter values in each cycle of the application.
Once the application detects the database going offline and coming back online, upon reconnect to the database the application only executes,
_commandA.Prepare();
Two more strange things we noticed.
1. The above situation on happens with CommandType.Text type commands in the code. Our application also uses the same exact logic to invoke stored procedures but we never get this issue with stored procedures.
2. Up to now we were unable to reproduce this issue no matter how many different ways we try it in the Debug mode in Visual Studio.
Thanks in advance..
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为,在将近 3 天的时间里提出这个问题、接近 20 个问题的浏览和 1 个答案,我必须得出结论,这不是我们可以用 SQL Server 尝试的方式处理的场景。
在应用程序中缓解此问题的最佳方法是在应用程序检测到数据库联机后再次重新创建 SqlCommand 对象实例。
我们对应用程序进行了更改,我们的 QA 团队对这一修改感到高兴,因为它为他们报告的问题提供了最佳(或者可能是唯一)的修复。
最后感谢所有查看并回答问题的人。
I think with almost 3 days of asking the question and close to 20 views of the question and 1 answer, I have to conclude that this is not a scenario that we can handle in the way we have tried with SQL server.
The best way to mitigate this issue in your application is to re-create the SqlCommand object instance again once the application detects that the database is online.
We did the change in our application and our QA team is happy about this modification since it provided the best (or maybe the only) fix for the issue they reported.
A final thanks to everyone who viewed and answered the question.
当您调用“command.Prepare”时,服务器会缓存查询计划。该错误表明当您再次调用“准备”时,无法找到此缓存的查询计划。尝试创建一个新的“SqlCommand”实例并对其调用查询。我以前遇到过这个异常,当服务器刷新缓存时它会自行修复。我怀疑是否可以在客户端以编程方式完成任何操作来解决此问题。
The server caches the query plan when you call 'command.Prepare'. The error indicates that it cannot find this cached query plan when you invoke 'Prepare' again. Try creating a new 'SqlCommand' instance and invoking the query on it. I've experienced this exception before and it fixes itself when the server refreshes the cache. I doubt there is anything that can be done programmatically on the client side, to fix this.
这不一定与您的问题完全相关,但我发布此消息是因为我花了几天时间尝试修复应用程序中的相同错误消息。我们有一个 Java 应用程序,使用 C3P0 连接池、JTDS 驱动程序连接到 SQL Server 数据库。
我们在 C3P0 连接池中禁用了语句缓存,但没有在驱动程序级别上执行此操作。将 maxStatements=0 添加到我们的连接 URL 可停止驱动程序缓存语句,并修复错误。
This is not necessarily related exactly to your problem but I'm posting this as I have spent a couple of days trying to fix the same error message in my application. We have a Java application using a C3P0 connection pool, JTDS driver, connecting to a SQL Server database.
We had disabled statement caching in our the C3P0 connection pool, but had not done this on the driver level. Adding maxStatements=0 to our connection URL stopped the driver caching statements, and fixed the error.