BDE, Delphi, ODBC, собственный клиент SQL и мертвая блокировка
У нас есть некоторый код Delphi, который использует BDE для доступа к SQL Server 2008 через драйвер ODBC для собственного клиента SQL Server (версия 2005 года). Наша проблема заключается в том, что у нас возникают проблемы с тупиком в цикле, выполняющем вставки в несколько таблиц.
Весь цикл выполняется внутри [TDatabase].StartTransaction. Глядя на SQL Server Profiler, мы ясно видим, что в какой-то момент цикла SPID (ID сеанса?) Меняются, и тогда мы, естественно, заходим в тупик. (Оба SPID делают вставки в одну таблицу)
Кажется, что BDE в какой-то момент устанавливает второе соединение с БД...
(Хотя я хотел бы пропустить BDE, в настоящее время это невозможно.)
Кто-нибудь с опытом поделиться?
3 ответа
Если ваше приложение многопоточное: BDE не является потокобезопасным. Вы должны использовать отдельный сеанс BDE (явно созданный экземпляр TSession
) для каждой темы; глобальный Session
созданного автоматически для основного потока недостаточно. Кроме того, все компоненты доступа к базе данных (TDatabase
, TQuery
и т. д.) могут использоваться только в контексте потока, где их соответствующий экземпляр TSession
был создан.
В установке ODBC проверьте, настроен ли драйвер SQL Server для создания пула соединений. Кажется, что установка Native Client активирует его по умолчанию... (По крайней мере, моя установка имела активный пул соединений, и я не активировал его).
Возможно, это слишком поздно для спрашивающего, но, возможно, это поможет другим.
Каждый раз, когда появляется курсор, который не закрывается, комбинация BDE/ODBC устанавливает новое соединение для последовательных запросов. "Смена спида", вероятно, является результатом незамкнутого курсора.
Чтобы решить эту проблему, вы должны найти BDE-компонент, который вызвал этот открытый курсор. Затем вы вызываете метод, который в конечном итоге закроет курсор (TTable.Close
, TTable.Last
...).
После этого "смена спида" должна исчезнуть и, следовательно, тупик.
Несколько советов, чтобы найти этот компонент:
- Во время блокировки выполните следующую инструкцию (например, с помощью Management Studio):
EXEC sp_who2
, - Посмотри в колонке
BlkBy
, В заблокированном соединении есть номер. - Этот номер является
spid
(Идентификатор процесса сервера) блокирующего соединения. - Затем вы выполняете
DBCC INPUTBUFFER(spid)
, - В колонке
EventInfo
Вы найдете SQL-оператор, выданный вашей программой. - С этой информацией вы сможете найти BDE-компонент, который вызывает у вас проблемы.