このチュートリアルでは、Accountant と Sales Manager はどちらも SalesOrder テーブルと SalesOrderItems テーブルに関わるタスクを行います。Accountant は、2001 年の 4 月に売り上げを上げた販売担当者に支払ったコミッションの小切手額を確認する必要があります。Sales Manager は、データベースに追加されなかった注文がいくつかあることに気づき、それを追加したいと思っています。
彼らの操作で幻ロックについて説明します。「幻ロック」は幻ローを防ぐためにインデックス・スキャン位置に設定される共有ロックです。独立性レベル 3 のトランザクションが特定の基準を満たすローを選択すると、データベース・サーバは対挿入ロックを設定し、他のトランザクションが基準を満たすローを挿入することを禁止します。設置するロック数は検索基準やデータベースの設計によって異なります。
このチュートリアルが正常に動作するためには、Interactive SQL ([ツール] - [オプション] - [SQL Anywhere]) の[データベース・ロックの自動解放] オプションをオフにする必要があります。
Interactive SQL の 2 つのインスタンスを起動します。チュートリアル:繰り返し不可能読み出しの手順 1 ~ 4 を参照してください。
次のコマンドを実行して、Sales Manager のウィンドウと Accountant のウィンドウに独立性レベル 2 を設定します。
SET TEMPORARY OPTION isolation_level = 2; |
毎月、販売担当者には、その月の各人の売り上げ高に対し、一定の割合のコミッションが支払われます。Accountant は、2001 年 4 月分のコミッションの小切手を準備しています。彼の最初のタスクは、その月の各担当者の売り上げ合計額を計算することです。
Accountant のウィンドウに次のコマンドを入力します。価格、注文情報、従業員データがそれぞれ別のテーブルに保存されます。外部キー関係を使用してこれらのテーブルをジョインすることにより、必要な情報を結合します。
SELECT EmployeeID, GivenName, Surname, SUM(SalesOrderItems.Quantity * UnitPrice) AS "April sales" FROM Employees KEY JOIN SalesOrders KEY JOIN SalesOrderItems KEY JOIN Products WHERE '2001-04-01' <= OrderDate AND OrderDate < '2001-05-01' GROUP BY EmployeeID, GivenName, Surname ORDER BY EmployeeID; |
EmployeeID | GivenName | Surname | April sales |
---|---|---|---|
129 | Philip | Chin | 2160.00 |
195 | Marc | Dill | 2568.00 |
299 | Rollin | Overbey | 5760.00 |
467 | James | Klobucher | 3228.00 |
... | ... | ... | ... |
Sales Manager は、Philip Chin の多額の売り上げがデータベースに入力されていないことに気づきました。Philip はコミッションの迅速な支払いを希望しているため、Sales Manager は 4 月 25 日の彼の漏れていた注文を入力します。
Sales Manager のウィンドウに次のコマンドを入力します。1 つの注文に多くの品目を含めることができるため、受注と品目は別のテーブルに入力されます。品目を追加する前に、売り上げ注文にエントリを作成します。参照整合性を維持するために、データベース・サーバは注文がすでに存在する場合にかぎり、トランザクションが品目を注文に追加することを許可します。
INSERT into SalesOrders VALUES ( 2653, 174, '2001-04-22', 'r1', 'Central', 129); INSERT into SalesOrderItems VALUES ( 2653, 1, 601, 100, '2001-04-25' ); COMMIT; |
Accountant は、Sales Manager が新しい注文を追加したことを知りません。新しい注文がもっと前に入力された場合は、Philip Chin の 4 月の売り上げ計算に含まれます。
Accountant のウィンドウで、4 月の売り上げ合計を再計算します。同じコマンドを使用しますが、Philip Chin の 4 月の売り上げ額が $4560.00 ドルに変更されていることに注意してください。
EmployeeID | GivenName | Surname | April sales |
---|---|---|---|
129 | Philip | Chin | 4560.00 |
195 | Marc | Dill | 2568.00 |
299 | Rollin | Overbey | 5760.00 |
467 | James | Klobucher | 3228.00 |
... | ... | ... | ... |
ここで、Accountant は 4 月の注文すべてにマークを付けて、コミッションが支払い済みであることを示します。Sales Manager が入力したばかりの注文が 2 度目の検索で見つかりましたが、たとえ Philip の 4 月の売り上げ合計に含まれていなかったとしても、支払い済みのマークが付いています。
独立性レベル 3 では、データベース・サーバは対挿入ロックを設定し、検索または選択条件に合うローを他のトランザクションが追加できないようにします。
Sales Manager のウィンドウで、次の文を実行して新しい注文を削除します。
DELETE FROM SalesOrderItems WHERE ID = 2653; DELETE FROM SalesOrders WHERE ID = 2653; COMMIT; |
Accountant のウィンドウで、次の 2 つの文を実行します。
ROLLBACK; SET TEMPORARY OPTION isolation_level = 3; |
Accountant のウィンドウで、前と同じクエリを実行します。
SELECT EmployeeID, GivenName, Surname, SUM(SalesOrderItems.Quantity * UnitPrice) AS "April sales" FROM Employees KEY JOIN SalesOrders KEY JOIN SalesOrderItems KEY JOIN Products WHERE '2001-04-01' <= OrderDate AND OrderDate < '2001-05-01' GROUP BY EmployeeID, GivenName, Surname; |
独立性レベル 3 を設定したため、データベース・サーバは自動的に対挿入ロックを設定し、Accountant がトランザクションを終了するまで、Sales Manager が 4 月の注文品目を挿入できないようにします。
Sales Manager のウィンドウに戻ります。再度 Philip Chin の漏れていた注文を入力します。
INSERT INTO SalesOrders VALUES ( 2653, 174, '2001-04-22', 'r1','Central', 129); |
Sales Manager のウィンドウは応答を停止し、操作は完了しません。ツールバーの [SQL 文の中断] ボタン (または [SQL] - [中断]) をクリックしてこのエントリを一時停止します。
Sales Manager は 4 月の注文を入力できませんが、5 月分には入力できると考えます。
コマンドの日付を 5 月 5 日に変更し、再実行します。
INSERT INTO SalesOrders VALUES ( 2653, 174, '2001-05-05', 'r1', 'Central', 129); |
Sales Manager のウィンドウは再度応答を停止します。ツールバーの [SQL 文の中断] ボタン (または [SQL] - [中断]) をクリックしてこのエントリを一時停止します。データベース・サーバは項目の挿入を防止するために必要な箇所にしかロックを設定しませんが、これらのロックは他の多数のトランザクションを妨げる可能性があります。
データベース・サーバはテーブル・インデックスにロックをかけます。たとえば、インデックスに幻ロックを設定し、インデックスの直前に新しいローを追加できないようにします。ただし、適切なインデックスが存在しない場合、テーブルのすべてのローにロックをかける必要があります。
ある状況では、対挿入ロックによって特定テーブルへの挿入のみをブロックできます。
Sales Manager は、注文 2651 に 2 番目の品目を追加したいと考えています。次のコマンドを使用します。
INSERT INTO SalesOrderItems VALUES ( 2651, 2, 302, 4, '2001-05-22' ); |
Sales Manager のウィンドウは応答を停止します。ツールバーの [SQL 文の中断] ボタン (または [SQL] - [中断]) をクリックしてこのエントリを一時停止します。
変更を取り消して SQL Anywhere サンプル・データベースの変更を防止し、このチュートリアルを終了します。Sales Manager のウィンドウに次のコマンドを入力します。
ROLLBACK; |
Accountant のウィンドウに同じコマンドを入力します。
ROLLBACK; |
両方のウィンドウを閉じます。
Copyright © 2009, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.1 |