業務運用中、ユーザーはしばしばロック競合の問題に直面します。行ロックには、その持ち主と待機者という2つの重要な対象があり、これら2つの対象は行ロックのトラブルシューティングにおいて重要な役割を果たします。本質的に、行ロックの競合はすべてトランザクションによって引き起こされるものであり、この2つの対象はいずれもトランザクションに属しています。そのため、行ロックの問題を処理する際には、アクティブなトランザクションの監視も必要となります。
ロックを保持またはロックを要求しているトランザクションの関連情報の照会
ビューGV$OB_LOCKSには、現在のユーザーが各テーブルで保持または要求しているロックの状況が記録されています。このビューでは主に以下の3種類のロックが表示されます:
- テーブルロック(TM):テーブルまたはパーティション(Tablet)上のロックです。通常、insert/update/deleteなどのDML操作によりパーティションレベルのテーブルロックが生成され、DDL操作によりテーブルレベルのテーブルロックが生成されます。
- 行ロック(TR):行を書き込む際にかかるロックです。
- トランザクションロック(TX):最も一般的なロックであり、通常、トランザクション内で書き込み操作が行われた場合にトランザクションロックが生成されると理解できます。
OceanBaseデータベースでは、トランザクションが行ロックを保持している場合、そのトランザクションは必ず自身のトランザクションロックを保持しています。
以下の方法で、ロックを保持またはロックを要求しているトランザクションの関連情報を確認できます。
システムテナント
システムテナントでは、以下のステートメントを使用して照会できます。
obclient> SELECT t.TENANT_ID, t.TRANS_ID, t.TYPE, t.ID1, t.ID2, t.LMODE, t.REQUEST, ROUND(t.CTIME / 1000000) CTIME_s, t.BLOCK FROM oceanbase.gv$ob_locks t WHERE t.BLOCK = 1 ORDER BY t.TRANS_ID;ユーザーテナント
MySQLモードのユーザーテナントでは、以下のステートメントを使用して照会できます。
obclient> SELECT t.TRANS_ID, t.TYPE, t.ID1, t.ID2, t.LMODE, t.REQUEST, ROUND(t.CTIME / 1000000) CTIME_s, t.BLOCK FROM oceanbase.gv$ob_locks t WHERE t.BLOCK = 1 ORDER BY t.TRANS_ID;Oracleモードのユーザーテナントでは、以下のステートメントを使用して照会できます。
obclient> SELECT t.TRANS_ID, t.TYPE, t.ID1, t.ID2, t.LMODE, t.REQUEST, ROUND(t.CTIME / 1000000) CTIME_s, t.BLOCK FROM SYS.gv$ob_locks t WHERE t.BLOCK = 1 ORDER BY t.TRANS_ID;
例えば、システムテナントの照会結果は次のとおりです:
+-----------+----------+------+----------+--------------------------------+-------+---------+---------+-------+
| TENANT_ID | TRANS_ID | TYPE | ID1 | ID2 | LMODE | REQUEST | CTIME_s | BLOCK |
+-----------+----------+------+----------+--------------------------------+-------+---------+---------+-------+
| 1002 | 23723243 | TR | 200051 | 23723237-{"BIGINT UNSIGNED":1} | NONE | X | 20 | 1 |
| 1002 | 23723243 | TX | 23723237 | NULL | NONE | X | 20 | 1 |
+-----------+----------+------+----------+--------------------------------+-------+---------+---------+-------+
2 rows in set
最初の結果行から、現在1つの行ロック(TR)情報が存在し、ロックを要求しているトランザクションのID(フィールドTRANS_ID)は23723243、ロック対象のtablet_id(フィールドID1)は200051であることがわかります。また、ロックされている行の情報(フィールドID2)は23723237-{"BIGINT UNSIGNED":1}であり、ロック待機時間は20秒です。
2番目の結果行から、現在1つのトランザクションロック(TX)情報が存在し、ロックを要求しているトランザクションのID(フィールドTRANS_ID)は23723243、ロックを保持しているトランザクションのID(フィールドID1)は23723237であることがわかります。
trans_idに基づいてトランザクションに対応するsession_idを照会する
ビューGV$OB_TRANSACTION_PARTICIPANTSは、すべてのOBServerノード上でアクティブなトランザクションの参加者情報を記録しています。
ロックを保持またはロックを要求するトランザクションのtrans_idを取得した後、ビューGV$OB_TRANSACTION_PARTICIPANTSを照会することで、そのトランザクションに対応するsession_idを取得できます。
システムテナント
システムテナントでは、以下のステートメントを使用して照会できます。
obclient> SELECT ROUND(now() - t.CTX_CREATE_TIME) RUNNING_TIME_s, t.TENANT_ID, t.SVR_IP, t.SVR_PORT, t.SESSION_ID, t.TX_TYPE, t.TX_ID, t.STATE, t.ACTION, t.CTX_CREATE_TIME, t.LAST_REQUEST_TIME FROM oceanbase.GV$OB_TRANSACTION_PARTICIPANTS t WHERE t.TX_ID IN (holdlock_trans_id, requestlock_trans_id);ユーザーテナント
MySQLモードのユーザーテナントでは、以下のステートメントを使用して照会できます。
obclient>SELECT ROUND(now() - t.CTX_CREATE_TIME) RUNNING_TIME_s, t.TENANT_ID, t.SVR_IP, t.SVR_PORT, t.SESSION_ID, t.TX_TYPE, t.TX_ID, t.STATE, t.ACTION, t.CTX_CREATE_TIME, t.LAST_REQUEST_TIME FROM oceanbase.GV$OB_TRANSACTION_PARTICIPANTS t WHERE t.TX_ID IN (holdlock_trans_id, requestlock_trans_id);Oracleモードのユーザーテナントでは、以下のステートメントを使用して照会できます。
obclient>SELECT ROUND(now() - t.CTX_CREATE_TIME) RUNNING_TIME_s, t.TENANT_ID, t.SVR_IP, t.SVR_PORT, t.SESSION_ID, t.TX_TYPE, t.TX_ID, t.STATE, t.ACTION, t.CTX_CREATE_TIME, t.LAST_REQUEST_TIME FROM SYS.GV$OB_TRANSACTION_PARTICIPANTS t WHERE t.TX_ID IN (holdlock_trans_id, requestlock_trans_id);
ステートメント内で:
running_time_s:トランザクション実行の合計時間。holdlock_trans_id:ロックを保持するトランザクションのID。requestlock_trans_id:ロックを要求するトランザクションのID。
ロックを保持するトランザクションに対応するsession_idを取得した後、kill session_idを使用して対応するトランザクションをロールバックできます。