文档主页
MySQL 9.0 参考手册
相关文档 下载此手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
Man 页面 (TGZ) - 258.2Kb
Man 页面 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  表级锁问题

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 中的锁定代码以使用单个队列。在这种情况下,写锁和读锁将具有相同的优先级,这可能有助于某些应用程序。