我创建了这个表 USERS 有 1000 万条记录
mysql> desc users;
+--------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| id | int | NO | | NULL | |
| name | varchar(255) | NO | | NULL | |
| email | varchar(255) | NO | | NULL | |
| gender | varchar(10) | NO | | NULL | |
+--------+--------------+------+-----+---------+-------+
现在我有 2 个终端会话,session_1 和 session_2 在 session_1 中,我运行了此命令
mysql> alter table users add primary key(id);
虽然 session_1 中的这个 alter 命令仍在进行中,但在会话 2 中,我使用以下命令终止了 mysql 客户端
kill -9 <mysql_session_id>
当我重新启动 mysql 客户端时,我desc USERS
再次发出,我在 id 列上看不到任何主键,但大约一分钟后,我看到主键在
id
列上。
mysql> desc users;
+--------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| id | int | NO | PRI | NULL | |
| name | varchar(255) | NO | | NULL | |
| email | varchar(255) | NO | | NULL | |
| gender | varchar(10) | NO | | NULL | |
+--------+--------------+------+-----+---------+-------+
4 rows in set (0.01 sec)
我也尝试过set autocommit=0
在版本 8.0 之前,DDL 语句(例如 ALTER)是在没有事务 ACID 的情况下执行的。(也就是说,
autocommit
并BEGIN..COMMIT
没有受到尊重。)如果客户端在 RENAME 之前消失或系统崩溃,则进程终止。(通常“tmp”留在磁盘上。)
RENAME 速度很快,而且本质上是原子的,因此一旦完成,操作就完成了。
(还有一些锁我没有列出。)
MySQL 8.0 做了同样的事情,但在这些语句
BEGIN
周围COMMIT
,加上新的代码能够ROLLBACK
.回到你的问题......实际上,旧代码几乎具有新代码的效果,因为杀死客户端可能发生在 之前
RENAME
,因此看起来它被回滚了。另请注意,该
INSERT
语句花费的时间最长,因为它必须复制所有数据,而且可能以不同的顺序复制。(数据根据主键存储在B+Tree中。)它也会重建所有的辅助键INDEXes
你运行什么版本?也许您正在运行 8.0 并且您的 ALTER 确实已完成,但锁定到位需要一些时间。这也许可以解释 DESC 显示它的延迟。(我认为没有任何 Oracle 开发人员在关注这个论坛,因此您可能无法在这里得到明确的答案。您可以在 bugs.mysql.com 上发布错误,希望得到答案。)