Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 Reference Manual  /  ...  /  Table Locking Issues

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 语句将在第一个 SELECT 语句完成之前执行,不会等待第一个 SELECT 语句完成。

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

  • 要给特定INSERTUPDATEDELETE语句低优先级,使用LOW_PRIORITY属性。

  • 要给特定SELECT语句高优先级,使用HIGH_PRIORITY属性。见第 15.2.13 节,“SELECT 语句”

  • 使用mysqld,将max_write_lock_count系统变量设置为低值,以迫使 MySQL 临时提高所有等待表的SELECT语句的优先级,直到特定数量的写锁定到表中(例如,插入操作)。这允许在一定数量的写锁定后读锁定。

  • 如果您遇到混合SELECTDELETE语句的问题,LIMIT选项可能有助于DELETE。见第 15.2.2 节,“DELETE 语句”

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

  • 将表内容拆分到单独的表中可能有助于,使查询可以在一个表的列上运行,而更新被限制在另一个表的列上。

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