-
Дмитрий Тимохов (25.04.11 15:16) [0]Добрый день!
Ситуация такова:
1. Использую базу данных MS SQL Server.
2. Для доступа использую ADODB.
3. Использую провайдер SQLOLEDB
Проблема:
1. Хочу отлавливать момент, когда ADODB.Command завершается с ошибкой "Timeout expired" для целей последующей отладки подобных ситуаций.
Что не получается:
1. Не могу понять, как по ADODB.Error понять, что произошла эта ошибка (кроме как анализировать ADODB.Error.Description - но это же несерьезно).
2. Не могу понять, откуда вообще брать коды ошибок, и что значат на самом деле ADODB.Error.NativeError и ADODB.Error.SqlState.
Что делал:
1. Поймал ошибку в runtime.
Description: "Timeout expired"
Native error: "0"
Source: "Microsoft OLE DB Provider for SQL Server"
SQLState: "HYT00"
2. Я подумал, что HYT00 это код ошибки из Microsoft OLE DB Provider for SQL Server. Но не нашел такого.
3. Потому я подумал, что это может код ошибки из стандарта SQL. Но там вроде согласно http://msdn.microsoft.com/en-us/library/aa937531%28SQL.80%29.aspx кодом ошибки для Timeout expired является S1T00
Вопросы:
1. Какая ошибка то должна быть?
2. Правильно я понимаю, что есть:
а) Ошибки ADODB
б) Ошибки сервера
в) Ошибки OLEDB Provider'а
Если да, то то где их всех отлавливать: в NativeError или SQLState?
3. Где взять списки возможных ошибок? -
> 1. Какая ошибка то должна быть?
Походу EOleException
> в) Ошибки OLEDB Provider'а
http://msdn.microsoft.com/en-us/library/ms190181.aspx
> 3. Где взять списки возможных ошибок?
Сейчас под рукой нет, см. в msdn и bol.
Вообще я когда-то давно что-то подобное ловил, там у класса исключения ErrorCode должен быть. -
Самое простое: тестовый проект, коннект к базе, отрубаешь сервер и вызываешь какой-нить запрос.
try
ADODataSet.Open;
except on E: Exception do
ShowMessage(E.ClassName);
end;
Вроде бы должен EOleError вернуть, у него код определённый есть. Выщучивай код и ищи в MSDN по нему (как в dec, так и в hex). -
Дмитрий Тимохов (25.04.11 15:55) [3]Олегыч, ну я делал все это. Что нашел, то привел в вопросе.
Почему вроде должен быть код ошибки в SQLState S1T00, а на самом деле HYT00... -
> Олегыч, ну я делал все это. Что нашел, то привел в вопросе.
Значит не так понял вопрос.
ЕМНИП, там две разных ошибки. Одна - собственно сам процесс коннекта. Вторая - длительное выполнение команды.
Возможно это именно та разница. -
Дмитрий Тимохов (25.04.11 16:21) [5]Коннект нормальный. Я про выполнение запроса уже с помощью ADODB.Command.Execute. Меня интересует этот таймаут
-
> Коннект нормальный. Я про выполнение запроса уже с помощью
> ADODB.Command.Execute. Меня интересует этот таймаут
ааа.
тогда см. ADODB.Command.CommandTimeout -
Дмитрий Тимохов (25.04.11 16:50) [7]Олегыч, ты вопрос то прочти.
Суть вопроса - по факту возвращается один код ошибки, а вроде должен быть другой, или я не понимаю что-то в структуре ошибок кодов ошибок... -
OW © (25.04.11 17:02) [8]try
except
on E:Exception do
begin
EOleException(E).ErrorCode; // comobj
end;
end;
какой код? -
Дмитрий Тимохов (25.04.11 17:08) [9]
> какой код?
//
// MessageId: DB_E_ABORTLIMITREACHED
//
// MessageText:
//
// Execution aborted because a resource limit has been reached; no
// results have been returned
//
DB_E_ABORTLIMITREACHED = HResult($80040E31); -
Дмитрий Тимохов (25.04.11 17:18) [10]Перефразирую вопрос - как бы вы гарантированно отлавливали timeout?
-
> HResult($80040E31);
Вот http://social.msdn.microsoft.com/forums/en-US/sqldataaccess/thread/4baafb7f-8eae-4ca8-90fc-2a4273c0fd57/
(вместе с комментариями)
Ещё тут http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.commandtimeout.aspx -
OW © (25.04.11 17:22) [12]блокировки, видимо
что за запрос? -
Дмитрий Тимохов (25.04.11 17:29) [13]да запрос то не причем.
я просто пытаюсь наладить логирование плохих запросов.
специально поставил таймаут на минимум - многие отчеты вываливаются по таймауту.
хочу понять, как определять, что это таймаут -
> специально поставил таймаут на минимум - многие отчеты вываливаются
> по таймауту.
Ставь в 0, мало ли какой там отчет, или какая активность сервера?
Вполне может быть, что решается через какой-нитьDBCC DBREINDEX -
Дмитрий Тимохов (25.04.11 17:41) [15]хороший совет. все равно, что - terminateprocess непокорным делать. ))
-
> хороший совет. все равно, что - terminateprocess непокорным
> делать.
Не, ну а что ты хочешь? Как можно оценить продолжительность выполнения запроса и выставить нужный timeout на конкретном сервере? Может быть дохлое железо, может быть много подключений, может быть старая индексация таблиц, может быть загрузка сети. Да что угодно может быть. -
Дмитрий Тимохов (25.04.11 19:14) [17]блин ))) ты и MSDN так читаешь)))))
я хочу услышать компетентный ответ, как МНЕ ОДНОЗНАЧНО ПОНЯТЬ, что выполнение метода ADODB.Command.Execute закончилось именно в ошибкой TIMEOUT EXPIRED, а не любой другой. -
Дмитрий Тимохов (25.04.11 19:15) [18]Я пока проверяю SQLState и на равенство HYT00 и на S1T00... (по союзу OR, конечно, если что...)
Вроде работает. Но удивляет, почему в доке одно (т.е. S1T00), а по факту HYT00...
Может кто объяснит это? Возможно, что я не верно понимаю топологию кодов ошибок... -
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
begin
try
ADOCommand1.Execute;
Memo1.Lines.Add('Ok');
except
on E: Exception do begin
Memo1.Lines.Add(E.ClassName + ' : ' + E.Message);
if E is EOleException then
Memo1.Lines.Add('EOleException.ErrorCode : ' + IntToStr(EOleException(E).ErrorCode));
with ADOConnection1.Errors do
for i:= 0 to ADOConnection1.Errors.Count-1 do
with Item[i] do
Memo1.Lines.Add(IntToStr(NativeError {0}) + ':' +IntToStr(Number {-2147217871}) + ' : ' + Description);
end;
end;
end;