「プログラミングのお勉強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

表示オプション

横に並べて表示:
変化行の前後のみ表示:
記事メニュー
目安箱バナー