SQL 在将 Base64 转换为二进制的视图上执行 reader 超时
SQL timeouts executing reader on view that converts Base64 to binary
我们将文件以 Base64 编码存储在 SQL 服务器 table 中。我们需要将文件作为二进制数据进行流式传输,因此我们查询一个将 Base64 列转换为 varbinary
:
的视图
CREATE VIEW [dbo].[FilesView]
AS
SELECT
f.Id,
CAST(N'' AS XML).value('xs:base64Binary(sql:column("f.FileContents"))', 'varbinary(max)') AS FileContents,
FROM [Files] f
FileContents
在文件 table 中,定义为 varchar(max)
.
我们使用 ADO.NET 查询此列并使用 SqlDataReader
流式传输内容:
private async Task<Stream> FileStream(Guid id)
{
string commandText = "SELECT FileContents FROM FilesView WHERE Id = @id";
using (SqlCommand cmd = new SqlCommand(commandText, (SqlConnection)context.Database.GetDbConnection()))
{
cmd.Parameters.Add(new SqlParameter("@id", id));
if (cmd.Connection.State != ConnectionState.Open)
{
await cmd.Connection.OpenAsync();
}
SqlDataReader reader = await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess);
if (await reader.ReadAsync())
{
return reader.GetStream(0);
}
}
return null;
}
这对我们来说效果很好,文件下载会立即开始,但是在发货后,我们有少数客户在 cmd.ExecuteReaderAsync
行遇到异常:
Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
根据他们的说法,这些文件也不是很大,不到 1 MB。在我们的测试中,我们使用了更大的文件并且没有超时问题。我们让他们将命令超时时间增加到 60 秒或更多,并且大部分时间都得到了纠正,但花了很长时间,问题仍然存在。由于打开 reader 时出现异常,我的假设是 Base64 到二进制转换是导致超时的原因。
为什么只有一些实例? SQL 服务器中是否有特定的 feature/option 我们应该检查或更改可能导致此问题的原因?我不知道他们的数据库服务器的硬件规格,但我想这可能只是转换动力不足的情况?
事实证明,此特定客户端使用的是 SQL Server 2017,但其兼容性级别设置为 SQL Server 2012 (110)。将其移至 130,查询现在 运行 毫秒。
我们将文件以 Base64 编码存储在 SQL 服务器 table 中。我们需要将文件作为二进制数据进行流式传输,因此我们查询一个将 Base64 列转换为 varbinary
:
CREATE VIEW [dbo].[FilesView]
AS
SELECT
f.Id,
CAST(N'' AS XML).value('xs:base64Binary(sql:column("f.FileContents"))', 'varbinary(max)') AS FileContents,
FROM [Files] f
FileContents
在文件 table 中,定义为 varchar(max)
.
我们使用 ADO.NET 查询此列并使用 SqlDataReader
流式传输内容:
private async Task<Stream> FileStream(Guid id)
{
string commandText = "SELECT FileContents FROM FilesView WHERE Id = @id";
using (SqlCommand cmd = new SqlCommand(commandText, (SqlConnection)context.Database.GetDbConnection()))
{
cmd.Parameters.Add(new SqlParameter("@id", id));
if (cmd.Connection.State != ConnectionState.Open)
{
await cmd.Connection.OpenAsync();
}
SqlDataReader reader = await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess);
if (await reader.ReadAsync())
{
return reader.GetStream(0);
}
}
return null;
}
这对我们来说效果很好,文件下载会立即开始,但是在发货后,我们有少数客户在 cmd.ExecuteReaderAsync
行遇到异常:
Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
根据他们的说法,这些文件也不是很大,不到 1 MB。在我们的测试中,我们使用了更大的文件并且没有超时问题。我们让他们将命令超时时间增加到 60 秒或更多,并且大部分时间都得到了纠正,但花了很长时间,问题仍然存在。由于打开 reader 时出现异常,我的假设是 Base64 到二进制转换是导致超时的原因。
为什么只有一些实例? SQL 服务器中是否有特定的 feature/option 我们应该检查或更改可能导致此问题的原因?我不知道他们的数据库服务器的硬件规格,但我想这可能只是转换动力不足的情况?
事实证明,此特定客户端使用的是 SQL Server 2017,但其兼容性级别设置为 SQL Server 2012 (110)。将其移至 130,查询现在 运行 毫秒。