禁用超时时 SqlBulkCopy 到 Azure 超时
SqlBulkCopy to Azure Timing out when Timeouts are disabled
我正在尝试使用 .NET Core 中的 SqlBulkCopy 将几百万行批量插入开发实例 Azure SQL 数据库。
我已禁用连接字符串超时和 BulkCopyTimeout(将它们都设置为 0),但我仍然超时。
现在这不是一台高级机器(它是一个开发环境),而且这个过程很容易使 DTU 达到最大值……但我对 DTU 最大值应该如何工作的理解是它是节流机制,而不是中止机制。无限超时,我希望这个过程需要一段时间,但最终会完成。相反,我看到的是过程开始......上传一堆行......然后在奇怪的时间超时:2:38,4:20......没有韵律或原因。
这让我认为这是某种传输错误,但我显然遇到了 TimeoutException。
根据 Bulk insert is not working properly in Azure SQL Server 中的建议,我也尝试将批次设置得非常小,但这似乎也无济于事。
谁能解释这里发生了什么,以及如何解决它?这阻碍了高可见度项目的开发,我不想告诉人们我可以让它在笔记本电脑的 SQL Server Express 上运行,但不能在 Azure DB 上运行。
请 运行 以下查询,让我们尝试找到有关 Azure SQL 数据库受到限制的证据。
SELECT *
FROM sys.dm_db_resource_stats
ORDER BY end_time DESC;
如果您看到 avg_log_write_percent 接近或等于 100%,则表示正在发生限制,您需要扩展数据库层。非高级层不适合 I/O 密集型工作负载,建议使用批处理。
当 Azure SQL 数据库发生节流时,您不仅会看到响应时间变慢,而且还会开始看到不成功的连接尝试和超时。
select *
from sys.event_log
where event_type <> 'connection_successful' and
start_time >= CAST(FLOOR(CAST(getdate() AS float)) AS DATETIME)
order by start_time desc
select *
from sys.database_connection_stats_ex
where start_time >= CAST(FLOOR(CAST(getdate() AS float)) AS DATETIME)
order by start_time desc
我只是想重现,但做不到。 SqlBulkCopy 运行 超过 30 分钟才取消它。
从 Azure 外部针对低 DTU Azure SQL 数据库尝试此操作:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
var constr = "Server=tcp:xxxxxx.database.windows.net,1433;Initial Catalog=xxxxxx;User ID=xxxxxx;Password=xxxxxx";
using (var con = new SqlConnection(constr))
{
con.Open();
var cmd = con.CreateCommand();
cmd.CommandText = "create table #test(id int, data varbinary(max))";
cmd.ExecuteNonQuery();
var bc = new SqlBulkCopy(con);
bc.DestinationTableName = "#test";
bc.BulkCopyTimeout = 0;
var dt = new DataTable();
dt.Columns.Add("id", typeof(int));
dt.Columns.Add("data", typeof(byte[]));
var buf = Enumerable.Range(1, 1000 * 1000).Select(i => (byte)(i % 256)).ToArray();
dt.BeginLoadData();
for (int i = 0; i < 1000*1000*10; i++)
{
var r = dt.NewRow();
r[0] = 1;
r[1] = buf;
dt.Rows.Add(r);
}
dt.EndLoadData();
foreach (DataColumn col in dt.Columns)
{
bc.ColumnMappings.Add(col.ColumnName, col.ColumnName);
}
bc.NotifyAfter = 100;
bc.SqlRowsCopied += (s, a) =>
{
Console.WriteLine($"{a.RowsCopied} rows copied");
};
Console.WriteLine($"Starting {DateTime.Now}");
bc.WriteToServer(dt);
Console.WriteLine($"Finished {DateTime.Now}");
}
Console.WriteLine("done");
}
}
两个答案都很好,但我的问题似乎与代码无关。有一些 "glitch in the matrix" 似乎导致了我所看到的症状,在某一点之后我无法再重现它们。
我正在尝试使用 .NET Core 中的 SqlBulkCopy 将几百万行批量插入开发实例 Azure SQL 数据库。
我已禁用连接字符串超时和 BulkCopyTimeout(将它们都设置为 0),但我仍然超时。
现在这不是一台高级机器(它是一个开发环境),而且这个过程很容易使 DTU 达到最大值……但我对 DTU 最大值应该如何工作的理解是它是节流机制,而不是中止机制。无限超时,我希望这个过程需要一段时间,但最终会完成。相反,我看到的是过程开始......上传一堆行......然后在奇怪的时间超时:2:38,4:20......没有韵律或原因。
这让我认为这是某种传输错误,但我显然遇到了 TimeoutException。
根据 Bulk insert is not working properly in Azure SQL Server 中的建议,我也尝试将批次设置得非常小,但这似乎也无济于事。
谁能解释这里发生了什么,以及如何解决它?这阻碍了高可见度项目的开发,我不想告诉人们我可以让它在笔记本电脑的 SQL Server Express 上运行,但不能在 Azure DB 上运行。
请 运行 以下查询,让我们尝试找到有关 Azure SQL 数据库受到限制的证据。
SELECT *
FROM sys.dm_db_resource_stats
ORDER BY end_time DESC;
如果您看到 avg_log_write_percent 接近或等于 100%,则表示正在发生限制,您需要扩展数据库层。非高级层不适合 I/O 密集型工作负载,建议使用批处理。
当 Azure SQL 数据库发生节流时,您不仅会看到响应时间变慢,而且还会开始看到不成功的连接尝试和超时。
select *
from sys.event_log
where event_type <> 'connection_successful' and
start_time >= CAST(FLOOR(CAST(getdate() AS float)) AS DATETIME)
order by start_time desc
select *
from sys.database_connection_stats_ex
where start_time >= CAST(FLOOR(CAST(getdate() AS float)) AS DATETIME)
order by start_time desc
我只是想重现,但做不到。 SqlBulkCopy 运行 超过 30 分钟才取消它。
从 Azure 外部针对低 DTU Azure SQL 数据库尝试此操作:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
var constr = "Server=tcp:xxxxxx.database.windows.net,1433;Initial Catalog=xxxxxx;User ID=xxxxxx;Password=xxxxxx";
using (var con = new SqlConnection(constr))
{
con.Open();
var cmd = con.CreateCommand();
cmd.CommandText = "create table #test(id int, data varbinary(max))";
cmd.ExecuteNonQuery();
var bc = new SqlBulkCopy(con);
bc.DestinationTableName = "#test";
bc.BulkCopyTimeout = 0;
var dt = new DataTable();
dt.Columns.Add("id", typeof(int));
dt.Columns.Add("data", typeof(byte[]));
var buf = Enumerable.Range(1, 1000 * 1000).Select(i => (byte)(i % 256)).ToArray();
dt.BeginLoadData();
for (int i = 0; i < 1000*1000*10; i++)
{
var r = dt.NewRow();
r[0] = 1;
r[1] = buf;
dt.Rows.Add(r);
}
dt.EndLoadData();
foreach (DataColumn col in dt.Columns)
{
bc.ColumnMappings.Add(col.ColumnName, col.ColumnName);
}
bc.NotifyAfter = 100;
bc.SqlRowsCopied += (s, a) =>
{
Console.WriteLine($"{a.RowsCopied} rows copied");
};
Console.WriteLine($"Starting {DateTime.Now}");
bc.WriteToServer(dt);
Console.WriteLine($"Finished {DateTime.Now}");
}
Console.WriteLine("done");
}
}
两个答案都很好,但我的问题似乎与代码无关。有一些 "glitch in the matrix" 似乎导致了我所看到的症状,在某一点之后我无法再重现它们。