Ошибка истечения времени ожидания DTU отдельной базы данных SQL Azure

Я использую модель покупки DTU для одной базы данных Azure SQL. Средняя загрузка, кажется, составляет менее 10%. Время от времени я получаю ошибку, теперь это происходит почти каждый день. Я использую EF Core 3.1 для доступа к базе данных. Доступ к базе данных осуществляется через API, созданный с помощью ядра ASP.NET 3.1 и развернутый в службе приложений Linux Azure.
Ошибка:
Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (258): Unknown error 258

Трассировки стека:

An exception occurred in the database while saving changes for context type 'MTP.Api.Persistence.MTPDbContext'.
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
 ---> Microsoft.Data.SqlClient.SqlException (0x80131904): Execution Timeout Expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
 ---> System.ComponentModel.Win32Exception (258): Unknown error 258
   at Microsoft.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__164_0(Task`1 result)
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
ClientConnectionId:16f899d4-cfc9-4401-b631-1b4d547c4c19
Error Number:-2,State:0,Class:11
ClientConnectionId before routing:02e37a1e-981c-4ff6-9437-cade8b401cc5
Routing Destination:c71faab34237.tr1.francecentral1-a.worker.database.windows.net,11018
   --- End of inner exception stack trace ---
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(DbContext _, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)

Любая идея, что может вызвать это? Или как найти причину проблемы?


person Emanuel Paul    schedule 24.07.2020    source источник
comment
Включите хранилище запросов и следите за временем выполнения запроса и статистикой ожидания. docs.microsoft.com/en-us/sql/relational-databases/performance/ Это время ожидания на стороне клиента, которое вы можете увеличить: docs.microsoft.com/en-us/dotnet/api/   -  person David Browne - Microsoft    schedule 24.07.2020
comment
Спасибо, Дэвид, я включу хранилище запросов. Период ожидания составляет уже 30 секунд.   -  person Emanuel Paul    schedule 24.07.2020
comment
Возможно, вам придется увеличить время ожидания для сбора статистики ожидания, поскольку я считаю, что они могут быть получены только для завершенных запросов. Хранилище запросов включено по умолчанию в sql azure. Выбор плана запроса может быть фактором, поэтому опубликуйте его, если вы застряли   -  person Conor Cunningham MSFT    schedule 25.07.2020
comment
Я увеличу таймаут. Эта ошибка возникает только в Azure SQL, она отлично работает в SQL Server 2017 Express.   -  person Emanuel Paul    schedule 25.07.2020
comment
Насколько велики задействованные таблицы? Если большой, то одной из возможностей для получения такого рода спорадической ошибки может быть обновление статистики (если они не настроены на асинхронное обновление) - другой возможностью для любого размера таблицы может быть блокировка от других транзакций.   -  person Martin Smith    schedule 25.07.2020
comment
Таблицы действительно маленькие, самые большие, используемые для чтения и записи, составляют около 2-3 МБ. Есть один на 117 МБ, но он используется только для чтения данных.   -  person Emanuel Paul    schedule 26.07.2020


Ответы (2)


Я обновил пакет nuget Microsoft.Data.SqlClient до версии 2.0. Кажется, это решает проблему.

API использует EF Core 3.1. EF Core использует MARS (MultipleActiveResultSets). Похоже, возникла проблема с Microsoft.Data.SqlClient версии 1.0 при развертывании в Linux и использовании MARS. EF Core по умолчанию использует v1.

person Emanuel Paul    schedule 12.08.2020

Это может быть связано с исключением EF Core при отправке нескольких запросов #13452:

Я обновил свой проект до ASP.NET Core 2.1 RTM. Когда я отправляю несколько запросов, я получаю это исключение:

Exception has occurred: CLR/System.Data.SqlClient.SqlException
An exception of type 'System.Data.SqlClient.SqlException' occurred in Microsoft.EntityFrameworkCore.dll but was not handled in user code: 'Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.'
 Inner exceptions found, see $exception in variables window for more details.
 Innermost exception   System.ComponentModel.Win32Exception : Unknown error 258

@ajcvicers Я обнаружил проблему. Хост SQL Server получил два обновления: KB4338815, KB4338824.

Известные проблемы в этом обновлении Перезапуск службы SQL Server может иногда завершаться ошибкой «Порт TCP уже используется».

Когда я удалил эти обновления, мой проект заработал без проблем.


Конечно, это также может быть просто тупиковым сценарием. Чтобы легче отслеживать это, вы можете захотеть регистрировать как очень медленные, но успешные запросы, так и неудачные запросы.

В сценарии взаимоблокировки участвуют по крайней мере два запроса. По крайней мере, один будет тайм-аут, но другой может все еще быть ниже порога тайм-аута, а затем завершиться успешно после отмены первого запроса. Поэтому, если вы зарегистрируете оба, вы сможете отследить причину взаимоблокировки.


В любом случае, если вы хотите решать подобные проблемы в целом, вы можете настроить Устойчивость соединения, используя options.EnableRetryOnFailure() и, возможно, уменьшая значение времени ожидания команды. Это повторит неудачные операции.

person lauxjpn    schedule 25.07.2020
comment
Кажется, он отлично работает на SQL Server 2017 Express. Ошибка возникает только в SQL Azure. Так что, вероятно, это не связано с ошибкой, которую я получаю. - person Emanuel Paul; 25.07.2020
comment
Я обновил свой ответ, указав другую причину и несколько общих советов. - person lauxjpn; 25.07.2020
comment
Устойчивость соединения уже используется. Я заметил, что вся таблица заблокирована, поэтому с этой таблицей нельзя выполнять никаких действий, пока не будет изменен план обслуживания. - person Emanuel Paul; 26.07.2020
comment
Проверьте журнал базы данных на стороне сервера, чтобы увидеть, что происходит. Кроме того, что вы имеете в виду под изменением тарифного плана? - person lauxjpn; 26.07.2020
comment
При использовании SQL Azure существует несколько ценовых категорий и режимов покупки. Таблица остается заблокированной (происходит ошибка тайм-аута) до тех пор, пока ценовая категория не изменится, например, с 20 DTU на 50 DTU. - person Emanuel Paul; 26.07.2020
comment
Сколько одновременных подключений у вас есть в часы пик, и происходят ли эти тайм-ауты в пиковое время? Предполагая наличие тупиковой ситуации, это может привести к блокировке всех других соединений, а также ожиданию одной из заблокированных таблиц. Это исчерпало бы ваши DTU. Другие запросы могут по-прежнему стоять в очереди позади, и хотя первый запрос в конечном итоге истечет по тайм-ауту, следующие запросы могут продолжать блокировать таблицы. Если происходит тайм-аут, вы должны зарегистрировать, сколько DTU используется в настоящее время и не заблокированы ли какие-либо таблицы. - person lauxjpn; 26.07.2020