postgresql “错误:57014:由于用户请求而取消语句”Npgsql
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32632926/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"ERROR: 57014: canceling statement due to user request" Npgsql
提问by gyosifov
I am having this phantomproblem in my application where one in every 5 request on a specific page (on an ASP.NET MVC application) throws this error:
我在我的应用程序中遇到了这个幻象问题,其中特定页面(在 ASP.NET MVC 应用程序上)上的每 5 个请求中就有一个抛出此错误:
Npgsql.NpgsqlException: ERROR: 57014: canceling statement due to user request
at Npgsql.NpgsqlState.<ProcessBackendResponses>d__0.MoveNext()
at Npgsql.ForwardsOnlyDataReader.GetNextResponseObject(Boolean cleanup)
at Npgsql.ForwardsOnlyDataReader.GetNextRow(Boolean clearPending)
at Npgsql.ForwardsOnlyDataReader.Read()
at Npgsql.NpgsqlCommand.GetReader(CommandBehavior cb)
...
On the npgsql github page I found the following bug report: 615
在 npgsql github 页面上,我发现了以下错误报告:615
It says there:
它在那里说:
Regardless of what exactly is happening with Dapper, there's definitely a race condition when cancelling commands. Part of this is by design, because of PostgreSQL: cancel requests are totally "asynchronous" (they're delivered via an unrelated socket, not as part of the connection to be cancelled), and you can't restrict the cancellation to take effect only on a specific command. In other words, if you want to cancel command A, by the time your cancellation is delivered command B may already be in progress and it will be cancelled instead.
不管 Dapper 到底发生了什么,在取消命令时肯定存在竞争条件。部分原因是设计使然,因为 PostgreSQL:取消请求是完全“异步的”(它们通过不相关的套接字传递,而不是作为要取消的连接的一部分),并且您不能限制取消生效仅在特定命令上。换句话说,如果您想取消命令 A,则在您发送取消时,命令 B 可能已经在进行中,它将被取消。
Although they have made "changes to hopefully make cancellations much safer"in Npgsql 3.0.2 my current code is incompatible with this version because the need of migration described here.
尽管他们在 Npgsql 3.0.2 中进行了“希望使取消更安全的更改”,但我当前的代码与此版本不兼容,因为这里描述了迁移的需要。
My current workaround (stupid): I have commented the code in Dapper that says command.Cancel();
and the problem seems to be gone.
我目前的解决方法(愚蠢):我已经评论了 Dapper 中的代码,command.Cancel();
问题似乎消失了。
if (reader != null)
{
if (!reader.IsClosed && command != null)
{
//command.Cancel();
}
reader.Dispose();
reader = null;
}
Is there a better solution to the problem? And secondly what am I loosing with the current fix (except that I have to remember the change every time I update Dapper)?
有没有更好的解决问题的方法?其次,我在当前修复中丢失了什么(除了每次更新 Dapper 时我都必须记住更改)?
Configuration: NET45, Npgsql 2.2.5, Postgresql 9.3
配置:NET45、Npgsql 2.2.5、Postgresql 9.3
采纳答案by gyosifov
I found why my code didn't dispose the reader, resulting in calling command.Cancel()
. This only happens with QueryMultiple
method when not every refcursor
is read.
我找到了为什么我的代码没有处理读取器,导致调用command.Cancel()
. 这只发生在QueryMultiple
方法不是每个都refcursor
被读取时。
Changing the code from:
更改代码:
using (var multipleResults = connection.QueryMultiple("schema.getuserbysocialsecurity", new { socialSecurityNumber }))
{
var client = multipleResults.Read<Client>().SingleOrDefault();
if (client != null)
{
client.Address = multipleResults.Read<Address>().Single();
}
return client;
}
To:
到:
using (var multipleResults = connection.QueryMultiple("schema.getuserbysocialsecurity", new { socialSecurityNumber }))
{
var client = multipleResults.Read<Client>().SingleOrDefault();
var address = multipleResults.Read<Address>().SingleOrDefault();
if (client != null)
{
client.Address = address;
}
return client;
}
This fixed the issue and now the reader is properly disposed and command.Cancel()
is not invoked.
这解决了问题,现在读取器被正确处理并且command.Cancel()
不会被调用。
Hope this helps anyone else!
希望这对其他人有帮助!
UPDATE
更新
The npgsql docs for version 2.2states:
Npgsql is able to ask the server to cancel commands in progress. To do this, call the NpgsqlCommand's Cancel method. Note that another thread must handle the request as the main thread will be blocked waiting for command to finish. Also, the main thread will raise an exception as a result of user cancellation. (The error code is 57014.)
Npgsql 能够要求服务器取消正在进行的命令。为此,请调用 NpgsqlCommand 的 Cancel 方法。请注意,另一个线程必须处理请求,因为主线程将被阻塞等待命令完成。此外,主线程将因用户取消而引发异常。(错误代码是 57014。)
I have also posted an issueon the Dapper github page.
我还在Dapper github 页面上发布了一个问题。