MySQL InnoDB row/table 执行 ALTER 时锁定
MySQL InnoDB row/table lock when performing ALTER
我创建了一个 sysbench table,如下所示,其中包含 25,000,000 条记录(大小为 5.7G):
Create Table: CREATE TABLE `sbtest1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`k` int(11) NOT NULL DEFAULT '0',
`c` char(120) NOT NULL DEFAULT '',
`pad` char(60) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `k_1` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=25000001 DEFAULT CHARSET=latin1
然后直接用ALTER语句在c上加了索引,耗时18分钟左右,更新table如下图:
mysql> alter table sbtest1 add index c_1(c);
Query OK, 0 rows affected (18 min 47.32 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show create table sbtest1\G
*************************** 1. row ***************************
Table: sbtest1
Create Table: CREATE TABLE `sbtest1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`k` int(11) NOT NULL DEFAULT '0',
`c` char(120) NOT NULL DEFAULT '',
`pad` char(60) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `k_1` (`k`),
KEY `c_1` (`c`)
) ENGINE=InnoDB AUTO_INCREMENT=25000002 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
在 table 更新过程的 18 分钟内,我尝试通过插入新记录在 table 上执行一些事务,并更新 c 列上的现有记录,这让我感到惊讶当我希望锁定以防止这种情况发生时,一切都有效。我一直明白,在 InnoDB table 上执行 ALTER,尤其是大的 table,会导致进程持续期间的记录锁定,所以想知道为什么我无法执行插入和更新没有任何问题吗?
以下是关于我的服务器的一些信息:
mysql> show variables like '%isolation%';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
| tx_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
mysql> select version()
-> ;
+-----------+
| version() |
+-----------+
| 5.7.25-28 |
+-----------+
对我来说,现在好像在MySQL 5.7 中,直接运行 ALTER 语句可以不用担心锁吗?这是一个准确的结论吗?
已更新
当我尝试删除添加的索引 c_1 时,只用了不到一秒钟,这也让我感到惊讶,因为我预计这比实际添加索引花费的时间更长。我一直认为添加索引简单快捷,但是删除或更新一个索引需要很长时间,因为必须更改整个 table 结构。对此有点困惑???
Adding secondary index 可以就地完成并允许并发 DML。
我创建了一个 sysbench table,如下所示,其中包含 25,000,000 条记录(大小为 5.7G):
Create Table: CREATE TABLE `sbtest1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`k` int(11) NOT NULL DEFAULT '0',
`c` char(120) NOT NULL DEFAULT '',
`pad` char(60) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `k_1` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=25000001 DEFAULT CHARSET=latin1
然后直接用ALTER语句在c上加了索引,耗时18分钟左右,更新table如下图:
mysql> alter table sbtest1 add index c_1(c);
Query OK, 0 rows affected (18 min 47.32 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show create table sbtest1\G
*************************** 1. row ***************************
Table: sbtest1
Create Table: CREATE TABLE `sbtest1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`k` int(11) NOT NULL DEFAULT '0',
`c` char(120) NOT NULL DEFAULT '',
`pad` char(60) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `k_1` (`k`),
KEY `c_1` (`c`)
) ENGINE=InnoDB AUTO_INCREMENT=25000002 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
在 table 更新过程的 18 分钟内,我尝试通过插入新记录在 table 上执行一些事务,并更新 c 列上的现有记录,这让我感到惊讶当我希望锁定以防止这种情况发生时,一切都有效。我一直明白,在 InnoDB table 上执行 ALTER,尤其是大的 table,会导致进程持续期间的记录锁定,所以想知道为什么我无法执行插入和更新没有任何问题吗?
以下是关于我的服务器的一些信息:
mysql> show variables like '%isolation%';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
| tx_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
mysql> select version()
-> ;
+-----------+
| version() |
+-----------+
| 5.7.25-28 |
+-----------+
对我来说,现在好像在MySQL 5.7 中,直接运行 ALTER 语句可以不用担心锁吗?这是一个准确的结论吗?
已更新 当我尝试删除添加的索引 c_1 时,只用了不到一秒钟,这也让我感到惊讶,因为我预计这比实际添加索引花费的时间更长。我一直认为添加索引简单快捷,但是删除或更新一个索引需要很长时间,因为必须更改整个 table 结构。对此有点困惑???
Adding secondary index 可以就地完成并允许并发 DML。