MySQL 表锁定

17 Mar 2025 | 5 分钟阅读

锁是与表相关联的一种机制,用于限制对表中数据的未经授权的访问。 MySQL 允许客户端会话显式获取表锁,以与其他会话协作访问表的数据。 MySQL 还允许表锁定,以防止在特定时期内对同一表进行未经授权的修改。

MySQL 中的会话只能为自己获取或释放表上的锁。因此,一个会话不能为其他会话获取或释放表锁。需要注意的是,我们必须拥有 TABLE LOCK 和 SELECT 权限才能进行表锁定。

MySQL 中的表锁定主要 用于解决并发问题。它将在运行事务时使用,即首先从表(数据库)中读取值,然后将其写入表(数据库)。

MySQL 提供 两种类型的表锁,它们是

读取锁 (READ LOCK):此锁只允许用户从表中读取数据。

写入锁 (WRITE LOCK):此锁允许用户对表进行读取和写入操作。

需要注意的是,MySQL 中使用的默认存储引擎是 InnoDB。InnoDB 存储引擎不需要手动进行表锁定,因为 MySQL 会自动对 InnoDB 表使用行级锁定。因此,我们可以对同一表同时进行多个事务的读写操作,而无需相互等待。所有其他存储引擎都使用 MySQL 中的表锁定。

在理解表锁定概念之前,我们首先使用以下语句创建一个名为 "info_table" 的新表

MySQL LOCK TABLES 语句

以下是允许我们显式获取表锁的语法

在上述语法中,我们在 LOCK TABLES 关键字之后指定了我们想要获取锁的 表名。我们可以指定 锁类型,可以是 READ 或 WRITE。

我们还可以通过使用逗号分隔的表名列表和锁类型来锁定 MySQL 中的多个表。请参阅以下语法

MySQL UNLOCK TABLES 语句

以下是允许我们 释放 MySQL 中表的锁的语法

锁类型

让我们详细了解锁类型。

读取锁

以下是读取锁的特点

  • 同时,MySQL 允许多个会话获取表的读取锁。所有其他会话都可以在不获取锁的情况下读取表。
  • 如果会话持有表的读取锁,则不能对其执行写入操作。这是因为读取锁只能从表中读取数据。所有其他未获取读取锁的会话在未释放读取锁的情况下,都无法将数据写入表中。写入操作将进入等待状态,直到我们释放读取锁。
  • 当会话正常或异常终止时,MySQL 会隐式释放表上的所有类型锁。此功能也适用于写入锁。

让我们以一个示例来看看读取锁在 MySQL 中如何与给定场景一起工作。我们将首先连接到数据库并使用 CONNECTION_ID() 函数,该函数在第一个会话中提供当前连接 ID,如下所示

请参见下面的输出

MySQL Table Locking

接下来,我们将使用以下语句向 info_table 中插入几行

现在,使用以下语句验证表中的数据

我们应该看到以下输出

MySQL Table Locking

现在,我们将执行 LOCK TABLE 语句来获取表上的锁

之后,我们将尝试向 info_table 中插入一条新记录,如下所示

我们将得到以下输出,MySQL 会发出以下消息 "表 'info_table' 已被读取锁锁定,无法更新"

MySQL Table Locking

因此,我们可以看到,一旦在表上获取了读取锁,我们就无法在同一会话中向表中写入数据。

现在,我们将检查读取锁如何从不同的会话中工作。首先,我们将连接到数据库并查看连接 ID

MySQL Table Locking

接下来,我们将从 info_table 中查询数据,返回以下输出

MySQL Table Locking

然后,向此表中插入一些行,如下所示

我们应该看到以下输出

MySQL Table Locking

在上述输出中,我们可以看到第二个会话的插入操作处于 等待状态。这是由于读取锁,该锁已由第一个会话获取并在表上,并且尚未释放。

我们可以使用第一个会话中的 SHOW PROCESSLIST 语句查看它们的详细信息。请参阅以下输出

MySQL Table Locking

最后,我们需要使用第一个会话中的 UNLOCK TABLES 语句释放锁。现在,我们可以在第二个会话中执行 INSERT 操作。

写入锁

以下是写入锁的特点

  • 它是持有表锁的会话,可以从表中读取和写入数据。
  • 它是唯一一个通过持有锁来访问表的会话。所有其他会话都无法访问表中的数据,直到释放写入锁。

让我们以一个示例来看看写入锁在 MySQL 中如何与给定场景一起工作。在第一个会话中,我们将使用以下语句获取写入锁

然后,我们将向 info_table 中插入一条新记录,如下所示

上述语句成功执行。现在,我们可以使用 SELECT 语句验证输出

MySQL Table Locking

再次,我们将尝试从第二个会话访问(读取/写入)表

我们可以看到这些操作被置于等待状态。使用 SHOW PROCESSLIST 语句查看它们的详细信息

MySQL Table Locking

最后,我们将从第一个会话中释放锁。现在,我们可以执行挂起的操作。

读取锁与写入锁

  • 读取锁类似于“共享”锁,因为多个线程可以同时获取它。
  • 写入锁是“独占”锁,因为其他线程无法读取它。
  • 我们不能同时对表提供读取锁和写入锁。
  • 读取锁的 优先级低于 写入锁,这确保了更新尽快完成。

下一个主题MySQL 账户锁定