すべてのプロダクト
Search
ドキュメントセンター

PolarDB:DRDSモードのデータベースの主キーと一意キー

最終更新日:Jun 05, 2024

このトピックでは、DRDSモードで、テーブルの主キーがグローバル主キーであるかローカル主キーであるか、およびテーブルの一意キーがグローバル一意キーであるかローカル一意キーであるかを判断する方法について説明します。

主キー

PolarDB-Xでは、主キーは次の基準に基づいてグローバル主キーとローカル主キーに分類されます。

  • 主キーがグローバルに一意である場合、それはグローバル主キーです。

  • プライマリキーがテーブルシャード内でのみ一意である場合、それはローカルのプライマリキーです。

シングルテーブルとブロードキャストテーブル

単一のテーブルまたはブロードキャストテーブル内の主キーは、グローバルに一意なグローバル主キーです。

例1: 単一のテーブルとブロードキャストテーブルのグローバル主キー

## 単一のテーブル
CREATE TABLE single_tbl (
 id bigint NOT NULL AUTO_INCREMENT、 
 名前varchar(30) 、 
 主要なキー (id)
);

## 放送テーブル
テーブルの作成brd_tbl (
 id bigint NOT NULL AUTO_INCREMENT、 
 名前varchar(30) 、 
 主要なキー (id)
) 放送; 

データベースとテーブルシャード

グローバル主キー

テーブルの主キーにデータベースとテーブルシャードのすべてのシャードキーが含まれている場合、主キーはグローバルに一意なグローバル主キーです。

例2: データベースとテーブルシャードのグローバル主キー

user_tblテーブルでは、データベースシャードキーはid、テーブルシャードキーはname、プライマリキー列 (id, name, addr) にはすべてのシャードキーが含まれます。 したがって、テーブルの主キーは、グローバルに一意なグローバル主キーです。

CREATE TABLE user_tbl (
 id bigint,
 名前varchar(10) 、
 addr varchar(30) 、
 主要なキー (id、name、addr)
) DBPARTITION BY HASH(id) TBPARTITION BY HASH(name) TBPARTITIONS 4; 

ローカル主キー

テーブルのプライマリキーにデータベースとテーブルシャードのすべてのシャードキーが含まれていない場合、プライマリキーはローカルのプライマリキーになります。

例3: データベースとテーブルシャードのローカル主キー

order_tblテーブルの主キー列はorder_idであり、データベースシャードキー都市は含まれていません。 したがって、テーブルの主キーは、テーブル内で一意であるがグローバルに一意ではないローカル主キーです。

CREATE TABLE order_tbl (
 order_id bigint、
 都市varchar(50) 、
 テキスト名、
 PRIMARYキー (order_id)
) ハッシュによるDBPARTITION (都市); 

例4: グローバルに一意ではないローカル主キー

ローカル主キーはテーブル内でのみ一意であり、グローバルに一意ではありません。 したがって、重複するローカル主キーが存在する可能性があります。 この例では、例3のorder_tblテーブルが使用されます。 データベースシャードキーは都市です。 データベースシャーディングは実行され、テーブルシャーディングは実行されません。 したがって、各データベースシャードに含まれるテーブルは1つだけです。

  1. データレコードをorder_tblに挿入します。 データレコードが正常に挿入されました。

    INSERT INTO order_tbl(order_id, city, name) VALUES (10001, "Beijing", "phone");
    クエリOK、1行が影響 
  2. 同じorder_id値と同じcity値を持つデータレコードをorder_tblに挿入します。 都市値は以前に挿入されたデータレコードの都市値と同じであるため、システムは以前に挿入されたデータレコードと同じテーブルシャードにデータレコードを挿入しようとします。 SQL文の実行に失敗しました。 主キーの競合を示すエラーが報告されました。 この結果は、同じプライマリキー値を持つデータレコードを同じテーブルシャードに挿入することはできず、ローカルのプライマリキーはテーブルシャード内で一意であることを示しています。

    INSERT INTO order_tbl(order_id, city, name) VALUES (10001, "Beijing", "book");
    (1062、"ERR-CODE: [TDDL-4614][ERR_EXECUTE_ON_MYSQL] GROUP 'D25_000002_GROUP 'ATOM 'dskey_d25_000002_group#polardbx-storage-0-master#11.167.60.147-1766#d25_000002': キー 'PRIMARY 'のエントリ '10001' の重複") 
  3. 同じorder_id値を持つが異なるcity値を持つデータレコードをorder_tblに挿入します。 都市値は以前に挿入されたデータレコードの都市値とは異なる深センであるため、システムはデータレコードを別のテーブルシャードに挿入しようとします。

    SQL文を正常に実行できます。 その結果、order_tblテーブルには、同じ主キー値を持つ2つのデータレコードが含まれます。 これは、ローカル主キーがグローバルに一意ではないことを示します。

    INSERT INTO order_tbl (order_id、都市、名前) 値 (10001、"深セン" 、"カメラ");
    クエリOK、影響を受ける1行
    
    SELECT * からorder_tbl;
    + --------- ------------ ------------ +
    | order_id | 都市 | 名前 |
    + --------- ------------ ------------ +
    | 10001 | 北京 | 電話 |
    | 10001 | 深セン | カメラ |
    + --------- ------------ ------------ +
    2行のセット 

例5: 重複主キーを含むテーブルでDDLステートメントを実行すると、主キーの競合を示すエラーが発生する可能性があります。

ローカル主キーを使用するテーブルでは、主キーの値が重複する場合があります。 DDLステートメントを実行してテーブルタイプを変更したり、データを他のデータベースに同期したりするなど、テーブルに対してデータの再配布操作を実行すると、プライマリキーの競合を示すエラーが発生する可能性があります。

order_tblテーブルには、同じ主キー値を持つ2つのデータレコードが含まれます。 これらのレコードは、異なるテーブルシャードに挿入されます。 DDLステートメントを実行して、シャードデータベースとテーブルを1つのテーブルに変更します。 都市値が北京であるデータレコードと都市値が深センであるデータレコードが同じテーブルに挿入されます。

ALTER TABLE order_tbl SINGLE;
(4700, '[17399c0a2fc00000][30.221.117.14:8527][d25]ERR-CODE: [TDDL-4700][ERR_SERVER] サーバエラーby DDLジョブがロールバックされました。 ddlのstmtを点検して下さい。 jobId: 1673540305653071872 ') 

DDLステートメントの実行に失敗しました。 これは、単一のテーブル内の主キー値が一意でなければならないためです。 ただし、テーブルタイプを単一のテーブルに変更すると、同じプライマリキー値を持つデータレコードが単一のテーブルに挿入されます。

ローカル主キーを使用するテーブルの主キーの値が重複することによる主キーの競合を回避するには、次の操作を実行します。

  • AUTO_INCREMENT属性を使用して、PolarDB-Xに主キーを生成させます。

  • ビジネス側の主キー値を手動で指定しないでください。

    重要

    ローカル主キーを使用し、主キーが重複しているテーブルの場合は、データを他のデータベースに同期するときに主キーの競合を回避する必要があります。 たとえば、DTSを使用してローカルのプライマリキーを含むテーブルをAnalyticDB For MySQLデータベースに同期する場合、AnalyticDB for MySQLデータベースが引き続きPolarDB-Xテーブルのプライマリキーを使用すると競合が発生する可能性があります。 この問題を回避するには、PolarDB-Xテーブルのプライマリキー列とすべてのシャードキーを含むようにAnalyticDB for MySQLデータベースのプライマリキーを設定します。

ユニークなキー

主キーと同様に、PolarDB-Xの一意キーは、次の基準に基づいてグローバル一意キーとローカル一意キーに分類されます。

  • 一意キーがグローバルに一意である場合、それはグローバル一意キーです。

  • 一意のキーがテーブルシャード内でのみ一意である場合、それはローカルの一意のキーです。

このセクションでは、さまざまなシナリオで、テーブルの一意キーがグローバル一意キーかローカル一意キーかを判断する方法について説明します。

シングルテーブルとブロードキャストテーブル

単一のテーブルまたはブロードキャストテーブル内の一意キーは、グローバルに一意であるグローバル一意キーである。

例6: 単一のテーブルとブロードキャストテーブルのグローバル一意キー

## 単一のテーブル
CREATE TABLE single_tbl (
 serial_id bigint、
 名前varchar(30) 、 
 UNIQUEキー (serial_id)
);

## 放送テーブル
テーブルの作成brd_tbl (
 serial_id bigint、
 名前varchar(30) 、 
 	UNIQUEキー (serial_id)
) 放送; 

データベースとテーブルシャード

グローバル一意キー

テーブルの一意キーにデータベースとテーブルシャードのすべてのシャードキーが含まれている場合、一意キーはグローバルに一意なグローバル一意キーです。

例7: データベースとテーブルシャードのグローバル一意キー

type_tblテーブルでは、一意のキー列は (inner_id, type_id) で、シャードキーtype_idのみが含まれます。 したがって、テーブルの一意キーは、グローバル一意キーである。

CREATE TABLE type_tbl (
 type_id int,
 inner_id int,
 UNIQUE KEY(inner_id, type_id)
) ハッシュによるDBPARTITION (type_id); 

データベースとテーブルシャードのグローバルセカンダリインデックスも、グローバルに一意なグローバル一意キーです。 詳細については、「グローバルセカンダリインデックス」をご参照ください。

例8: 一意のグローバルインデックスで構成されるグローバル一意キー

テーブルtype_tbl2には、インデックス列がserial_idである一意のグローバルインデックスが含まれます。 serial_id列はグローバルに一意であり、グローバル一意キーです。

CREATE TABLE type_tbl2 (
 type_id int,
 serial_id int,
 UNIQUEグローバルインデックスu_sid(serial_id) DBPARTITION BY HASH(serial_id)
) ハッシュによるDBPARTITION (type_id); 

ローカル一意キー

テーブルの一意のキーにデータベースとテーブルシャードのすべてのシャードキーが含まれていない場合、一意のキーはローカルの一意のキーです。

例9: データベースとテーブルシャードのローカル一意キー

info_tblテーブルの一意のキー列はserial_idで、シャードキーorder_timeは含まれません。 したがって、info_tblテーブルの一意キーはローカル一意キーです。 一意キーはテーブル内でのみ一意であり、グローバルに一意ではありません。

CREATE TABLE info_tbl (
 id int primary key auto_increment,
 serial_id int,
 	order_time date NOT NULL,
 UNIQUEキー (serial_id)
) DBPARTITION BY YYYYMM(order_time); 

例10: グローバルに一意ではないローカル一意キー

ローカル主キーと同様に、ローカル一意キーはグローバルに一意ではありません。 したがって、重複するローカル一意キーが存在し得る。

この例では、例9のinfo_tblテーブルが使用されます。 データベースシャードキーはorder_timeです。 データベースシャーディングは実行され、テーブルシャーディングは実行されません。 したがって、各データベースシャードに含まれるテーブルは1つだけです。

  1. info_tblにデータレコードを挿入します。 データレコードが挿入されます。

    INSERT INTO info_tbl(serial_id, order_time) VALUES (20001, '2022-01-01 ');
    クエリOK、1行が影響 
  2. 同じserial_id値と2022-01-02のorder_time値を持つデータレコードをinfo_tblに挿入します。 order_time値は以前に挿入されたデータレコードの値と同じであるため、システムは以前に挿入されたデータレコードと同じテーブルシャードにデータレコードを挿入しようとします。 SQL文の実行に失敗しました。 一意のキーの競合を示すエラーが報告されます。 この結果は、同じ一意のキー値を持つデータレコードを同じテーブルシャードに挿入することはできず、ローカルの一意のキーはテーブルシャード内で一意であることを示しています。

    INSERT INTO info_tbl(serial_id, order_time) VALUES (20001, '2022-01-02 ');
    (1062、"ERR-CODE: [TDDL-4614][ERR_EXECUTE_ON_MYSQL] GROUP 'D25_000001_GROUP 'ATOM 'dskey_d25_000001_group#polardbx-storage-1-master#11.167.60.147-1766#d25_000001': 重複エントリ '20001' for key 'serial_id'") 
  3. 同じserial_id値と2023-03-01のorder_time値を持つデータレコードをinfo_tblに挿入します。 order_time値は以前に挿入されたデータレコードの値とは異なるため、システムはデータレコードを別のテーブルシャードに挿入しようとします。 データレコードが挿入されます。 その結果、serial_idテーブルには、同じ一意のキー値を持つ2つのデータレコードが含まれます。 これは、ローカル一意キーがグローバルに一意ではないことを示します。

    INSERT INTO info_tbl(serial_id, order_time) VALUES (20001, '2023-03-01 ');
    クエリOK、影響を受ける1行
    
    SELECT * からinfo_tbl;
    + ------- ----------- ------------------
    | id | serial_id | order_time |
    + ------- ----------- ------------------
    | 100006 | 20001 | 2023-03-01 |
    | 100001 | 20001 | 2022-01-01 |
    + ------- ----------- ------------------ 

例11: 重複する一意のキーを持つテーブルに対してDDLステートメントを実行すると、一意のキーの競合を示すエラーが発生する可能性があります。

ローカル主キーを含むテーブルと同様に、ローカル一意キーを使用するテーブルは、重複する一意キー値を有することができる。 DDLステートメントを実行してテーブルタイプを変更したり、データを他のデータベースに同期したりするなど、テーブルに対してデータの再配布操作を実行すると、一意のキーの競合を示すエラーが発生する可能性があります。

info_tblテーブルには、同じ一意のキー値を持つ2つのデータレコードがすでに含まれています。 これらのレコードは、異なるテーブルシャードに格納されます。 DDLステートメントを実行して、シャードデータベースとテーブルを1つのテーブルに変更します。 これにより、info_tblテーブルにデータが再配布されます。

ALTER TABLE info_tbl SINGLE;
(4700、"ERR-CODE: [TDDL-4700][ERR_SERVER] サーバエラーによるDDLタスクの実行に失敗しました。 原因: ERR-CODE: [TDDL-5321][ERR_GLOBAL_SECONDARY_INDEX_BACKFILL_DUPLICATE_ENTRY] キー 'PRIMARY' "のエントリ '20001' の複製) 

DDLステートメントの実行に失敗しました。 一意のキーの競合を示すエラーが返されます。 これは、単一のテーブル内の一意のキー値が一意でなければならないためです。 ただし、info_tblのテーブルタイプを単一のテーブルに変更すると、同じ一意のキー値を持つデータレコードが単一のテーブルに挿入されます。

ローカル一意キーを使用するテーブルの重複する一意キー値によって引き起こされる一意キーの競合を回避するには、一意キー値が一意であることを確認する必要があります。

重要

ローカルの一意キーを使用し、一意キーが重複しているテーブルの場合は、データを他のデータベースに同期するときに一意キーの競合を回避するために、ソースデータを手動で修正する必要があります。

FAQ

  • 特別な構文を使用して、グローバル主キーまたはグローバル一意キーを作成できますか?

    いいえ、できません。 同じMySQL構文を使用して、プライマリキーまたは一意のキーを作成します。 作成する主キーと一意キーが、グローバル主キーとグローバル一意キーの基準を満たしていることを確認します。

  • 私のテーブルはローカル主キーを使用します。 プライマリキーがグローバルに一意であることを確認するにはどうすればよいですか?

    PolarDB-Xが提供するシーケンスを使用して、グローバルに一意な主キー値を生成できます。 詳細については、「シーケンス」をご参照ください。