Транзакції

Firebird підтримує слідуючі рівні ізоляції транзакції:

Firebird виконує блокування рівня строки завжди в будь-якому випадку.

Firebird виконує оптимістичне блокування. Ваша транзакція не пробує блокувати запис, поки Ви не запрошуєте операцію модифікації, котра змінює цей запис. Це означає, що це можливо, хоча вкрай рідко, для вашої модифікації, щоб терпіти невдачу, тому що другий клиєнт блокував запис, навіть якщо Ви розпочали Вашу транзакцію раніше ніж інший клиєнт.

Firebird використовує версіоний двигун, щоб забезпечити ступінь деталювання більш точніше ніж забезпечення традиційного блокування рівня строки. Версійний двигун дозволяє будь-якій кількості клієнтів читати непротирічну копію будь-якого записа, навіть якщо в той самий час інший клиєнт змінює той самий запис. Читаючі і пишучі транзакції один той самий запис николи не блокують один одного.

Починаючи з версії v2.0, Firebird ODBC підтримує всі без винятку транзакції, які тільки може забезпечити сервер, включаючи блокування таблиць. Для цього було добавлено SQL синтаксис(GPRE), який виконується ODBC API функцією SQLExecDirect.

Повна форма запиту:

SET|DECLARE TRANSACTION [LOCAL] [NAME transaction [USING nameUniqueWorkspase]]
[READ WRITE | READ ONLY]
[WAIT | NO WAIT]
[AUTOCOMMIT]
[NO_AUTO_UNDO]
[[ISOLATION LEVEL] {SNAPSHOT [TABLE STABILITY] or REPEATABLE READ
| SERIALIZABLE
| READ COMMITTED [[NO] RECORD_VERSION]}]
[RESERVING 'reserving_clause'];

'reserving_clause' = table [, table :]
[FOR [SHARED | PROTECTED] {READ | WRITE}] [, ]

Призначення і опис.

DECLARE TRANSACTION... - декларування транзакції, без її виконання.

SET TRANSACTION... - ставимо транзакцію на виконання, вимикаючи установку SQL_ATTR_AUTOCOMMIT в позицію SQL_AUTOCOMMIT_OFF. Після завершення активної буде працювати вказана.
LOCAL - визначає виконання транзакції в межах активного оператора(запита).
NAME transaction - виняткове ім'я транзакції, по якому формується в середовищі з'єднань таблиця транзакцій підготовлених до виконання.
USING nameUniqueWorkspase - виняткове ім'я робочого простору транзакцій, по якому в середовищі з'єднань формуються таблиці транзакцій підготовлених до виконання.
Ми, маючи два робочі простори, можемо в них мати транзакції з однаковими іменами, але з різними описами самих транзакцій по суті.

DECLARE TRANSACTION ... [NAME transaction [USING nameUniqueWorkspase]]
Ця форма запису передбачена для попередньої підготовки описа транзакцій, які зберігаються в середовищі з'єднань. Це економить час і дозволяє багаторазово використовувати для будь якого активного з'єднання. Виклик такої транзакції на виконання виконується командою:

- для з'єднання

- для окремого запита в межах одного з'єднання


SET TRANSACTION ... [NAME transaction [USING nameUniqueWorkspase]]
Ця форма запису відрізняється від попереднього тим, що ставить транзакцію на виконання, після завершення активної, якщо така існує. Але якщо вказано ключове слово NAME або USING, то ця транзакція може також багаторазово визиватися вже тільки з вказівкою її імені. Примітка. Для повернення в звичайний ритм роботи потрібно виконати повторне з'єднання.

Також, добавлено обслуговування SQL запитів COMMIT і ROLBACK, ці виклики виконують ту саму роботу що і основний виклик SQLEndTran. Є програми, які вміють викликати SQLExecDirect і не вміють викликати SQLEndTran. Для цих програм потрібно виконати виклик

що гарантовано забезпечить виклик: Але якщо транзакція була ініціювали як локальна, то драйвер виконає SQLEndTran для локального hStmt.

Two Phase Commit Transactions

Ця можливість дозволяє максимально на 16 різних Firebird базах даних виконувати commit(завершення) транзакції. Наприклад, використовуючи інструкцію

Ви повідомляєте Firebird ODBC, що це з'єднання повинно бути присутнім в схемі "two phase commit transactions". Піключив цією командой декілька з'єднаннь і виконуючи на будь-якому з'єднання Commit або Rollback, Ви отримаєте схему "two phase commit transactions". Для виключення з'єднання з схеми використовуйте інструкцію:

Приклад використання різних транзакцій в одному з'єднанні

    HSTMT stmtRd;
    HSTMT stmtWr;

    SQLAllocHandle( SQL_HANDLE_STMT, connection, &stmtRd );
    SQLAllocHandle( SQL_HANDLE_STMT, connection, &stmtWr );

    SQLExecDirect( stmtRd, (UCHAR*)
		   "SET TRANSACTION LOCAL\n"
		   "READ ONLY\n"
		   "ISOLATION LEVEL\n"
		   "READ COMMITTED NO RECORD_VERSION WAIT\n",
		   SQL_NTS );

    SQLExecDirect( stmtWr, (UCHAR*)
		   "SET TRANSACTION LOCAL\n"
		   "READ WRITE\n"
		   "ISOLATION LEVEL\n"
		   "READ COMMITTED NO RECORD_VERSION WAIT\n",
		   SQL_NTS );

    SQLExecDirect( stmtRd,(UCHAR*)
		   "SELECT CURRENCY FROM COUNTRY"
		   "   WHERE country = 'Canada'"
		   "   FOR UPDATE OF CURRENCY",
		   SQL_NTS );

    SQLFetch( stmtRd );

    SQLPrepare( stmtWr, (UCHAR*)
		"update COUNTRY\n"
		"set    CURRENCY = 'CndDlr'\n"
		"where  COUNTRY = 'Canada'\n",
		SQL_NTS );

    SQLExecute( stmtWr );

    SQLExecDirect( stmtWr, (UCHAR*)"COMMIT", SQL_NTS );

Для більш детального знайомства з цими і іншими можливостями будьласка, розгляньте приклади.