О вреде автоматических транзакций.
Привет всем.
Текущая деятельность заставила провести ревизию кода, связанного с управлением автоматическими транзакциями. Вот что я могу сказать по этому поводу:
1. Вы не контролируете момент завершения автоматической транзакции. И нет гарантий, в случае ошибки коммита автоматической транзакции, что вы получите об этом сообщение. Если автоматическая транзакция завершается при освобождении (последний вызов IUnknown::Release) потока с с данными блоба (COM-объекты с интерфейсом ISequentialStream) или набора рядов (COM-объекты с интерфейсом IRowset) — ошибки коммита будут задавлены в деструкторах соответствующих классов.
Навеяло. Одно время, провайдер пытался уведомлять пользователя о таких проблемах. И с этим связана забавная ошибка в Windows. Исправлена в Висте.
2. Текущая реализация (сборка 3.3.1.11241) ICommand::Execute (выполнение запроса) завершает автоматическую транзакцию после формирования буфера с OUT-значениями параметров. Если произойдет ошибка — провайдер выкинет ошибку, но буфер с OUT-значениями не очистит. И это может привести к проблемам в виде утечек ресурсов в процессе.
3. Автоматические транзакции безопасны при выполнении следующих условий
- Запрос содержит только входящие значения параметров.
- Запрос не возвращает курсор или этот курсор только читает данные.
Например, DDL-запросы можно выполнять в автоматической транзакции без всяких проблем и опасений.
4. Автоматические транзакции снижают скорость работы приложения. Потому что старт и завершение транзакций, мягко говоря, операции не дешевые.
—
Так что, в целом, если не хотите неприятностей — три раза подумайте перед тем как указывать «auto_commit=true» в вашей строке подключения.
Kovalenko on 7 января, 2011
В версии IBP v3.4 устранены все критические проблемы, которые могут возникнуть при использовании автоматических транзакций. В частности:
— (2)
В случае критических ошибок завершения операции выполнения команды, провайдер выполнит очистку буфера с установленными OUT-параметрами.
—
Если команда (с одиночным запросом) не возвращает результирующее множество, то коммит автоматической транзакции (по-умолчанию) будет выполнен явно. И, в случае ошибки завершения, пользователь получит информацию об этой ошибке.
Ранее, если команда возвращала OUT-параметр с блобом в виде объекта (ISequentialStream), автоматическая транзакция блокировалась этим объектом. И завершалась в при освобождении этого объекта. Соответственно — все ошибки давились в деструкторе. Сейчас, по-умолчанию в таких случаях, блоб перекачивается во временное хранилище и объект (который возвращается пользователю) уже не блокирует транзакцию. Иными словами, в случае автоматических транзакций для OUT-параметров запрещено отложенное чтение данных.
Настройка отложенного чтения осуществляется двумя новыми свойствами — deferred_data и deferred_out_param.
Насчет временного хранилища. Можно сильно не беспокоиться по поводу того, что оно начнет выжирать оперативную память. Оно работает на базе временного файла.
PS. Так что, будем считать, моё изложение о проблемах с автоматическими транзакциями принесло пользу. Я смог их переосмыслить и, сказав «какого чёрта?», устранить их 🙂