このトピックでは、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つだけです。
データレコードをorder_tblに挿入します。 データレコードが正常に挿入されました。
INSERT INTO order_tbl(order_id, city, name) VALUES (10001, "Beijing", "phone"); クエリOK、1行が影響
同じ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' の重複")
同じ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つだけです。
info_tblにデータレコードを挿入します。 データレコードが挿入されます。
INSERT INTO info_tbl(serial_id, order_time) VALUES (20001, '2022-01-01 '); クエリOK、1行が影響
同じ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'")
同じ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が提供するシーケンスを使用して、グローバルに一意な主キー値を生成できます。 詳細については、「シーケンス」をご参照ください。