SQL> SET TRANSACTION READ ONLY ISOLATION LEVEL READ COMMITTED; %SQL-F-SETTRASLI, SET TRANSACTION statement specifies conflicting options SQL> -- or SQL> SET TRANSACTION READ ONLY ISOLATION LEVEL REPEATABLE READ; %SQL-F-SETTRASLI, SET TRANSACTION statement specifies conflicting options |
SQL> -- Declares characteristics for the first transaction: SQL> -- SQL> DECLARE TRANSACTION READ WRITE; SQL> -- SQL> -- There is no COMMIT or ROLLBACK statement between the SQL> -- DECLARE and the SET statements: SQL> -- SQL> SET TRANSACTION READ ONLY; SQL> -- SQL> -- The ROLLBACK statement rolls back the SET TRANSACTION SQL> -- statement. SQL> -- SQL> ROLLBACK; SQL> -- SQL> -- The transaction characteristics are once again those SQL> -- specified in the first DECLARE TRANSACTION statement: SQL> -- SQL> SELECT * FROM EMPLOYEES; |
トランザクション全体が正常にコミットされるまでは、データベースを変更するトランザクションのいずれの部分も完了しません。特に、トランザクションが正常にコミットされるまでは、トランザクション中の任意の時点においてデッドロックが発生する可能性があります。プログラムでは、読取り専用モードまたは排他モードで開始されたトランザクションを除き、各データベース操作後にDEADLOCKについて検証する必要があります。また、プログラムでトランザクションのNOWAITが宣言されている場合、LOCK_CONFLICTについて検証する必要があります。
通常、デッドロックまたはロック競合からリカバリするための最善の方法は、ROLLBACK文を使用し、トランザクションを再開する方法です。
データを共有モードで挿入または更新する場合、この表で索引の索引ノードがロックされる場合があります。この機能により、新規データのためにこれらの索引ノードを更新できるようになります。このプロセスはしばしばデッドロックが発生する原因となります。
SQL> ROLLBACK; SQL> SET TRANSACTION READ ONLY WAIT; SQL> SELECT * FROM EMPLOYEES; [waits for EXCLUSIVE WRITE transaction to end] . . . [EXCLUSIVE WRITE transaction performs COMMIT or ROLLBACK] %RDB-E-LOCK_CONFLICT, request failed due to locked resource; no-wait parameter specified for transaction -RDMS-F-CANTSNAP, can't ready storage area for snapshots |
読取り専用トランザクションは、エラー・メッセージの後にSELECT文を再発行する必要があります。
トランザクションでデータベース内の領域に対する排他書込みアクセスが必要な場合、スナップショット・ファイル内の同じ表のコピーにアクセスしようとする読取り専用トランザクションに対する排他書込みトランザクションの結果に注意する必要があります。
例1: 読取り専用トランザクションの開始
SQL> SET TRANSACTION READ ONLY;
この文の場合、データベースからデータを読み取ることはできますが、データを挿入または更新することはできません。データを取得すると、トランザクションが開始されたときに存在していたデータベース・レコードが表示されます。これ以降に行われたデータベースに対する更新は表示されません。
例2: SET TRANSACTION文を使用した特定の表の予約
次の文では、トランザクションで各表に対して目的のアクションを指定できます。
SQL> ATTACH 'FILENAME mf_personnel'; SQL> SET TRANSACTION READ WRITE RESERVING cont> EMPLOYEES FOR PROTECTED WRITE, cont> JOBS, SALARY_HISTORY FOR SHARED READ;
このトランザクションにより、他の2つの表(JOBSおよびSALARY_HISTORY)で見つかった値に基づいてEMPLOYEES表を更新するとします。
- このトランザクションではEMPLOYEES表を更新する必要があるため、EMPLOYEESは、保護された書込みアクセス用として用意されています。
- JOBS表およびSALARY_HISTORY表からは値の読取りのみが行われるため、書込みアクセスまたは保護された書込みアクセスは必要ありません。ただし、トランザクションでレコードを更新することが目的であるため、読取り専用トランザクションは適切ではありません。
例3: SET TRANSACTION文での複数のデータベースの指定
1つのトランザクションで複数のデータベースにアクセスできます。この例では、この機能の利点について説明します。
読取り専用トランザクションではデータのスナップショット・バージョンが使用されるため、アプリケーションで取得されるデータには古い値が含まれる場合があります。これは、読取り/書込みトランザクションを使用する別のトランザクションによって表が更新されている可能性があるためです。
スナップショット・ファイルは、他のプログラムによって更新されているデータベース行の以前のイメージを表します。最新のデータが必要な場合、両方のデータベースに対して読取り/書込みアクセスを指定し、共有読取りモードを組み込んで他のユーザーがデータベースの1つを読み取るのを許可する必要があります。この方法により、更新中にデータ整合性を保持するとともに、読取り対象のデータベースからのデータの同時取得を許可できます。
ただし、読取り/書込みトランザクションを設定する場合、可能な同時アクセス数が読取り専用アクセスよりも少なくなります。このため、読取り/書込みトランザクションを使用するのは必要な場合のみにしてください。
SET TRANSACTION文の複数データベース機能を使用する前に、アクセス対象の各データベースを指定するDECLARE ALIAS文を発行する必要があります。DECLARE ALIAS文には、別名を含める必要があります。たとえば、次のDECLARE ALIAS文では、更新アプリケーションに必要な2つのデータベースを識別しています。
EXEC SQL DECLARE DB1 ALIAS FOR FILENAME PERSONNEL; END EXEC EXEC SQL DECLARE DB2 ALIAS FOR FILENAME benefits; END EXEC
PERSONNELデータベースではEMPLOYEES表の読取りのみが必要ですが、BENEFITSデータベースでは2つの表(TUITIONおよびSTATUS)の値を変更する必要があるため、更新プログラムには、次のSET TRANSACTION文を含めることができます。
EXEC SQL SET TRANSACTION ON DB1 USING ( READ ONLY RESERVING DB1.EMPLOYEES FOR SHARED READ ) AND ON DB2 USING ( READ WRITE RESERVING DB2.TUITION FOR SHARED WRITE DB2.STATUS FOR SHARED WRITE ) END EXEC
例4: SET TRANSACTION文でのマルチスキーマ・データベースの指定
アクセスするデータベースの1つがマルチスキーマ・データベースである場合、デリミタ付き識別子を使用してこれを指定する必要があります。次の例は、単一スキーマのpersonnelデータベースおよびマルチスキーマのcorporate_dataデータベースにアクセスする方法を示しています。表EMPLOYEESは、CORPORATE_DATAデータベース内のカタログADMINISTRATIONのスキーマPERSONNEL内にあります。
SQL> ATTACH 'ALIAS CORP FILENAME corporate_data'; SQL> ATTACH 'ALIAS PERS FILENAME personnel'; SQL> SET QUOTING RULES 'SQL92'; SQL> SET CATALOG '"CORP.ADMINISTRATION"'; SQL> SET SCHEMA '"CORP.ADMINISTRATION".PERSONNEL'; SQL> -- SQL> SET TRANSACTION ON CORP USING (READ ONLY cont> RESERVING "CORP.EMPLOYEES" FOR SHARED READ) cont> AND ON PERS USING (READ WRITE RESERVING cont> PERS.EMPLOYEES FOR SHARED WRITE);
例5: SET TRANSACTION文での動詞実行時における評価の指定
次の例は、EMPLOYEE_ID 00164の新規取得学位をDEGREES表に挿入する処理を示しています。新規学位であるMMEが評価されましたが、これは受入れ可能な学位コードではないため、エラー・メッセージが即時に返されています。
SQL> ATTACH 'FILENAME personnel'; SQL> SET TRANSACTION READ WRITE cont> EVALUATING DEGREES_FOREIGN1 AT VERB TIME, cont> DEGREES_FOREIGN2 AT VERB TIME, cont> DEG_DEGREE_VALUES AT VERB TIME cont> RESERVING DEGREES FOR PROTECTED WRITE, cont> COLLEGES, EMPLOYEES FOR SHARED READ; SQL> SHOW TRANSACTION Transaction information: Statement constraint evaluation is off On the default alias Transaction characteristics: Read Write Evaluating constraint DEGREES_FOREIGN1 at verb time Evaluating constraint DEGREES_FOREIGN2 at verb time Evaluating constraint DEG_DEGREE_VALUES at verb time Reserving table DEGREES for protected write Reserving table COLLEGES for shared read Reserving table EMPLOYEES for shared read Transaction information returned by base system: a read-write transaction is in progress - updates have not been performed - transaction sequence number (TSN) is 153 - snapshot space for TSNs less than 153 can be reclaimed - session ID number is 21 SQL> INSERT INTO DEGREES cont> (EMPLOYEE_ID, COLLEGE_CODE, YEAR_GIVEN, cont> DEGREE, DEGREE_FIELD) cont> VALUES cont> ('00164', 'PRDU', 1992, cont> 'MME', 'Mech Enging'); %RDB-E-INTEG_FAIL, violation of constraint DEG_DEGREE_VALUES caused operation to fail -RDB-F-ON_DB, on database DISK1:[JONES.PERSONNEL]PERSONNEL.RDB;1 SQL> ROLLBACK;
例6: トランザクションでの分離レベルの明示的な設定
この文では、データベースでのデータの読取りと書込みが可能です。また、トランザクションは、上位のデフォルト分離レベルであるSERIALIZABLEではなく、分離レベルREAD COMMITTEDで実行されるよう設定されています。
SQL> SET TRANSACTION READ WRITE ISOLATION LEVEL REPEATABLE READ;
例7: 索引の同時作成
次の例は、共有データ定義用の表を予約する方法と、索引を作成する方法を示しています。
SQL> SET TRANSACTION READ WRITE cont> RESERVING EMPLOYEES FOR SHARED DATA DEFINITION; SQL> -- SQL> CREATE INDEX EMP_LAST_NAME1 ON EMPLOYEES (LAST_NAME); SQL> -- SQL> -- Commit the transaction immediately. SQL> -- SQL> COMMIT;
例8: パーティションの予約
SQL> -- This example locks only the second partition of SQL> -- the EMPLOYEES table in exclusive write mode. SQL> -- The advantage of this is that the process can insert, SQL> -- update, or delete from this partition without writing SQL> -- to the snapshot (.snp) file, and in general, uses fewer SQL> -- resources for operations on the partition. SQL> SET TRANSACTION READ WRITE cont> RESERVING EMPLOYEES PARTITION (2) FOR EXCLUSIVE WRITE;
例9: RESERVING句と列のDEFAULT値の相互作用
この例では、表を(直接的または間接的に)参照するDEFAULT値とRESERVING句の相互作用について確認します。SET TRANSACTIONのRESERVING句により、トランザクションは、このトランザクション用としてリストされている表にのみ制限されます。
制約、トリガー、COMPUTED BY句、AUTOMATIC句およびDEFAULT値によって直接参照される表は、SHARED READ用として暗黙的に予約されます。ただし、これらの定義によってストアド・ファンクションを介して表が間接的に参照される場合、この表は自動予約の対象とはみなされません。
この例では、DEFAULT値を使用して、3つの異なるメカニズムおよびそのRESERVING句との相互作用を対比しています。この技術は、トリガーおよび制約などの他の定義にも適用できます。
DEFAULT値は、データベースの有効なユーザーごとに1つの値が保持されるセカンダリ表(DEFAULTS)から導出されます。DEFAULTは、CURRENT_USERの値に基づいて取得されます。次の3つの表では、値は、直接フェッチされるか(SAMPLE_TABLE2)、ストアド・ファンクションを介してフェッチされています(SAMPLE_TABLE1およびSAMPLE_TABLE3)。
SQLファンクションGET_DEFAULT3には、表を正しく予約できるようLOCK TABLE文が含まれています。この方法を使用すると、プログラマはトランザクションに対してRESERVING句をコーディングするときに必要な表を把握しなくて済むため、この方法を使用することをお薦めします。
SQL> set dialect 'sql99'; SQL> SQL> create table DEFAULTS cont> (user_id rdb$object_name primary key, cont> valid_number integer); SQL> insert into DEFAULTS values ('SMITH', 100); 1 row inserted SQL> SQL> create module UTL1 cont> function GET_DEFAULT1 () cont> returns integer cont> not deterministic; cont> return (select valid_number from DEFAULTS cont> where user_id = CURRENT_USER); cont> end module; SQL> SQL> create table SAMPLE_TABLE1 cont> (id integer identity, cont> quantity integer cont> default GET_DEFAULT1 () cont> ); SQL> SQL> create table SAMPLE_TABLE2 cont> (id integer identity, cont> quantity integer cont> default (select valid_number from DEFAULTS cont> where user_id = CURRENT_USER) cont> ); SQL> SQL> create module UTL3 cont> function GET_DEFAULT3 () cont> returns integer cont> not deterministic; cont> begin cont> lock table DEFAULTS for shared read mode; cont> return (select valid_number from DEFAULTS cont> where user_id = CURRENT_USER); cont> end; cont> end module; SQL> SQL> create table SAMPLE_TABLE3 cont> (id integer identity, cont> quantity integer cont> default GET_DEFAULT3 () cont> ); SQL> SQL> commit;
次のトランザクションは、この例で説明するように成功または失敗しています。
SQL> /* ***> Fails because the module references a table that is not reserved ***> */ SQL> set transaction read write cont> reserving SAMPLE_TABLE1 for shared write; SQL> insert into SAMPLE_TABLE1 default values; %RDB-E-UNRES_REL, relation DEFAULTS in specified request is not a relation reserved in specified transaction SQL> rollback; SQL> SQL> /* ***> Succeeds because direct access to the table from the DEFAULT ***> is implicitly added to the reserving list as SHARED READ ***> */ SQL> set transaction read write cont> reserving SAMPLE_TABLE2 for shared write; SQL> insert into SAMPLE_TABLE2 default values; 1 row inserted SQL> rollback; SQL> SQL> /* ***> Succeeds because the routine adds the table to the reserved ***> table list using LOCK TABLE. ***> */ SQL> set transaction read write cont> reserving SAMPLE_TABLE3 for shared write; SQL> insert into SAMPLE_TABLE3 default values; 1 row inserted SQL> rollback; SQL>