Poznatek o uložených procedurách a řízení transakcí

Top  Previous  Next

Seznam témat:

řešení

 

Řešení

V případě, že uložená procedura řídí transakce, narazil jsem na problémy, které se mi dlouho nedařilo vyřešit (a postupně jsem se k tomuto problému vracel, jak dovolovaly jiné termíny ) a domnívám se, že je na místě podělit se o poznatky.

Uložené procedury napsané v dialektu transact mají default CHAINED option "ON".  Viz "BEGIN TRANSACTION statement", "CHAINED option".

 

V popisu k "CHAINED option" je psáno:

Controls the Transact-SQL transaction mode.

1. In Unchained mode (CHAINED = OFF), each statement is committed individually unless an explicit BEGIN TRANSACTION statement is executed

to start a transaction.

2. In chained mode (CHAINED = ON) a transaction is implicitly started before any data retrieval or modification statement.

 

V popisu k "BEGIN TRANSACTION statement" je psáno

1.The default Adaptive Server Enterprise transaction mode, called unchained mode , commits each statement individually, unless an explicit

BEGIN TRANSACTION statement is executed to start a transaction.

In contrast, the ISO SQL/92 compatible chained mode only commits a transaction when an explicit COMMIT is executed or when a statement that

carries out an autocommit (such as data definition statements ) is executed.

 

2.In the ISO SQL/92 compatible chained mode only commits a transaction when an explicit COMMIT is executed or when a statement that

carries out an autocommit (such as data definition statements ) is executed.

 

3.In unchained mode, a transaction is implicitly started before any data retrieval or modification statement.

These statements include: DELETE, INSERT, OPEN, FETCH, SELECT, and UPDATE.

You must still explicitly end the transaction with a COMMIT or ROLLBACK statement.

 

Takže popis bod 1. je v rozporu s bodem 3. Jak to vlastně je?

 

Dlouhým testováním s umísťování beginů commitů transakcí a zjišťováním změn @@tancount a @@tranchained jsem zjistil, že přestože je

CHAINED=ON (zkusil jsem i explicitní nastavení ale nic se nezměnilo) autocomit té vnitřní transakce to neprovádí po každém INSERT,

UPDATE, DELETE, ale provádí po SELECT nebo FETCH. Navíc někdy to i po INSERT, UPDATE nebo DELETE autocommit provede, jinak by nemohly

některé procedury konverze vůbec fungovat - ale toto jsem netestoval.

 

Takže jsem zkusil následující taktiku, podle které jsem právě dodělal některé procedury a všechny fungují.

Dokonce nezávisle na nastavení CHAINED option:

 

Jakýkoliv insert update nebo delete, který je mimo transakci důsledně uzavírám do transakce, po každém takovém insert, update nebo delete vyhodnotím @@error a dle toho provedu commit nebo rollback. Procedura postavená podle této zásady funguje a to i nezávisle na nastavení CHAINED option.

 

Ale pozor, nabil jsem si .. tak, že jsem v konverzi z Oskara u přijatého plnění mimo transakci spouštěl uloženou proceduru, o které jsem si

myslel, že neprovádí změnu na datech, jenže z ní se volala další a z té další, kde se provedl droboučký update, a to byl problém. Když jsem

volání této procedury uzavřel do transakce, vše začalo fungovat.

 

Související témata