Poznatek o uložených procedurách a řízení transakcí |
Top Previous Next |
Seznam témat:
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 |