「プログラミングのお勉強Blog/2005年09月05日/Firebirdにおける行ロックを考える」の編集履歴(バックアップ)一覧はこちら
「プログラミングのお勉強Blog/2005年09月05日/Firebirdにおける行ロックを考える」(2005/09/05 (月) 00:59:46) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
#blognavi
とりあえず、Firebirdは動くようになり、管理ツールも使えるようになった。というところで、気になったのは、行ロックの制御がどれくらいできるのかということだった。
DBで行ロックの制御がちゃんとできないとプログラム側での労力が大きい。
SQL Server でも ORACLEでも変わらないと思っている人も結構いるようだが、やはりDBの機能差は上位アプリを開発する上ではかなり影響する。ORACLEの機能を有効に使うことでだいぶコードは減るものだ。
という点の一つ大きいところがこのロック制御に他ならない。
** Firebirdへの接続
SQL> connect "/opt/firebird/examples/employee.fdb"
CON> user 'sysdba' password 'welcome';
Database: "/opt/firebird/examples/employee.fdb", User: sysdba
SQL> show table customer;
CUST_NO (CUSTNO) INTEGER Not Null
CHECK (VALUE > 1000)
CUSTOMER VARCHAR(25) Not Null
CONTACT_FIRST (FIRSTNAME) VARCHAR(15) Nullable
CONTACT_LAST (LASTNAME) VARCHAR(20) Nullable
PHONE_NO (PHONENUMBER) VARCHAR(20) Nullable
ADDRESS_LINE1 (ADDRESSLINE) VARCHAR(30) Nullable
ADDRESS_LINE2 (ADDRESSLINE) VARCHAR(30) Nullable
CITY VARCHAR(25) Nullable
STATE_PROVINCE VARCHAR(15) Nullable
COUNTRY (COUNTRYNAME) VARCHAR(15) Nullable
POSTAL_CODE VARCHAR(12) Nullable
ON_HOLD CHAR(1) Nullable DEFAULT NULL
CONSTRAINT INTEG_61:
Foreign key (COUNTRY) References COUNTRY (COUNTRY)
CONSTRAINT INTEG_60:
Primary key (CUST_NO)
CONSTRAINT INTEG_59:
CHECK (on_hold IS NULL OR on_hold = '*')
Triggers on Table CUSTOMER:
SET_CUST_NO, Sequence: 0, Type: BEFORE INSERT, Active
SQL> select cust_no,customer from customer where cust_no=1001;
CUST_NO CUSTOMER
============ =========================
1001 Signature Design
SQL>
** ロックを発生させる。
TELNETでA,B2箇所からfirebirdに接続する。
Aで実行。
SQL> select cust_no,customer from customer where cust_no=1001 for update;
CUST_NO CUSTOMER
============ =========================
1001 Signature Design
SQL>
Bで実行。ここでロックを発生させる。
SQL> select cust_no,customer from customer where cust_no=1001 for update;
CUST_NO CUSTOMER
============ =========================
1001 Signature Design
SQL>
と、どちらもSELECTできてしまい、ロックがかからなかった。
次にUPDATE句で実行する。
Aで実行。
SQL> update customer set contact_last='TEST' where cust_no=1001;
SQL>
Bで実行。
SQL> update customer set contact_last='TEST' where cust_no=1001;
これでBではロックがかかっている為、WAITになる。
次に、SELECT FOR UPDATE句でのロックを再度確認。
「with lock」をつけることでロックをつけられた。
SQL> select cust_no,customer from customer where cust_no=1001 for update with lock;
CUST_NO CUSTOMER
============ =========================
1001 Signature Design
SQL>
これをBでも実行するとロックのためのWAITになる。
またBで1002を検索すると、ロックを取得できる。
SQL> select cust_no,customer from customer where cust_no=1002 for update with lock;
CUST_NO CUSTOMER
============ =========================
1002 Dallas Technologies
SQL>
これでUPDATE及びSELECT FOR UPDATEで行ロックがちゃんとかかる。
*** NO WAITのテスト。
次に、NO WAITのテスト。プログラムの中ではロック解除を待たずにエラーで返してくれる方が良い場合もある。ということで、ロックしているデータの場合は即エラーで返す設定を確認する。
Aで上記と同様でロックをかける。
Bで下記を実行。
SQL> set transaction no wait;
これでロック時にはWAITをかけずにエラーする。
SQL> select cust_no,customer from customer where cust_no=1001 for update with lock;
CUST_NO CUSTOMER
============ =========================
Statement failed, SQLCODE = -901
lock conflict on no wait transaction
-deadlock
-update conflicts with concurrent update
SQL>
***デッドロックチェック
次にはデッドロックの場合どのようなエラーを返すか確認する。
Aで下記を実行。
SQL> set transaction wait;
SQL> select cust_no,customer from customer where cust_no=1001 for update with lock;
CUST_NO CUSTOMER
============ =========================
1001 Signature Design
このとき、Bで下記を実行する。
SQL> set transaction wait;
SQL> select cust_no,customer from customer where cust_no=1002 for update with lock;
CUST_NO CUSTOMER
============ =========================
1002 Dallas Technologies
これでAがCUST_NO=1001、BがCUST_NO=1002をそれぞれロックしている。
このときに、Bで下記を実行。
SQL> select cust_no,customer from customer where cust_no=1001 for update with lock;
これでBはロック待ち状態に入る。
Aでデッドロックを発生させる。
SQL> select cust_no,customer from customer where cust_no=1002 for update with lock;
これでデッドロック完成。すると1,2秒後に下記のエラーが発生。
CUST_NO CUSTOMER
============ =========================
Statement failed, SQLCODE = -913
deadlock
-deadlock
-update conflicts with concurrent update
上記でロック系の確認を一通りした。
フリーのDBということでロックについてはあまり期待していなかったが結構実用に耐えうるものと思えた。
#right{
カテゴリ: [[[Firebird>プログラミングのお勉強Blog/カテゴリ/Firebird]]] - &trackback() - 2005年09月05日 00:25:25
}
#comment(nostyle,nsize8,size30)
#blognavi
#blognavi
とりあえず、Firebirdは動くようになり、管理ツールも使えるようになった。というところで、気になったのは、行ロックの制御がどれくらいできるのかということだった。
DBで行ロックの制御がちゃんとできないとプログラム側での労力が大きい。
SQL Server でも ORACLEでも変わらないと思っている人も結構いるようだが、やはりDBの機能差は上位アプリを開発する上ではかなり影響する。ORACLEの機能を有効に使うことでだいぶコードは減るものだ。
という点の一つ大きいところがこのロック制御に他ならない。
** Firebirdへの接続
DBに接続。
SQL> connect "/opt/firebird/examples/employee.fdb"
CON> user 'sysdba' password 'welcome';
Database: "/opt/firebird/examples/employee.fdb", User: sysdba
CUSTOMER表の構成を見る。
SQL> show table customer;
CUST_NO (CUSTNO) INTEGER Not Null
CHECK (VALUE > 1000)
CUSTOMER VARCHAR(25) Not Null
CONTACT_FIRST (FIRSTNAME) VARCHAR(15) Nullable
CONTACT_LAST (LASTNAME) VARCHAR(20) Nullable
PHONE_NO (PHONENUMBER) VARCHAR(20) Nullable
ADDRESS_LINE1 (ADDRESSLINE) VARCHAR(30) Nullable
ADDRESS_LINE2 (ADDRESSLINE) VARCHAR(30) Nullable
CITY VARCHAR(25) Nullable
STATE_PROVINCE VARCHAR(15) Nullable
COUNTRY (COUNTRYNAME) VARCHAR(15) Nullable
POSTAL_CODE VARCHAR(12) Nullable
ON_HOLD CHAR(1) Nullable DEFAULT NULL
CONSTRAINT INTEG_61:
Foreign key (COUNTRY) References COUNTRY (COUNTRY)
CONSTRAINT INTEG_60:
Primary key (CUST_NO)
CONSTRAINT INTEG_59:
CHECK (on_hold IS NULL OR on_hold = '*')
Triggers on Table CUSTOMER:
SET_CUST_NO, Sequence: 0, Type: BEFORE INSERT, Active
CUSTOMER表を検索してみる。
SQL> select cust_no,customer from customer where cust_no=1001;
CUST_NO CUSTOMER
============ =========================
1001 Signature Design
SQL>
** ロックを発生させる。
TELNETでA,B2箇所からfirebirdに接続する。
Aで実行。
SQL> select cust_no,customer from customer where cust_no=1001 for update;
CUST_NO CUSTOMER
============ =========================
1001 Signature Design
SQL>
Bで実行。ここでロックを発生させる。
SQL> select cust_no,customer from customer where cust_no=1001 for update;
CUST_NO CUSTOMER
============ =========================
1001 Signature Design
SQL>
と、どちらもSELECTできてしまい、ロックがかからなかった。
次にUPDATE句で実行する。
Aで実行。
SQL> update customer set contact_last='TEST' where cust_no=1001;
SQL>
Bで実行。
SQL> update customer set contact_last='TEST' where cust_no=1001;
これでBではロックがかかっている為、WAITになる。
次に、SELECT FOR UPDATE句でのロックを再度確認。
「with lock」をつけることでロックをつけられた。
SQL> select cust_no,customer from customer where cust_no=1001 for update with lock;
CUST_NO CUSTOMER
============ =========================
1001 Signature Design
SQL>
これをBでも実行するとロックのためのWAITになる。
またBで1002を検索すると、ロックを取得できる。
SQL> select cust_no,customer from customer where cust_no=1002 for update with lock;
CUST_NO CUSTOMER
============ =========================
1002 Dallas Technologies
SQL>
これでUPDATE及びSELECT FOR UPDATEで行ロックがちゃんとかかる。
*** NO WAITのテスト。
次に、NO WAITのテスト。プログラムの中ではロック解除を待たずにエラーで返してくれる方が良い場合もある。ということで、ロックしているデータの場合は即エラーで返す設定を確認する。
Aで上記と同様でロックをかける。
Bで下記を実行。
SQL> set transaction no wait;
これでロック時にはWAITをかけずにエラーする。
SQL> select cust_no,customer from customer where cust_no=1001 for update with lock;
CUST_NO CUSTOMER
============ =========================
Statement failed, SQLCODE = -901
lock conflict on no wait transaction
-deadlock
-update conflicts with concurrent update
SQL>
***デッドロックチェック
次にはデッドロックの場合どのようなエラーを返すか確認する。
Aで下記を実行。
SQL> set transaction wait;
SQL> select cust_no,customer from customer where cust_no=1001 for update with lock;
CUST_NO CUSTOMER
============ =========================
1001 Signature Design
このとき、Bで下記を実行する。
SQL> set transaction wait;
SQL> select cust_no,customer from customer where cust_no=1002 for update with lock;
CUST_NO CUSTOMER
============ =========================
1002 Dallas Technologies
これでAがCUST_NO=1001、BがCUST_NO=1002をそれぞれロックしている。
このときに、Bで下記を実行。
SQL> select cust_no,customer from customer where cust_no=1001 for update with lock;
これでBはロック待ち状態に入る。
Aでデッドロックを発生させる。
SQL> select cust_no,customer from customer where cust_no=1002 for update with lock;
これでデッドロック完成。すると1,2秒後に下記のエラーが発生。
CUST_NO CUSTOMER
============ =========================
Statement failed, SQLCODE = -913
deadlock
-deadlock
-update conflicts with concurrent update
上記でロック系の確認を一通りした。
フリーのDBということでロックについてはあまり期待していなかったが結構実用に耐えうるものと思えた。
#right{
カテゴリ: [[[Firebird>プログラミングのお勉強Blog/カテゴリ/Firebird]]] - &trackback() - 2005年09月05日 00:25:25
}
#comment(nostyle,nsize8,size30)
#blognavi
表示オプション
横に並べて表示:
変化行の前後のみ表示: