重要
このページは英語版のページを機械翻訳しています。原文はこちらからご覧ください。

AS OF TIMESTAMP句を使用して履歴データを読み取る

このドキュメントでは、 AS OF TIMESTAMP句を使用して古い読み取り機能を実行し、TiDBの履歴データを読み取る方法について説明します。これには、履歴データを保存するための具体的な使用例と戦略が含まれます。

警告

現在、StaleReadをTiFlashと一緒に使用することはできません。 SQLクエリにAS OF TIMESTAMP句が含まれていて、TiDBがTiFlashレプリカからデータを読み取る可能性がある場合、 ERROR 1105 (HY000): stale requests require tikv backendのようなメッセージでエラーが発生する可能性があります。

この問題を解決するには、StaleReadクエリのTiFlashレプリカを無効にします。これを行うには、次のいずれかの操作を実行します。

  • set session tidb_isolation_read_engines='tidb,tikv'変数を使用します。
  • ヒントを使用して、TiDBがTiKVからデータを読み取るように強制します。

TiDBは、特別なクライアントやドライバーを必要とせずに、 AS OF TIMESTAMPのSQL句である標準SQLインターフェイスを介した履歴データの読み取りをサポートします。データが更新または削除された後、このSQLインターフェイスを使用して、更新または削除前の履歴データを読み取ることができます。

ノート:

履歴データを読み取る場合、TiDBは、現在のテーブル構造が異なっていても、古いテーブル構造のデータを返します。

構文

AS OF TIMESTAMP句は、次の3つの方法で使用できます。

正確な時点を指定する場合は、日時値を設定するか、 AS OF TIMESTAMP句で時刻関数を使用できます。日時の形式は「2016-10-0816:45:26.999」のようにミリ秒が最小時間単位ですが、ほとんどの場合、「2016-10-08 16:45:26.999」のように、秒の時間単位で日時を指定できます。 -10-0816:45:26"NOW(3)関数を使用して、現在の時刻をミリ秒まで取得することもできます。数秒前のデータを読みたい場合は、 NOW() - INTERVAL 10 SECONDなどの式を使用することをお勧めします。

時間範囲を指定する場合は、句でTIDB_BOUNDED_STALENESS()関数を使用できます。この関数を使用すると、TiDBは指定された時間範囲内で適切なタイムスタンプを選択します。 「適切」とは、このタイムスタンプより前に開始され、アクセスされたレプリカでコミットされていないトランザクションがないことを意味します。つまり、TiDBはアクセスされたレプリカで読み取り操作を実行でき、読み取り操作はブロックされません。この関数を呼び出すには、 TIDB_BOUNDED_STALENESS(t1, t2)を使用する必要があります。 t1t2は時間範囲の両端であり、日時値または時間関数のいずれかを使用して指定できます。

AS OF TIMESTAMP句の例を次に示します。

  • AS OF TIMESTAMP '2016-10-08 16:45:26' :2016年10月8日の16:45:26に保存された最新のデータを読み取るようにTiDBに指示します。
  • AS OF TIMESTAMP NOW() - INTERVAL 10 SECOND秒前に保存された最新のデータを読み取るようにTiDBに指示します。
  • AS OF TIMESTAMP TIDB_BOUNDED_STALENESS('2016-10-08 16:45:26', '2016-10-08 16:45:29') :2016年10月8日の16:45:26から16:45:29の時間範囲内で可能な限り新しいデータを読み取るようにTiDBに指示します。
  • AS OF TIMESTAMP TIDB_BOUNDED_STALENESS(NOW() - INTERVAL 20 SECOND, NOW())秒前から現在までの時間範囲内で可能な限り新しいデータを読み取るようにTiDBに指示します。

ノート:

タイムスタンプの指定に加えて、 AS OF TIMESTAMP句の最も一般的な使用法は、数秒前のデータを読み取ることです。このアプローチを使用する場合は、5秒より古い履歴データを読み取ることをお勧めします。

Stale Readを使用する場合は、TiDBノードとPDノードにNTPサービスを展開する必要があります。これにより、TiDBによって使用される指定されたタイムスタンプが最新のTSO割り当ての進行状況(数秒先のタイムスタンプなど)よりも進んだり、GCセーフポイントのタイムスタンプよりも遅れたりする状況を回避できます。指定されたタイムスタンプがサービススコープを超えると、TiDBはエラーを返します。

使用例

このセクションでは、いくつかの例を使用してAS OF TIMESTAMP句を使用するさまざまな方法について説明します。最初に、リカバリ用のデータを準備する方法を紹介し、次に、それぞれSELECT 、およびSTART TRANSACTION READ ONLY AS OF TIMESTAMPAS OF TIMESTAMPを使用する方法を示しSET TRANSACTION READ ONLY AS OF TIMESTAMP

データサンプルを準備する

リカバリ用のデータを準備するには、最初にテーブルを作成し、データのいくつかの行を挿入します。

create table t (c int);
Query OK, 0 rows affected (0.01 sec)
insert into t values (1), (2), (3);
Query OK, 3 rows affected (0.00 sec)

表のデータを表示します。

select * from t;
+------+
| c    |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

現在の時刻を表示します。

select now();
+---------------------+
| now()               |
+---------------------+
| 2021-05-26 16:45:26 |
+---------------------+
1 row in set (0.00 sec)

行のデータを更新します。

update t set c=22 where c=2;
Query OK, 1 row affected (0.00 sec)

行のデータが更新されていることを確認します。

select * from t;
+------+
| c    |
+------+
|    1 |
|   22 |
|    3 |
+------+
3 rows in set (0.00 sec)

SELECTステートメントを使用して履歴データを読み取ります

SELECT ... FROM ... AS OF TIMESTAMPステートメントを使用して、過去のある時点のデータを読み取ることができます。

select * from t as of timestamp '2021-05-26 16:45:26';
+------+
| c    |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

ノート:

1つのSELECTステートメントを使用して複数のテーブルを読み取る場合は、TIMESTAMPEXPRESSIONの形式が一貫していることを確認する必要があります。たとえば、 select * from t as of timestamp NOW() - INTERVAL 2 SECOND, c as of timestamp NOW() - INTERVAL 2 SECOND; 。さらに、 SELECTステートメントで関連するテーブルのAS OF情報を指定する必要があります。それ以外の場合、 SELECTステートメントはデフォルトで最新のデータを読み取ります。

START TRANSACTION READ ONLY AS OF TIMESTAMPステートメントを使用して履歴データを読み取ります

START TRANSACTION READ ONLY AS OF TIMESTAMPステートメントを使用して、過去の時点に基づいて読み取り専用トランザクションを開始できます。トランザクションは、指定された時間の履歴データを読み取ります。

start transaction read only as of timestamp '2021-05-26 16:45:26';
Query OK, 0 rows affected (0.00 sec)
select * from t;
+------+
| c    |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)
commit;
Query OK, 0 rows affected (0.00 sec)

トランザクションがコミットされた後、最新のデータを読み取ることができます。

select * from t;
+------+
| c    |
+------+
|    1 |
|   22 |
|    3 |
+------+
3 rows in set (0.00 sec)

ノート:

ステートメントSTART TRANSACTION READ ONLY AS OF TIMESTAMPでトランザクションを開始する場合、それは読み取り専用トランザクションです。このトランザクションでは、書き込み操作は拒否されます。

SET TRANSACTION READ ONLY AS OF TIMESTAMPステートメントを使用して履歴データを読み取ります

SET TRANSACTION READ ONLY AS OF TIMESTAMPステートメントを使用して、過去の指定された時点に基づいて、次のトランザクションを読み取り専用トランザクションとして設定できます。トランザクションは、指定された時間の履歴データを読み取ります。

set transaction read only as of timestamp '2021-05-26 16:45:26';
Query OK, 0 rows affected (0.00 sec)
begin;
Query OK, 0 rows affected (0.00 sec)
select * from t;
+------+
| c    |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)
commit;
Query OK, 0 rows affected (0.00 sec)

トランザクションがコミットされた後、最新のデータを読み取ることができます。

select * from t;
+------+
| c    |
+------+
|    1 |
|   22 |
|    3 |
+------+
3 rows in set (0.00 sec)

ノート:

ステートメントSET TRANSACTION READ ONLY AS OF TIMESTAMPでトランザクションを開始する場合、それは読み取り専用トランザクションです。このトランザクションでは、書き込み操作は拒否されます。