О вреде автоматических транзакций.

Привет всем.

Текущая деятельность заставила провести ревизию кода, связанного с управлением автоматическими транзакциями. Вот что я могу сказать по этому поводу:

1. Вы не контролируете момент завершения автоматической транзакции. И нет гарантий, в случае ошибки коммита автоматической транзакции, что вы получите об этом сообщение. Если автоматическая транзакция завершается при освобождении (последний вызов IUnknown::Release) потока с с данными блоба (COM-объекты с интерфейсом ISequentialStream) или набора рядов (COM-объекты с интерфейсом IRowset) — ошибки коммита будут задавлены в деструкторах соответствующих классов.

Навеяло. Одно время, провайдер пытался уведомлять пользователя о таких проблемах. И с этим связана забавная ошибка в Windows. Исправлена в Висте.

2. Текущая реализация (сборка 3.3.1.11241) ICommand::Execute (выполнение запроса) завершает автоматическую транзакцию после формирования буфера с OUT-значениями параметров. Если произойдет ошибка — провайдер выкинет ошибку, но буфер с OUT-значениями не очистит. И это может привести к проблемам в виде утечек ресурсов в процессе.

3. Автоматические транзакции безопасны при выполнении следующих условий

  • Запрос содержит только входящие значения параметров.
  • Запрос не возвращает курсор или этот курсор только читает данные.

Например, DDL-запросы можно выполнять в автоматической транзакции без всяких проблем и опасений.

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


Так что, в целом, если не хотите неприятностей — три раза подумайте перед тем как указывать «auto_commit=true» в вашей строке подключения.

One Comment

Kovalenko  on 7 января, 2011

В версии IBP v3.4 устранены все критические проблемы, которые могут возникнуть при использовании автоматических транзакций. В частности:

— (2)
В случае критических ошибок завершения операции выполнения команды, провайдер выполнит очистку буфера с установленными OUT-параметрами.


Если команда (с одиночным запросом) не возвращает результирующее множество, то коммит автоматической транзакции (по-умолчанию) будет выполнен явно. И, в случае ошибки завершения, пользователь получит информацию об этой ошибке.

Ранее, если команда возвращала OUT-параметр с блобом в виде объекта (ISequentialStream), автоматическая транзакция блокировалась этим объектом. И завершалась в при освобождении этого объекта. Соответственно — все ошибки давились в деструкторе. Сейчас, по-умолчанию в таких случаях, блоб перекачивается во временное хранилище и объект (который возвращается пользователю) уже не блокирует транзакцию. Иными словами, в случае автоматических транзакций для OUT-параметров запрещено отложенное чтение данных.

Настройка отложенного чтения осуществляется двумя новыми свойствами — deferred_data и deferred_out_param.

Насчет временного хранилища. Можно сильно не беспокоиться по поводу того, что оно начнет выжирать оперативную память. Оно работает на базе временного файла.

PS. Так что, будем считать, моё изложение о проблемах с автоматическими транзакциями принесло пользу. Я смог их переосмыслить и, сказав «какого чёрта?», устранить их 🙂

Leave a Comment