|
Использует ли метод DbCommand.Cancel тайм-аут?
|
|||
---|---|---|---|
#18+
У меня такая проблема: моё .NET приложение вызвало на MS SQL Server хранимую процедуру используя DBCommand.ExecuteScalar(). Процедура выполняется долго. В это время другой thread этого же приложения захотел отменить (cancel) этот вызов; и вызвал метод DbCommand.Cancel(). Я ожидал что тут же тот DBCommand.ExecuteScalar() (возврата из которого ждёт первый thread) сгенерирует exception. Но – ничего не произошло. Почему? Может быть – потому что тот объект DbCommand имеет большой (много часов) тайм-аут в свойстве CommandTimeout ? Может быть, метод DbCommand.Cancel() имеет логику вроде такой: “сперва подождём время DbCommand.CommandTimeout, и только потом делаем abort выполняющейся SQL-команде ” - ? Такая логика выглядит странно; но другого объяснения пока не имею. Документация про метод Cancel ( https://docs.microsoft.com/en-us/dotnet/api/system.data.common.dbcommand.cancel?view=netframework-4.7.2) ничего про это не говорит. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.06.2020, 17:00 |
|
Использует ли метод DbCommand.Cancel тайм-аут?
|
|||
---|---|---|---|
#18+
Чем вас не устраивает ExecuteScalarAsync(CancellationToken)? ... |
|||
:
Нравится:
Не нравится:
|
|||
26.06.2020, 17:58 |
|
Использует ли метод DbCommand.Cancel тайм-аут?
|
|||
---|---|---|---|
#18+
Shocker.Pro Чем вас не устраивает ExecuteScalarAsync(CancellationToken)? Если честно – я раньше про этот CancellationToken и не слышал :-) У меня есть старый код написанный много лет назад неизвестно кем; и он использует вот именно ту схему что я привёл выше – без CancellationToken. Переписать этот код на CancellationToken можно; спасибо за этот совет. Но всё-таки – может быть знаете, почему в вышеописанной схеме не сработал Cancel() вызванный из другого потока? ... |
|||
:
Нравится:
Не нравится:
|
|||
26.06.2020, 18:11 |
|
Использует ли метод DbCommand.Cancel тайм-аут?
|
|||
---|---|---|---|
#18+
KellyLynch Но всё-таки – может быть знаете, почему в вышеописанной схеме не сработал Cancel() вызванный из другого потока? Обновление по проблеме: я воссоздал ситуацию в установленном на моём PC сервере SQL Server 2012 и увидел вот что: 1. Вызванный из другого потока DbCommand.Cancel() вполне себе работает правильно. Делает то чего ожидалось: тот DBCommand.ExecuteScalar() (возврата из которого ждёт первый thread) сгенерирует exception. Моя версия про “Может быть – потому что тот объект DbCommand имеет большой (много часов) тайм-аут в свойстве CommandTimeout ? Может быть, метод DbCommand.Cancel() имеет логику вроде такой: “сперва подождём время DbCommand.CommandTimeout, и только потом делаем abort выполняющейся SQL-команде ” - ?” не подтвердилась – и слава богу. 2. Другое дело, что это всё может (в определённых обстоятельствах) занять много времени. То есть DbCommand.Cancel() возвращается-то быстро; но это всего лишь значит что “процесс абортирования текущей команды начался”. Как быстро этот “процесс абортирования” завершится – зависит от того, сколько времени SQL Server-у понадобится на то чтобы прервать (и сделать rollback) текущую транзакцию. А в конкретно моём случае вызываемая SQL процедура как раз и имела транзакцию внутри себя. Там был использовался SQL курсор которых ходил по большому списку IDs; и для каждого извлечённого значения из этого списка он делал так: Код: c# 1. 2. 3. 4. 5.
Ну вот – ежели этот самый “EXEC MySubProc()" к моменту вызова метода Cancel() успел много чего поменять в базе, то с момента вызова метода Cancel() “всё сделанное” надо откатить обратно (Rollback). Если “успел много чего поменять в базе” составляет десятки миллионов строк, то и отмена займёт много секунд (а то и – минут). Всё это время в моём .NET приложении “тот DBCommand.ExecuteScalar() (возврата из которого ждёт первый thread)” ничего не генерирует и не возвращает управление, а терпеливо ждёт пока SQL сервер закончит abort моей процедуры. Итак, всё объяснимо пока, кроме одного: когда я всё это передал автору упомянутой процедуры MySubProc (я про неё пока ничего не знаю) он сказал что “вряд ли моя процедура может что-то выполнять целый час и изменять десятки миллионов строк; обычно она успевает за минуту)”. Придётся мне тогда копать MySubProc. Возможно – кто то прочитав этот мой пост, сможет мне дать какие нибудь ещё полезные подсказки? Я вот про что: а вдруг на проблему "а почему же так долго SQL Server не может сделать abort для EXEC MySubProc(), ведь эта процедура вроде бы работает довольно быстро?" как-то влияет тот факт что (см выше) EXEC MySubProc() вызывается много раз - см мои слова " ...SQL курсор которых ходил по большому списку IDs; и для каждого извлечённого значения из этого списка он делал так:.. ". Мне кажется что тот факт что этих вызово много - несущественен; ведь транзакия открывается перед каждый из вызовов и закрывается полсле каждого из них. Или тут есть какой-то "подвох" которго я пока не вижу? ... |
|||
:
Нравится:
Не нравится:
|
|||
27.06.2020, 15:23 |
|
|
start [/forum/topic.php?fid=17&fpage=2&tid=1349063]: |
0ms |
get settings: |
10ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
28ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
44ms |
get tp. blocked users: |
2ms |
others: | 13ms |
total: | 134ms |
0 / 0 |