CentOS7.3 MariaDB Galera Clusterの排他ロック

シェアする

データベースのクラスター環境の一つである「MariaDB Galera Cluster」ですが、まだまだ、発展途上なためか、いくつかの機能制限があるようで、構築した時から、ノード間のデッドロックは出そうというところを検証してみました。

他のサイト様で検証されていたものを参考にして、実機で確認しました。
結論から言えば、今回の新しいバージョン(MariaDB 10.2.6, Galera 25.3.20)でも、同じくデッドロックになりました。

参考URL
http://blog.amedama.jp/entry/2015/09/20/194617

検証したときの環境

今後、改善されていく事を予想(期待)して、今回の検証した環境を明記しておきます。
なお、検証環境自体は、こちらの記事で構築したものを使っています。

# cat /etc/centos-release <LF>
CentOS Linux release 7.3.1611 (Core)
# uname -r <LF>
3.10.0-514.16.1.el7.x86_64
# mysql -u root -prootpass -e "show variables like 'version';" <LF>
+---------------+----------------+
| Variable_name | Value          |
+---------------+----------------+
| version       | 10.2.6-MariaDB |
+---------------+----------------+
# mysql -u root -prootpass -e "show status like 'wsrep_provider_version';" <LF>
+------------------------+----------------+
| Variable_name          | Value          |
+------------------------+----------------+
| wsrep_provider_version | 25.3.20(r3703) |
+------------------------+----------------+

検証するための事前準備(ノード間の排他ロック)

検証確認は、1号機と2号機を利用しました。

・1号機での操作

テーブルを作成して、テスト用データを作成します。

# mysql -u root -p <LF>
Enter password: rootpass
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 14
Server version: 10.2.6-MariaDB MariaDB Server
 
Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
MariaDB [(none)]> prompt mariadb01>      <= 1号機の操作と判るように
PROMPT set to 'mariadb01> '
mariadb01> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| orangetakam        |    <= これを使う
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)
 
mariadb01> use orangetakam
Database changed
mariadb01> create table TBL_TEST ( ID INT, NAME VARCHAR(10) NOT NULL, PRIMARY KEY (ID) );
Query OK, 0 rows affected (0.90 sec)
 
mariadb01> insert into TBL_TEST ( ID, NAME ) values ( 1, 'takam');
Query OK, 1 row affected (0.40 sec)

・2号機での操作

# mysql -u root -p <LF>
Enter password: rootpass
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 14
Server version: 10.2.6-MariaDB MariaDB Server
 
Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
MariaDB [(none)]> prompt mariadb02>      <= 2号機の操作と判るように
PROMPT set to 'mariadb02> '
mariadb02> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| orangetakam        |    <= これを使う
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)
 
mariadb02> use orangetakam
Database changed

検証確認

「ある処理-1」と「ある処理-2」が同時に同じ行に対して排他ロックをかけて更新をしようとしたときの検証です。

(1) ある処理-1が1号機に対してアクセスし、更新を行なう為の行排他ロックをかける。(トラン1)
(2) ある処理-2が2号機に対してアクセスし、更新を行なう為の行排他ロックをかける。(トラン2)
(3) ある処理-1がデータに対して更新を行ない、コミットする。(トラン1)
(4) ある処理-2がデータに対して更新を行ない、コミットする。(トラン2)[但し、デッドロック]

上記の(1)から(4)までの操作を順番に実施する。

(1)の操作

 ある処理-1が1号機に対してアクセスし、更新を行なう為の行排他ロックをかけます。

mariadb01> begin;
Query OK, 0 rows affected (0.00 sec)
 
mariadb01> select * from TBL_TEST where NAME like 'takam' for update;
+----+-------+
| ID | NAME  |
+----+-------+
|  1 | takam |
+----+-------+
1 row in set (0.00 sec)

(2)の操作

ある処理-2が2号機に対してアクセスし、更新を行なう為の行排他ロックをかけます。
 ⇒ ある処理-1は1号機で行排他ロックをかけているが、2号機では効いていない。[待たされない]

mariadb02> begin;
Query OK, 0 rows affected (0.00 sec)
  
mariadb02> select * from TBL_TEST where NAME like 'takam' for update;
+----+-------+
| ID | NAME  |
+----+-------+
|  1 | takam |
+----+-------+
1 row in set (0.00 sec)

(3)の操作

ある処理-1がデータに対して更新を行ない、コミットします。

mariadb01> update TBL_TEST set NAME = 'orange' where NAME like 'takam';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
mariadb01> commit;
Query OK, 0 rows affected (0.43 sec)

(4)の操作

ある処理-2がデータに対して更新を行ない、コミットします。
 ⇒ 処理-1は1号機で排他ロックをかけ、更新してコミットまでしているが、2号機側では、その排他ロックが聞いていないので、更新をしてコミットの段階でデッドロックとなる。

mariadb02> update TBL_TEST set NAME = 'purple' where NAME like 'takam';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
mariadb02> commit;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction <= デッドロック

ということで、ノード間での排他ロックは効きません。

参考にしたURLのサイト様が言われるように、更新するノードは固定にする方法が良いと思います。
固定にするのは別記事にて。

なお、同じノード内であれば、排他ロックは効くようです。

検証するための事前準備(ノード内の排他ロック)

検証確認は、1号機で画面を2つ用意しました。

・画面1

$ mysql -u root -p <LF>
Enter password: rootpass
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 21
Server version: 10.2.6-MariaDB MariaDB Server
 
Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
MariaDB [(none)]> prompt mariadb01_1>
PROMPT set to 'mariadb01_1> '
mariadb01_1> use orangetakam
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
 
Database changed
mariadb01_1> select * from TBL_TEST;  <= 先ほどのものを利用
+----+--------+
| ID | NAME   |
+----+--------+
|  1 | orange |
+----+--------+
1 row in set (0.00 sec)

・画面2

$ mysql -u root -p <LF>
Enter password: rootpass
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 22
Server version: 10.2.6-MariaDB MariaDB Server
 
Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
MariaDB [(none)]> prompt mariadb01_2>
PROMPT set to 'mariadb01_2> '
mariadb01_2> use orangetakam
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
 
Database changed

検証確認

「処理-1」と「処理-2」が同時に同じ行に対して排他ロックをかけて更新をしようとしたときの検証です。

(1) ある処理-1が1号機に対してアクセスし、更新を行なう為の行排他ロックをかける。(トラン1)
(2) ある処理-2が1号機に対してアクセスし、更新を行なう為の行排他ロックをかけようとするが待たされる。(トラン2)
(3) ある処理-1がデータに対して更新を行ない、コミットする。(トラン1)
(4) ある処理-2がデータに対して更新を行なおうとするが、該当行はなくなっているため更新できない。(トラン2)

(1)の操作

ある処理-1が1号機に対してアクセスし、更新を行なう為の行排他ロックをかけます。

mariadb01_1> begin;
Query OK, 0 rows affected (0.00 sec)
 
mariadb01_1> select * from TBL_TEST where NAME like 'orange' for update;
+----+--------+
| ID | NAME   |
+----+--------+
|  1 | orange |
+----+--------+
1 row in set (0.00 sec)

(2)の操作

ある処理-2が1号機に対してアクセスし、更新を行なう為の行排他ロックをかけます。
 ⇒ 但し、対象となる行が排他ロックされているので待たされます。

mariadb01_2> begin;
Query OK, 0 rows affected (0.00 sec)

mariadb01_2> select * from TBL_TEST where NAME like 'orange' for update;
待たされる

(3)の操作

ある処理-1がデータに対して更新を行ない、コミットします。

mariadb01_1> update TBL_TEST set NAME = 'takam' where NAME like 'orange';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
mariadb01_1> commit;
Query OK, 0 rows affected (0.28 sec)

(4)の操作

ある処理-2が更新を行なう為の行排他ロックをかけようとするが、該当行はないため、目的の行の排他ロックはできない。
結果、コミットできないので、ロールバックしておく。

mariadb01_2> select * from TBL_TEST where NAME like 'orange' for update;
Empty set (19.86 sec)
 
mariadb01_2> rollback;
Query OK, 0 rows affected (0.00 sec)