Background
Tables without primary keys
Creating tables without primary keys in a MySQL database introduces significant risks to a high-availability architecture:
- Binlog synchronization failure When full table updates or range delete operations occur, each row-based binlog event requires a full table scan to locate data during replay on the secondary instance due to the lack of a clustered index. Tests show that these operations on tables with millions of rows cause the primary-secondary synchronized latency to increase exponentially.
- Storage engine feature conflict The clustered index feature of the InnoDB engine requires a unique row identifier. When a table lacks an explicit primary key:
- The implicit ROW_ID automatically generated by the engine lacks index visibility.
- Secondary index leaf nodes are forced to point to the implicit ROW_ID, making the data location path invisible and increasing maintenance costs.
- Each DML operation effectively becomes a full table scan.
- Avalanche effect on high-availability links: Latency from tables without primary keys is self-worsening:
- The primary database continuously generates new binlog events.
- The replica database cannot consume the event queue in time due to full table scans.
- This eventually interrupts synchronization.
- This creates a risk of data inconsistency during failover.
Solutions
- Reactive approach: Rebuild the standby database
- After a table without a primary key has been created, a reactive solution is to handle the issue without changing the table structure. This involves setting up primary-replica latency alerts, manually checking if the table without a primary key is the cause, and rebuilding the replica database through a work order. This approach creates an additional manual workload and is unsustainable.
- Proactive approach: Use hidden primary keys
- MySQL Community Edition 8.0.30 introduces the Generated Invisible Primary Key (GIPK) feature. It identifies tables without primary keys in CREATE TABLE statements and adds a user-invisible primary key index to the table by using MySQL's "invisible column" attribute. This approach solves the problem of tables without primary keys without affecting user operations, ensuring that newly created tables always have a primary key.
Introduction to the GIPK capabilities of RDS for MySQL
RDS for MySQL optimizes the community's invisible primary key based on the community version 8.0 and implements a GIPK-like function in MySQL 5.7 by using a unique index. The following compares the invisible primary key capabilities that RDS for MySQL provides for MySQL 8.0, MySQL 8.4, and MySQL 5.7.
Supported version
- MySQL 8.0 version, and the kernel minor version is MySQL 8.0.32_20240415 and above.
- MySQL 5.7 version, and the kernel minor version is MySQL 5.7.32_20241015 and above.
- MySQL 8.4 version, and the kernel version is MySQL 8.4.7_20260415 and above.
Usage
Enable invisible primary key
Modify the instance parameter to ON.
- MySQL 8.0、MySQL 8.4:sql_generate_invisible_primary_key
- MySQL 5.7:loose_sql_generate_invisible_primary_key
tip
- The two parameters above are not open for modification. If you need to modify them, submit a ticket to contact technical support.
- For instances with kernel minor version 20241215 or later, the value of these two parameters is ON by default.
Viewing the invisible primary key
After enabling the loose_show_gipk_in_create_table_and_information_schema parameter at the session level, you can see the invisible primary key byte_rds_ai_uk_row_id in show create table.
After enabling the show_gipk_in_create_table_and_information_schema parameter at the session level, you can see the invisible primary key my_row_id in show create table.
MySQL 8.4
After enabling the show_gipk_in_create_table_and_information_schema parameter at the session level, you can see the invisible primary key my_row_id in show create table.
After GIPK is enabled, RDS for MySQL supports DDL as described in the following table.
tip
The kernel minor version is 20241015 or a later version.
Table structure used in the example
- GIPK table: create table gipk_test(i int, c varchar(255));
- Standard primary key table: create table gipk_test(i int auto_increment primary key, c varchar(255));
Alert handling