SQLite,ロック(トランザクション・コミット)について

スポンサーリンク

鍛錬 178

SQLite,ロック(トランザクション・コミット)について

SQLite3 の、ロック(トランザクション・コミット)についてです。

ロックの種類

以下は、ロックの種類です。

名称 状態 読込 書込
UNLOCKED データベースへのアクセスが無く、ロックされていない。
SHARED 書き込みのロック中。 ×
RESERVED データの書き込み予約中。 ×
EXCLUSIVE EXCLUSIVEを含め、他のロックをかけることが不可能。 × ×
PENDING SHAREDが解除された後すぐに、
EXCLUSIVEロックをかけるために待機中。
×

トランザクションを開始

トランザクションを開始するには、begin transaction を使用します。

使用方法は、以下に示す通りです。
オプションは、DEFERRED・IMMEDIATE・EXCLUSIVE の 3 種類があり、ロックを開始するタイミングを設定します。

begin オプション transaction;

以下は、オプションについての説明です。

DEFERRED

ロック開始条件
最初にデータベースへアクセスした時点
状況 ロック種別 他のユーザーが持つ権限
最初のアクセスが「読み込み」の場合 SHARED 読込:○ 書込:×
最初のアクセスが「書き込み」の場合 RESERVED 読込:○ 書込:×

 
IMMEDIATE

ロック開始条件
BEGINコマンドを実行した時点
ロック種別 他のユーザーが持つ権限
RESERVED 読込:○ 書込:×

 
EXCLUSIVE:

ロック開始条件
BEGINコマンドを実行した時点
ロック種別 他のユーザーが持つ権限
EXCLUSIVE 読込:× 書込:×

トランザクションを終了(コミット)

トランザクションを終了するには、commit transaction を使用します。

使用方法は、以下に示す通りです。

commit transaction;

実際に挙動を確認する

実際に、トランザクションとコミットの挙動を確認します。

確認の際、端末を 2 つ起動して確認するため、分かりやすいようにプロンプト表示を変更しています。
プロンプト表示の変更については、別の記事にて紹介しています。

https://iwakurabit.com/training-sqlite3-change-prompt/

オプション DEFERRED の場合

  1. (端末A) プロンプト表示を A> に変更。
sqlite> 
sqlite> 
sqlite> 
sqlite> .prompt A>
A>
A>
A>
  1. (端末B) プロンプト表示を B> に変更。
sqlite> 
sqlite> 
sqlite> 
sqlite> .prompt B>
B>
B>
B>
  1. (端末A) 確認のため、テーブル fruits を表示。
A>
A>select * from fruits;
id   fruits_name   price 
---  ------------  ------
1    apple         300   
2    orange        250   
3    grape         500   
4    banana        350   
5    peach         700
  1. (端末A) オプションに DEFERRED を設定して、トランザクション開始。
A>
A>begin DEFERRED transaction;
  1. (端末B) 書き込みを実行。その後、テーブルを表示。
B>
B>insert into fruits values(6, 'strawberry', '550');
B>select * from fruits;
id   fruits_name   price 
---  ------------  ------
1    apple         300   
2    orange        250   
3    grape         500   
4    banana        350   
5    peach         700   
6    strawberry    550
  1. (端末A) 読み込み。(この時点で、ロックが開始)
A>
A>select * from fruits;
id   fruits_name   price 
---  ------------  ------
1    apple         300   
2    orange        250   
3    grape         500   
4    banana        350   
5    peach         700   
6    strawberry    550
  1. (端末B) 書き込みを実行。(ロックがかかっているため、エラーとなる)
B>
B>insert into fruits values(7, 'cherry', '600');
Error: database is locked
  1. (端末B) 読み込みを実行。(読み込みは可能)
sqlite> 
sqlite> select * from fruits;
id   fruits_name   price 
---  ------------  ------
1    apple         300   
2    orange        250   
3    grape         500   
4    banana        350   
5    peach         700   
6    strawberry    550
  1. (端末A) トランザクションをコミット。(この時点で、ロックが解除)
sqlite> 
sqlite> commit transaction;
  1. (端末B) 書き込みを実行。その後、テーブルを表示。
sqlite> 
sqlite> insert into fruits values(7, 'cherry', '600');
sqlite> select * from fruits;
id   fruits_name   price 
---  ------------  ------
1    apple         300   
2    orange        250   
3    grape         500   
4    banana        350   
5    peach         700   
6    strawberry    550   
7    cherry        600

 
オプション IMMEDIATE の場合

  1. (端末A) プロンプト表示を A> に変更。
sqlite> 
sqlite> 
sqlite> 
sqlite> .prompt A>
A>
A>
A>
  1. (端末B) プロンプト表示を B> に変更。
sqlite> 
sqlite> 
sqlite> 
sqlite> .prompt B>
B>
B>
B>
  1. (端末A) 確認のため、テーブル fruits を表示。
A>
A>select * from fruits;
id   fruits_name   price 
---  ------------  ------
1    apple         300   
2    orange        250   
3    grape         500   
4    banana        350   
5    peach         700
  1. (端末A) オプションに IMMEDIATE を設定して、トランザクション開始。(この時点で、ロックが開始)
sqlite> 
sqlite> begin IMMEDIATE transaction;
  1. (端末B) 書き込みを実行。(ロックがかかっているため、エラーとなる)
sqlite> 
sqlite> insert into fruits values(6, 'strawberry', '550');
Error: database is locked
  1. (端末B) 読み込みを実行。(読み込みは可能)
sqlite> 
sqlite> select * from fruits;
id   fruits_name   price 
---  ------------  ------
1    apple         300   
2    orange        250   
3    grape         500   
4    banana        350   
5    peach         700
  1. (端末A) トランザクションをコミット。(この時点で、ロックが解除)
sqlite> 
sqlite> commit transaction;
  1. (端末B) 書き込みを実行。その後、テーブルを表示。
sqlite> 
sqlite> insert into fruits values(6, 'strawberry', '550');
sqlite> select * from fruits;
id   fruits_name   price 
---  ------------  ------
1    apple         300   
2    orange        250   
3    grape         500   
4    banana        350   
5    peach         700   
6    strawberry    550

 
オプション EXCLUSIVE の場合

  1. (端末A) プロンプト表示を A> に変更。
sqlite> 
sqlite> 
sqlite> 
sqlite> .prompt A>
A>
A>
A>
  1. (端末B) プロンプト表示を B> に変更。
sqlite> 
sqlite> 
sqlite> 
sqlite> .prompt B>
B>
B>
B>
  1. (端末A) 確認のため、テーブル fruits を表示。
A>
A>select * from fruits;
id   fruits_name   price 
---  ------------  ------
1    apple         300   
2    orange        250   
3    grape         500   
4    banana        350   
5    peach         700
  1. (端末A) オプションに EXCLUSIVE を設定して、トランザクション開始。(この時点で、ロックが開始)
sqlite> 
sqlite> begin EXCLUSIVE transaction;
  1. (端末B) 書き込みを実行。(ロックがかかっているため、エラーとなる)
sqlite> 
sqlite> insert into fruits values(6, 'strawberry', '550');
Error: database is locked
  1. (端末B) 読み込みを実行。(ロックがかかっているため、エラーとなる)
sqlite> 
sqlite> select * from fruits;
Error: database is locked
  1. (端末A) トランザクションをコミット。(この時点で、ロックが解除)
sqlite> 
sqlite> commit transaction;
  1. (端末B) 書き込みを実行。その後、テーブルを表示。
sqlite> 
sqlite> insert into fruits values(6, 'strawberry', '550');
sqlite> select * from fruits;
id   fruits_name   price 
---  ------------  ------
1    apple         300   
2    orange        250   
3    grape         500   
4    banana        350   
5    peach         700   
6    strawberry    550
タイトルとURLをコピーしました