### 8.11.2 表锁定问题

[](<>)

`InnoDB`表使用行级锁定，以便多个会话和应用程序可以同时读取和写入同一个表，而不会让彼此等待或产生不一致的结果。对于此存储引擎，请避免使用[`锁定表`](lock-tables.html)声明，因为它不提供任何额外的保护，而是降低了并发性。自动行级锁定使这些表适用于包含最重要数据的最繁忙的数据库，同时还简化了应用程序逻辑，因为您不需要锁定和解锁表。因此，`InnoDB`存储引擎是 MySQL 中的默认引擎。

MySQL 对所有存储引擎使用表锁定（而不是页、行或列锁定），除了`InnoDB`.锁定操作本身并没有太多开销。但是因为任何时候只有一个会话可以写入表，为了获得这些其他存储引擎的最佳性能，主要将它们用于经常查询并且很少插入或更新的表。

-   [有利于 InnoDB 的性能注意事项](table-locking.html#table-locking-innodb)

-   [锁定性能问题的解决方法](table-locking.html#table-locking-workarounds)

#### 有利于 InnoDB 的性能注意事项

选择是否使用创建表时`InnoDB`或不同的存储引擎，请记住表锁定的以下缺点：

-   表锁定使许多会话可以同时从表中读取，但是如果会话想要写入表，它必须首先获得独占访问权限，这意味着它可能必须等待其他会话首先完成表。在更新期间，想要访问此特定表的所有其他会话必须等到更新完成。

-   当会话等待时，表锁定会导致问题，因为磁盘已满并且在会话可以继续之前需要可用空间。在这种情况下，所有想要访问问题表的会话也都处于等待状态，直到有更多磁盘空间可用。

-   一种[`选择`](select.html)需要很长时间运行的语句会阻止其他会话同时更新表，从而使其他会话显得缓慢或无响应。当一个会话等待获得对表的独占访问权以进行更新时，其他发出的会话[`选择`](select.html)语句在它后面排队，即使是只读会话也会降低并发性。

#### 锁定性能问题的解决方法

以下项目描述了避免或减少表锁定引起的争用的一些方法：

-   考虑将表切换到`InnoDB`存储引擎，或者使用`创建表 ... ENGINE=INNODB`在设置过程中，或使用`ALTER TABLE ... 引擎=INNODB`对于现有表。看[第 15 章，*InnoDB 存储引擎*](innodb-storage-engine.html)有关此存储引擎的更多详细信息。

-   优化[`选择`](select.html)语句运行得更快，以便它们锁定表的时间更短。您可能必须创建一些汇总表来执行此操作。

-   开始[**mysqld**](mysqld.html)和[`--低优先级更新`](server-system-variables.html#sysvar_low_priority_updates).对于只使用表级锁定的存储引擎（例如`MyISAM`,`记忆`， 和`合并`)，这使所有更新（修改）表的语句的优先级低于[`选择`](select.html)陈述。在这种情况下，第二[`选择`](select.html)前面场景中的语句将在[`更新`](update.html)声明，并且不会等待第一个[`选择`](select.html)完成。

-   要指定在特定连接中发布的所有更新都应以低优先级完成，请将[`低优先级更新`](server-system-variables.html#sysvar_low_priority_updates)服务器系统变量等于 1。

-   给出一个具体的[`插入`](insert.html),[`更新`](update.html)， 要么[`删除`](delete.html)语句优先级较低，使用`低优先级`属性。

-   给出一个具体的[`选择`](select.html)语句优先级较高，使用`HIGH_PRIORITY`属性。看[第 13.2.10 节，“SELECT 语句”](select.html).

-   开始[**mysqld**](mysqld.html)具有较低的价值[`max_write_lock_count`](server-system-variables.html#sysvar_max_write_lock_count)系统变量强制 MySQL 临时提升所有的优先级[`选择`](select.html)在表发生特定数量的写锁后等待表的语句（例如，对于插入操作）。这允许在一定数量的写锁之后读锁。

-   如果你有混合问题[`选择`](select.html)和[`删除`](delete.html)声明，`限制`选项[`删除`](delete.html)可能会有所帮助。看[第 13.2.2 节，“DELETE 语句”](delete.html).

-   使用`SQL_BUFFER_RESULT`和[`选择`](select.html)语句可以帮助缩短表锁的持续时间。看[第 13.2.10 节，“SELECT 语句”](select.html).

-   将表内容拆分为单独的表可能会有所帮助，因为它允许对一个表中的列运行查询，而更新仅限于不同表中的列。

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