InnoDB
tables use row-level locking so that multiple sessions and applications can read from and write to the same table simultaneously, without making each other wait or producing inconsistent results.
InnoDB表使用行级锁,这样多个会话和应用程序可以同时对同一个表进行读写,而不会导致彼此等待或产生不一致的结果。
For this storage engine, avoid using the LOCK TABLES statement, because it does not offer any extra protection, but instead reduces concurrency.
对于这个存储引擎,避免使用LOCK TABLES语句,因为它不提供任何额外的保护,而是减少并发性。
The automatic row-level locking makes these tables suitable for your busiest databases with your most important data, while also simplifying application logic since you do not need to lock and unlock tables. Consequently, the InnoDB
storage engine is the default in MySQL.
自动行级锁定使这些表适合于最繁忙的数据库,其中包含最重要的数据,同时也简化了应用程序逻辑,因为您不需要锁定和解锁表。因此,InnoDB存储引擎是MySQL的默认存储引擎。
MySQL uses table locking (instead of page, row, or column locking) for all storage engines except InnoDB
. The locking operations themselves do not have much overhead. But because only one session can write to a table at any one time, for best performance with these other storage engines, use them primarily for tables that are queried often and rarely inserted into or updated.
MySQL对除InnoDB外的所有存储引擎使用表锁(而不是页、行或列锁)。锁操作本身没有太多的开销。但是,由于在任何时候只能有一个会话写入表,因此,为了使用这些其他存储引擎获得最佳性能,主要将它们用于经常查询、很少插入或更新的表。
Performance Considerations Favoring InnoDB
性能考虑,支持InnoDB
When choosing whether to create a table using InnoDB
or a different storage engine, keep in mind the following disadvantages of table locking:
当选择是使用InnoDB还是使用不同的存储引擎创建表时,请记住表锁的以下缺点:
-
Table locking enables many sessions to read from a table at the same time, but if a session wants to write to a table, it must first get exclusive access, meaning it might have to wait for other sessions to finish with the table first. During the update, all other sessions that want to access this particular table must wait until the update is done.
-
表锁定允许多个会话同时从表中读取数据,但是如果一个会话想要写表,它必须首先获得独占访问,这意味着它可能必须等待其他会话先完成对表的操作。在更新期间,希望访问此特定表的所有其他会话必须等待更新完成。
-
Table locking causes problems when a session is waiting because the disk is full and free space needs to become available before the session can proceed. In this case, all sessions that want to access the problem table are also put in a waiting state until more disk space is made available.
-
当会话正在等待时,表锁定会导致问题,因为磁盘已满,在会话继续之前需要有可用的空闲空间。在这种情况下,希望访问问题表的所有会话也将处于等待状态,直到有更多的磁盘空间可用。
-
A SELECT statement that takes a long time to run prevents other sessions from updating the table in the meantime, making the other sessions appear slow or unresponsive. While a session is waiting to get exclusive access to the table for updates, other sessions that issue SELECT statements queue up behind it, reducing concurrency even for read-only sessions.
-
运行时间较长的SELECT语句会阻止其他会话在此期间更新表,使其他会话显得缓慢或无响应。当一个会话等待获得对表的独占访问以进行更新时,其他发出SELECT语句的会话排在它后面,这减少了即使是只读会话的并发性。
Workarounds for Locking Performance Issues
锁定性能问题的解决方案
The following items describe some ways to avoid or reduce contention caused by table locking:
以下内容描述了一些避免或减少表锁引起的争用的方法:
-
Consider switching the table to the
InnoDB
storage engine, either usingCREATE TABLE ... ENGINE=INNODB
during setup, or usingALTER TABLE ... ENGINE=INNODB
for an existing table. See Chapter 14, The InnoDB Storage Engine for more details about this storage engine. -
考虑将表切换到InnoDB存储引擎,或者使用CREATE table…ENGINE=INNODB,或者使用ALTER TABLE…ENGINE=INNODB。关于InnoDB存储引擎的更多细节,请参见第14章InnoDB存储引擎。
-
Optimize SELECT statements to run faster so that they lock tables for a shorter time. You might have to create some summary tables to do this.
-
优化SELECT语句以更快地运行,以便它们锁定表的时间更短。为此,您可能需要创建一些汇总表。
-
Start mysqld with --low-priority-updates. For storage engines that use only table-level locking (such as
MyISAM
,MEMORY
, andMERGE
), this gives all statements that update (modify) a table lower priority than SELECT statements. In this case, the second SELECT statement in the preceding scenario would execute before the UPDATE statement, and would not wait for the first SELECT to finish. -
使用——low-priority-updates启动mysqld。对于只使用表级锁的存储引擎(如MyISAM、MEMORY和MERGE),这使所有更新(修改)表的语句的优先级低于SELECT语句。在本例中,前面场景中的第二个SELECT语句将在UPDATE语句之前执行,而不会等待第一个SELECT语句完成。
-
To specify that all updates issued in a specific connection should be done with low priority, set the low_priority_updates server system variable equal to 1.
-
要指定在特定连接中发出的所有更新都应该以低优先级执行,可以将low_priority_updates服务器系统变量设置为1。
-
To give a specific INSERT, UPDATE, or DELETE statement lower priority, use the
LOW_PRIORITY
attribute. -
要为特定的INSERT、UPDATE或DELETE语句提供较低的优先级,请使用LOW_PRIORITY属性。
-
To give a specific SELECT statement higher priority, use the
HIGH_PRIORITY
attribute. See Section 13.2.9, “SELECT Statement”. -
要赋予特定SELECT语句更高的优先级,请使用HIGH_PRIORITY属性。
-
Start mysqld with a low value for the max_write_lock_count system variable to force MySQL to temporarily elevate the priority of all SELECT statements that are waiting for a table after a specific number of write locks to the table occur (for example, for insert operations). This permits read locks after a certain number of write locks.
-
启动mysqld时,max_write_lock_count系统变量的值较低,强制MySQL临时提高所有等待表的SELECT语句的优先级,这些语句在表发生特定数量的写锁之后(例如,对于插入操作)。这允许在一定数量的写锁之后使用读锁。
-
If you have problems with mixed SELECT and DELETE statements, the
LIMIT
option to DELETE may help. See Section 13.2.2, “DELETE Statement”. -
如果您在混合使用SELECT和DELETE语句时遇到问题,那么用于DELETE的LIMIT选项可能会有所帮助。
-
Using
SQL_BUFFER_RESULT
with SELECT statements can help to make the duration of table locks shorter. See Section 13.2.9, “SELECT Statement”. -
使用SQL_BUFFER_RESULT和SELECT语句可以帮助缩短表锁的持续时间。
-
Splitting table contents into separate tables may help, by allowing queries to run against columns in one table, while updates are confined to columns in a different table.
-
将表内容拆分为单独的表可能会有所帮助,因为允许对一个表中的列运行查询,而更新则局限于另一个表中的列。
-
You could change the locking code in
mysys/thr_lock.c
to use a single queue. In this case, write locks and read locks would have the same priority, which might help some applications. -
您可以更改mysys/thr_lock.c中的锁定代码以使用单个队列。在这种情况下,写锁和读锁具有相同的优先级,这可能有助于某些应用程序。