SqlBulkCopy для Azure Тайм-аут, когда тайм-ауты отключены - PullRequest
0 голосов
/ 04 февраля 2019

Я пытаюсь выполнить массовую вставку пары миллионов строк в базу данных SQL экземпляра dev с помощью SqlBulkCopy в .NET Core.

Я отключил тайм-аут строки подключения и BulkCopyTimeout (установите их обана 0), но время ожидания истекло.

Теперь это не машина высокого уровня (это среда разработки), и этот процесс довольно легко максимизирует DTU ... но мое пониманиепринцип работы DTU max заключается в том, что это механизм дросселирования, а не механизм прерывания.С неограниченным временем ожидания я бы ожидал, что процесс займет некоторое время, но в конце концов закончится.Вместо этого я вижу, что процесс начинается ... загрузка ряда строк ... и затем время ожидания, в нечетное время: 2:38, 4:20 ... без рифмы или причины.

Это заставляет меня думать, что это какая-то транспортная ошибка, но я явно получаю исключение TimeoutException.

Согласно рекомендациям Массовая вставка не работает должным образом в SQL Server Azure , я 'мы также пытались сделать партии очень маленькими, но это, похоже, тоже ничего не делает.

Кто-нибудь может объяснить, что здесь происходит, и как решить эту проблему?Это блокирует разработку проекта высокого уровня, и я не хочу говорить людям, что могу заставить его работать на SQL Server Express моего ноутбука, но не на базе данных Azure.

Ответы [ 3 ]

0 голосов
/ 04 февраля 2019

Я просто попытался воспроизвести и не смог.SqlBulkCopy работал более 30 минут, прежде чем я отменил его.

Попробуйте это из-за пределов Azure для базы данных SQL Azure с низким DTU:

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");
    }


}
0 голосов
/ 22 апреля 2019

Оба ответа хороши, но, похоже, моя проблема не связана с кодом.Был некоторый «сбой в матрице», который, казалось, вызывал симптомы, которые я видел, и после определенного момента я больше не мог их воспроизводить.

0 голосов
/ 04 февраля 2019

Пожалуйста, запустите следующий запрос, и давайте попробуем найти свидетельство об удушении базы данных SQL Azure.

SELECT *
FROM sys.dm_db_resource_stats
ORDER BY end_time DESC;

Если вы видите, что avg_log_write_percent близок или равен 100%, то происходит удушение, и вам нужномасштабировать уровень базы данных.Уровни не премиум-класса не подходят для интенсивных рабочих нагрузок ввода-вывода, поэтому рекомендуется пакетная обработка.

Когда регулирование происходит в базе данных SQL Azure, вы не только увидите медленное время отклика, но и начнете видеть неудачные соединенияпопытка и время ожидания.

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
...