Auto Generated Primary Key in MySQL
DatabaseWhen a primary key is not explicitly specified, MySQL uses the first not null, unique, and integer field as the primary key. If none are found, it generates an implicit primary key ROW_ID.
Creating the following four tables, only the last one will use id as the primary key. Since secondary indexes include the primary key, let’s create a secondary index to test and observe the indexing situation on these tables.
create table nothing(id int, val int, index idx_val(val));
create table not_null(id int not null, val int, index idx_val(val));
create table `unique`(id int unique, val int, index idx_val(val));
create table not_null_unique(id int not null unique, val int, index idx_val(val));
First Table
mysql> desc nothing;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| id    | int  | YES  |     | NULL    |       |
| val   | int  | YES  | MUL | NULL    |       |
+-------+------+------+-----+---------+-------+
mysql> select index_name, stat_name, stat_description from mysql.innodb_index_stats where database_name='test' and table_name = 'nothing';
+-----------------+--------------+-----------------------------------+
| index_name      | stat_name    | stat_description                  |
+-----------------+--------------+-----------------------------------+
| GEN_CLUST_INDEX | n_diff_pfx01 | DB_ROW_ID                         |
| GEN_CLUST_INDEX | n_leaf_pages | Number of leaf pages in the index |
| GEN_CLUST_INDEX | size         | Number of pages in the index      |
| idx_val         | n_diff_pfx01 | val                               |
| idx_val         | n_diff_pfx02 | val,DB_ROW_ID                     |
| idx_val         | n_leaf_pages | Number of leaf pages in the index |
| idx_val         | size         | Number of pages in the index      |
+-----------------+--------------+-----------------------------------+
You can see that there are two indexes in the table:
- The clustered index 
GEN_CLUST_INDEXcreated on the automatically generatedROW_ID. - The 
idx_valindex we added. 
Additionally, since the compound index idx_val has two prefixes: (val) and (val, primary key), we can see that MySQL uses the generated primary key DB_ROW_ID.
Second Table
mysql> desc not_null;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| id    | int  | NO   |     | NULL    |       |
| val   | int  | YES  | MUL | NULL    |       |
+-------+------+------+-----+---------+-------+
mysql> select index_name, stat_name, stat_description from mysql.innodb_index_stats where database_name='test' and table_name = 'not_null';
+-----------------+--------------+-----------------------------------+
| index_name      | stat_name    | stat_description                  |
+-----------------+--------------+-----------------------------------+
| GEN_CLUST_INDEX | n_diff_pfx01 | DB_ROW_ID                         |
| GEN_CLUST_INDEX | n_leaf_pages | Number of leaf pages in the index |
| GEN_CLUST_INDEX | size         | Number of pages in the index      |
| idx_val         | n_diff_pfx01 | val                               |
| idx_val         | n_diff_pfx02 | val,DB_ROW_ID                     |
| idx_val         | n_leaf_pages | Number of leaf pages in the index |
| idx_val         | size         | Number of pages in the index      |
+-----------------+--------------+-----------------------------------+
The situation is the same.
Third Table
mysql> desc `unique`;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| id    | int  | YES  | UNI | NULL    |       |
| val   | int  | YES  | MUL | NULL    |       |
+-------+------+------+-----+---------+-------+
mysql> select index_name, stat_name, stat_description from mysql.innodb_index_stats where database_name='test' and table_name = 'unique';
+-----------------+--------------+-----------------------------------+
| index_name      | stat_name    | stat_description                  |
+-----------------+--------------+-----------------------------------+
| GEN_CLUST_INDEX | n_diff_pfx01 | DB_ROW_ID                         |
| GEN_CLUST_INDEX | n_leaf_pages | Number of leaf pages in the index |
| GEN_CLUST_INDEX | size         | Number of pages in the index      |
| id              | n_diff_pfx01 | id                                |
| id              | n_leaf_pages | Number of leaf pages in the index |
| id              | size         | Number of pages in the index      |
| idx_val         | n_diff_pfx01 | val                               |
| idx_val         | n_diff_pfx02 | val,DB_ROW_ID                     |
| idx_val         | n_leaf_pages | Number of leaf pages in the index |
| idx_val         | size         | Number of pages in the index      |
+-----------------+--------------+-----------------------------------+
In addition to the previous two indexes, MySQL automatically creates a unique index id due to the unique constraint.
Fourth Table
mysql> desc not_null_unique;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| id    | int  | NO   | PRI | NULL    |       |
| val   | int  | YES  | MUL | NULL    |       |
+-------+------+------+-----+---------+-------+
mysql> select index_name, stat_name, stat_description from mysql.innodb_index_stats where database_name='test' and table_name = 'not_null_unique';
+------------+--------------+-----------------------------------+
| index_name | stat_name    | stat_description                  |
+------------+--------------+-----------------------------------+
| id         | n_diff_pfx01 | id                                |
| id         | n_leaf_pages | Number of leaf pages in the index |
| id         | size         | Number of pages in the index      |
| idx_val    | n_diff_pfx01 | val                               |
| idx_val    | n_diff_pfx02 | val,id                            |
| idx_val    | n_leaf_pages | Number of leaf pages in the index |
| idx_val    | size         | Number of pages in the index      |
+------------+--------------+-----------------------------------+
You can see that GEN_CLUST_INDEX and DB_ROW_ID have disappeared, replaced by the qualified id field, indicating that MySQL chose this field as the primary key.