MySQL 新增索引会加锁吗?

在 MySQL 数据库中,索引是非常重要的数据结构之一,用于加快数据的检索速度。当我们需要对某个表进行查询时,如果该表有适当的索引,MySQL 可以直接通过索引来定位到需要的数据行,从而提高查询效率。那么,在 MySQL 中新增索引会加锁吗?本文将通过代码示例和详细讲解来解答这个问题。

索引和锁的基本概念

在深入讨论新增索引是否会加锁之前,让我们先来了解一下索引和锁的基本概念。

索引

索引是一种特殊的数据结构,它可以帮助数据库系统快速定位到需要的数据行,从而提高查询效率。在 MySQL 中,常见的索引类型包括主键索引、唯一索引、普通索引等。

锁是数据库系统中用于控制并发访问的一种机制。当多个事务同时对同一数据进行操作时,可能会引发数据不一致的问题。通过加锁,可以确保每个事务在访问数据时的一致性和隔离性。在 MySQL 中,常见的锁类型包括共享锁(读锁)和排他锁(写锁)。

MySQL 索引的加锁行为

MySQL 在执行数据操作语句时,会根据具体的情况选择合适的锁策略。对于新增索引的操作,MySQL 会对相关的数据行加排他锁,以确保数据的一致性。

让我们通过一个简单的代码示例来验证这个结论。

首先,创建一个名为 users 的表,其中包含两个字段:idname

CREATE TABLE users (
  id INT PRIMARY KEY,
  name VARCHAR(50)
);

接下来,插入一些测试数据。

INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie');

然后,开启两个会话,分别执行以下代码。

会话1:

BEGIN;
SELECT * FROM users WHERE id = 1 FOR UPDATE;

会话2:

ALTER TABLE users ADD INDEX idx_name (name);

在会话2中执行 ALTER TABLE 语句时,MySQL 会对 users 表加排他锁,以防止其他会话对该表进行修改。而在会话1中,由于使用了 FOR UPDATE 语句,MySQL 也会对 id = 1 的数据行加排他锁。这样一来,会话2中的 ALTER TABLE 语句就会被阻塞,直到会话1中的事务提交或回滚。

MySQL 索引的加锁优化策略

虽然新增索引会对相关数据行加排他锁,但 MySQL 在一些特定情况下会采取优化策略,减少锁的范围,从而提高并发性能。

索引的在线创建

MySQL 支持在线创建索引,即在不影响表的读写操作的情况下,对表进行索引的创建。在线创建索引的过程中,MySQL 会使用复制表的方式来完成,不会对原表加锁。

让我们通过以下代码示例来验证这个结论。

首先,创建一个名为 users 的表,其中包含两个字段:idname

CREATE TABLE users (
  id INT PRIMARY KEY,
  name VARCHAR(50)
);

接下来,插入一些测试数据。

INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie');

然后,开启两个会话,分别执行以下代码。

会话1:

BEGIN;
SELECT * FROM users WHERE id = 1 FOR UPDATE;

会话2:

ALTER TABLE users ADD INDEX idx_name (name) ALGORITHM=INPLACE;

在会话2中执行 ALTER TABLE 语句时,