このブログの最初の部分では、MySQLGaleraClusterの新しいストリーミングレプリケーション機能の概要を説明しました。このブログでは、それを有効にする方法と結果を確認する方法を紹介します。
アプリケーション/クライアントと対話する特定のトランザクションに対して、セッションレベルでストリーミングレプリケーションを有効にすることを強くお勧めします。
前のブログで述べたように、Galeraはその書き込みセットをMySQLデータベースのwsrep_streaming_logテーブルに記録します。これは、特にロールバックが必要な場合に、パフォーマンスのボトルネックを引き起こす可能性があります。これは、ストリーミングレプリケーションを使用できないことを意味するのではなく、ストリーミングレプリケーションを使用するときにアプリケーションクライアントを効率的に設計して、パフォーマンスを向上させる必要があることを意味します。それでも、大規模なトランザクションを処理および削減するには、ストリーミングレプリケーションを使用するのが最適です。
ストリーミングレプリケーションを有効にするには、レプリケーションユニットとトランザクションフラグメントの形成に使用するユニット数を定義する必要があります。 wsrep_trx_fragment_unitとwsrep_trx_fragment_sizeの2つのパラメーターがこれらの変数を制御します。
以下は、次の2つのパラメータを設定する方法の例です。
SET SESSION wsrep_trx_fragment_unit='statements';
SET SESSION wsrep_trx_fragment_size=3;
この例では、フラグメントは3つのステートメントに設定されています。トランザクションからの3つのステートメントごとに、ノードはフラグメントを生成、複製、および認証します。
フラグメントを形成するときに、いくつかの複製ユニットから選択できます:
- バイト -これはフラグメントサイズをバイト単位で定義します。
- 行 -これは、フラグメントサイズをフラグメントが更新する行数として定義します。
- ステートメント -これは、フラグメントサイズをフラグメント内のステートメントの数として定義します。
Mariadb 10.4での大規模なトランザクションの処理に関する他のブログで説明したように、この基準に基づいて有効にした場合にストリーミングレプリケーションがどのように実行されるかを実行およびテストしました...
- ベースライン、グローバルwsrep_trx_fragment_size=0を設定;
- set global wsrep_trx_fragment_unit ='rows';グローバルwsrep_trx_fragment_size=1を設定します;
- set global wsrep_trx_fragment_unit ='statements';グローバルwsrep_trx_fragment_size=1を設定します;
- set global wsrep_trx_fragment_unit ='statements';グローバルwsrep_trx_fragment_size=5を設定します;
Transactions: 82.91 per sec., queries: 1658.27 per sec. (100%)
Transactions: 54.72 per sec., queries: 1094.43 per sec. (66%)
Transactions: 54.76 per sec., queries: 1095.18 per sec. (66%)
Transactions: 70.93 per sec., queries: 1418.55 per sec. (86%)
この例では、Percona-XtraDB-Cluster_8.0.15.5-27dev.4.2_Linux.x86_64.ssl102.tar.gzを使用して、テストブランチから直接Percona XtraDBCluster8.0.15を使用しています。建てる。
次に、以下のホスト情報を使用して3ノードのGaleraクラスターを試しました。
testnode11 = 192.168.10.110
testnode12 = 192.168.10.120
testnode13 = 192.168.10.130
sysbenchデータベースからテーブルを事前入力し、非常に大きな行を削除しようとしました。
[email protected][sbtest]#> select count(*) from sbtest1;
+----------+
| count(*) |
+----------+
| 12608218 |
+----------+
1 row in set (25.55 sec)
最初は、ストリーミングレプリケーションなしで実行しています
[email protected][sbtest]#> select @@wsrep_trx_fragment_unit, @@wsrep_trx_fragment_size, @@innodb_lock_wait_timeout;
+---------------------------+---------------------------+----------------------------+
| @@wsrep_trx_fragment_unit | @@wsrep_trx_fragment_size | @@innodb_lock_wait_timeout |
+---------------------------+---------------------------+----------------------------+
| bytes | 0 | 50000 |
+---------------------------+---------------------------+----------------------------+
1 row in set (0.00 sec)
[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;
しかし、ロールバックを取得することになりました...
---TRANSACTION 648910, ACTIVE 573 sec rollback
mysql tables in use 1, locked 1
ROLLING BACK 164858 lock struct(s), heap size 18637008, 12199395 row lock(s), undo log entries 11961589
MySQL thread id 183, OS thread handle 140041167468288, query id 79286 localhost 127.0.0.1 root wsrep: replicating and certifying write set(-1)
delete from sbtest1 where id >= 2000000
ClusterControlダッシュボードを使用して、フロー制御の兆候の概要を収集します。トランザクションはコミット時までマスター(アクティブライター)ノードでのみ実行されるため、フロー制御のアクティビティの兆候はありません。
疑問に思われるかもしれませんが、ClusterControlの現在のバージョンはまだありませんGalera Cluster4を使用したPXC8.0を直接サポートしています(まだ実験段階です)。ただし、インポートを試みることはできますが、ダッシュボードを正しく機能させるには、微調整が必要です。
[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;
ERROR 1180 (HY000): Got error 5 - 'Transaction size exceed set threshold' during COMMIT
wsrep_max_ws_rowsまたはwsrep_max_ws_sizeに関係なく、
[email protected][sbtest]#> select @@global.wsrep_max_ws_rows, @@global.wsrep_max_ws_size/(1024*1024*1024);
+----------------------------+---------------------------------------------+
| @@global.wsrep_max_ws_rows | @@global.wsrep_max_ws_size/(1024*1024*1024) |
+----------------------------+---------------------------------------------+
| 0 | 2.0000 |
+----------------------------+---------------------------------------------+
1 row in set (0.00 sec)
この間、システムテーブルmysql.wsrep_streaming_logは空です。これは、ストリーミングレプリケーションが実行されていないか有効になっていないことを示します。
[email protected][sbtest]#> select count(*) from mysql.wsrep_streaming_log;
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row in set (0.01 sec)
[email protected][sbtest]#> select count(*) from mysql.wsrep_streaming_log;
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row in set (0.00 sec)
これは、他の2つのノード(testnode12とtestnode13)で検証されます。
では、ストリーミングレプリケーションで有効にしてみましょう
[email protected][sbtest]#> select @@wsrep_trx_fragment_unit, @@wsrep_trx_fragment_size, @@innodb_lock_wait_timeout;
+---------------------------+---------------------------+----------------------------+
| @@wsrep_trx_fragment_unit | @@wsrep_trx_fragment_size | @@innodb_lock_wait_timeout |
+---------------------------+---------------------------+----------------------------+
| bytes | 0 | 50000 |
+---------------------------+---------------------------+----------------------------+
1 row in set (0.00 sec)
[email protected][sbtest]#> set wsrep_trx_fragment_unit='rows'; set wsrep_trx_fragment_size=100;
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
[email protected][sbtest]#> select @@wsrep_trx_fragment_unit, @@wsrep_trx_fragment_size, @@innodb_lock_wait_timeout;
+---------------------------+---------------------------+----------------------------+
| @@wsrep_trx_fragment_unit | @@wsrep_trx_fragment_size | @@innodb_lock_wait_timeout |
+---------------------------+---------------------------+----------------------------+
| rows | 100 | 50000 |
+---------------------------+---------------------------+----------------------------+
1 row in set (0.00 sec)
Galeraクラスターストリーミングレプリケーションが有効になっている場合、何が期待できますか?
testnode11でクエリが実行された場合、
[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;
変数wsrep_trx_fragment_sizeの設定値に応じて、トランザクションを1つずつフラグメント化します。他のノードでこれを確認しましょう:
[email protected][sbtest]#> pager sed -n '/TRANSACTIONS/,/FILE I\/O/p'; show engine innodb status\G nopager; show global status like 'wsrep%flow%'; select count(*) from mysql.wsrep_streaming_log;
PAGER set to 'sed -n '/TRANSACTIONS/,/FILE I\/O/p''
TRANSACTIONS
------------
Trx id counter 567148
Purge done for trx's n:o < 566636 undo n:o < 0 state: running but idle
History list length 44
LIST OF TRANSACTIONS FOR EACH SESSION:
..
...
---TRANSACTION 421740651985200, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 553661, ACTIVE 190 sec
18393 lock struct(s), heap size 2089168, 1342600 row lock(s), undo log entries 1342600
MySQL thread id 898, OS thread handle 140266050008832, query id 216824 wsrep: applied write set (-1)
--------
FILE I/O
1 row in set (0.08 sec)
PAGER set to stdout
+----------------------------------+--------------+
| Variable_name | Value |
+----------------------------------+--------------+
| wsrep_flow_control_paused_ns | 211197844753 |
| wsrep_flow_control_paused | 0.133786 |
| wsrep_flow_control_sent | 633 |
| wsrep_flow_control_recv | 878 |
| wsrep_flow_control_interval | [ 173, 173 ] |
| wsrep_flow_control_interval_low | 173 |
| wsrep_flow_control_interval_high | 173 |
| wsrep_flow_control_status | OFF |
+----------------------------------+--------------+
8 rows in set (0.00 sec)
+----------+
| count(*) |
+----------+
| 13429 |
+----------+
1 row in set (0.04 sec)
[email protected][sbtest]#> pager sed -n '/TRANSACTIONS/,/FILE I\/O/p'; show engine innodb status\G nopager; show global status like 'wsrep%flow%'; select count(*) from mysql.wsrep_streaming_log;
PAGER set to 'sed -n '/TRANSACTIONS/,/FILE I\/O/p''
TRANSACTIONS
------------
Trx id counter 568523
Purge done for trx's n:o < 567824 undo n:o < 0 state: running but idle
History list length 23
LIST OF TRANSACTIONS FOR EACH SESSION:
..
...
---TRANSACTION 552701, ACTIVE 216 sec
21587 lock struct(s), heap size 2449616, 1575700 row lock(s), undo log entries 1575700
MySQL thread id 936, OS thread handle 140188019226368, query id 600980 wsrep: applied write set (-1)
--------
FILE I/O
1 row in set (0.28 sec)
PAGER set to stdout
+----------------------------------+--------------+
| Variable_name | Value |
+----------------------------------+--------------+
| wsrep_flow_control_paused_ns | 210755642443 |
| wsrep_flow_control_paused | 0.0231273 |
| wsrep_flow_control_sent | 1653 |
| wsrep_flow_control_recv | 3857 |
| wsrep_flow_control_interval | [ 173, 173 ] |
| wsrep_flow_control_interval_low | 173 |
| wsrep_flow_control_interval_high | 173 |
| wsrep_flow_control_status | OFF |
+----------------------------------+--------------+
8 rows in set (0.01 sec)
+----------+
| count(*) |
+----------+
| 15758 |
+----------+
1 row in set (0.03 sec)
注目すべきことに、フロー制御が開始されました!
また、送受信されたWSREPキューもキックされています:
> ホストtestnode12(192.168.10.120) ホストtestnode13(192.168.10.130)では、結果について詳しく説明します。 mysql.wsrep_streaming_logテーブルから
[email protected][sbtest]#> pager sed -n '/TRANSACTIONS/,/FILE I\/O/p'|tail -8; show engine innodb status\G nopager;
PAGER set to 'sed -n '/TRANSACTIONS/,/FILE I\/O/p'|tail -8'
MySQL thread id 134822, OS thread handle 140041167468288, query id 0 System lock
---TRANSACTION 649008, ACTIVE 481 sec
mysql tables in use 1, locked 1
53104 lock struct(s), heap size 6004944, 3929602 row lock(s), undo log entries 3876500
MySQL thread id 183, OS thread handle 140041167468288, query id 105367 localhost 127.0.0.1 root updating
delete from sbtest1 where id >= 2000000
--------
FILE I/O
1 row in set (0.01 sec)
次に、結果を取得します
[email protected][sbtest]#> select count(*) from mysql.wsrep_streaming_log;
+----------+
| count(*) |
+----------+
| 38899 |
+----------+
1 row in set (0.40 sec)
[email protected][sbtest]#> select 3876500/38899.0;
+-----------------+
| 3876500/38899.0 |
+-----------------+
| 99.6555 |
+-----------------+
1 row in set (0.03 sec)
SHOW ENGINE INNODB STATUS \ Gの結果から取り消しログエントリを取得し、mysql.wsrep_streaming_logレコードの総数を除算します。以前に設定したように、wsrep_trx_fragment_size =100を定義しました。結果には、複製されたログの合計が現在Galeraによって処理されている量が表示されます。
フラグメントはトランザクションと見なされ、クラスター内の残りのノードに渡され、フラグメント化されたトランザクションを認証してから、書き込みセットを適用します。つまり、大規模なトランザクションが認証または優先順位付けされると、デッドロックが発生する可能性のあるすべての着信接続は、トランザクションが終了するまで待機する必要があります。
さて、巨大なテーブルを削除するという評決?
[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;
Query OK, 12034538 rows affected (30 min 36.96 sec)
他のノードではどのように見えますか? testnode12では、
[email protected][sbtest]#> pager sed -n '/TRANSACTIONS/,/FILE I\/O/p'|tail -8; show engine innodb status\G nopager; show global status like 'wsrep%flow%'; select count(*) from mysql.wsrep_streaming_log;
PAGER set to 'sed -n '/TRANSACTIONS/,/FILE I\/O/p'|tail -8'
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 421740651985200, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 553661, ACTIVE (PREPARED) 2050 sec
165631 lock struct(s), heap size 18735312, 12154883 row lock(s), undo log entries 12154883
MySQL thread id 898, OS thread handle 140266050008832, query id 341835 wsrep: preparing to commit write set(215510)
--------
FILE I/O
1 row in set (0.46 sec)
PAGER set to stdout
+----------------------------------+--------------+
| Variable_name | Value |
+----------------------------------+--------------+
| wsrep_flow_control_paused_ns | 290832524304 |
| wsrep_flow_control_paused | 0 |
| wsrep_flow_control_sent | 0 |
| wsrep_flow_control_recv | 0 |
| wsrep_flow_control_interval | [ 173, 173 ] |
| wsrep_flow_control_interval_low | 173 |
| wsrep_flow_control_interval_high | 173 |
| wsrep_flow_control_status | OFF |
+----------------------------------+--------------+
8 rows in set (0.53 sec)
+----------+
| count(*) |
+----------+
| 120345 |
+----------+
1 row in set (0.88 sec)
合計120345フラグメントで停止し、最後にキャプチャされた元に戻すログエントリで再度計算を行うと(元に戻すログはマスターからも同じです)、
[email protected][sbtest]#> select 12154883/120345.0; +-------------------+
| 12154883/120345.0 |
+-------------------+
| 101.0003 |
+-------------------+
1 row in set (0.00 sec)
つまり、合計で 120345 削除するためにフラグメント化されているトランザクション12034538 行。
ストリームレプリケーションの使用または有効化が完了したら、それを無効にすることを忘れないでください。ストリームレプリケーションは常に巨大なトランザクションをログに記録し、クラスターに多くのパフォーマンスオーバーヘッドを追加します。無効にするには、実行するだけです
[email protected][sbtest]#> set wsrep_trx_fragment_size=0;
Query OK, 0 rows affected (0.04 sec)
ストリーミングレプリケーションを有効にすると、フラグメントサイズの大きさと、選択する必要のある単位(バイト、行、ステートメント)を識別できることが重要です。
セッションレベルで実行する必要があること、そしてもちろん、ストリーミングレプリケーションのみを使用する必要がある場合を特定することも非常に重要です。
これらのテストの実行中に、ストリーミングレプリケーションが有効になっている巨大なテーブルに多数の行を削除すると、ディスク使用率とCPU使用率のピークが著しく高くなります。 RAMはより安定していましたが、これは、実行したステートメントがメモリの競合ではないことが原因である可能性があります。
ストリーミングレプリケーションは、大きなレコードを処理するときにパフォーマンスのボトルネックを引き起こす可能性があると言っても過言ではないため、適切な判断と注意を払って使用する必要があります。
最後に、ストリーミングレプリケーションを使用している場合は、不要な問題を回避するために、現在のセッションで一度実行すると、これを常に無効にすることを忘れないでください。