文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  表锁定问题

10.11.2 表锁定问题

InnoDB 表使用行级锁定,以便多个会话和应用程序可以同时读取和写入同一个表,而不会互相等待或产生不一致的结果。对于此存储引擎,请避免使用 LOCK TABLES 语句,因为它不提供任何额外的保护,反而会降低并发性。自动的行级锁定使这些表适合于您最繁忙的数据库,其中包含您最重要的数据,同时简化了应用程序逻辑,因为您不需要锁定和解锁表。因此,InnoDB 存储引擎是 MySQL 的默认存储引擎。

MySQL 对除 InnoDB 之外的所有存储引擎使用表级锁定(而不是页级、行级或列级锁定)。锁定操作本身没有太多开销。但由于一次只能有一个会话写入一个表,因此为了在这些其他存储引擎中获得最佳性能,主要将它们用于经常查询且很少插入或更新的表。

有利于 InnoDB 的性能注意事项

在选择使用 InnoDB 还是其他存储引擎创建表时,请记住表级锁定的以下缺点

  • 表级锁定允许许多会话同时读取表,但如果一个会话想要写入表,则必须首先获取独占访问权限,这意味着它可能必须等待其他会话先完成对表的访问。在更新期间,所有想要访问此特定表的其他会话都必须等待更新完成。

  • 当一个会话因磁盘已满而等待时,表级锁定会导致问题,并且需要释放空间才能继续。在这种情况下,所有想要访问问题表的会话也将处于等待状态,直到释放更多磁盘空间。

  • 一个 SELECT 语句如果运行时间过长,则会阻止其他会话在此期间更新表,使其他会话看起来很慢或无响应。当一个会话正在等待获取对表的独占访问权限以进行更新时,其他发出 SELECT 语句的会话将在其后面排队,从而降低了即使是只读会话的并发性。

解决锁定性能问题的变通方法

以下内容描述了一些避免或减少由表级锁定引起的争用的方法

  • 考虑将表切换到 InnoDB 存储引擎,要么在设置期间使用 CREATE TABLE ... ENGINE=INNODB,要么对现有表使用 ALTER TABLE ... ENGINE=INNODB。有关此存储引擎的更多详细信息,请参见 第 17 章,InnoDB 存储引擎

  • 优化 SELECT 语句以更快地运行,以便它们锁定表的时间更短。您可能需要创建一些汇总表来完成此操作。

  • 使用 mysqld 启动 --low-priority-updates。对于仅使用表级锁定的存储引擎(如 MyISAMMEMORYMERGE),这会使所有更新(修改)表的语句的优先级低于 SELECT 语句。在这种情况下,前面场景中的第二个 SELECT 语句将在 UPDATE 语句之前执行,并且不会等待第一个 SELECT 语句完成。

  • 要指定在特定连接中发出的所有更新都应以低优先级进行,请将 low_priority_updates 服务器系统变量设置为 1。

  • 为了降低特定INSERTUPDATEDELETE 语句的优先级,请使用 LOW_PRIORITY 属性。

  • 为了提高特定SELECT 语句的优先级,请使用 HIGH_PRIORITY 属性。参见第 15.2.13 节,“SELECT 语句”

  • 使用较低的值启动 mysqldmax_write_lock_count 系统变量,强制 MySQL 在对表执行特定数量的写锁(例如,插入操作)后,暂时提升所有等待表的SELECT 语句的优先级。这允许在一定数量的写锁后进行读锁。

  • 如果您在混合SELECTDELETE 语句方面遇到问题,DELETELIMIT 选项可能会有所帮助。参见第 15.2.2 节,“DELETE 语句”

  • SELECT 语句中使用 SQL_BUFFER_RESULT 可以帮助缩短表锁的持续时间。参见第 15.2.13 节,“SELECT 语句”

  • 将表内容拆分为单独的表可能会有所帮助,因为这样可以允许查询针对一个表的列运行,而更新仅限于另一个表的列。

  • 您可以更改mysys/thr_lock.c 中的锁定代码以使用单个队列。在这种情况下,写锁和读锁将具有相同的优先级,这可能有助于某些应用程序。