InnoDB
表使用行级锁定,以便多个会话和应用程序可以同时读取和写入同一个表,而不会互相等待或产生不一致的结果。对于此存储引擎,请避免使用 LOCK TABLES
语句,因为它不提供任何额外的保护,反而会降低并发性。自动的行级锁定使这些表适合于您最繁忙的数据库,其中包含您最重要的数据,同时简化了应用程序逻辑,因为您不需要锁定和解锁表。因此,InnoDB
存储引擎是 MySQL 的默认存储引擎。
MySQL 对除 InnoDB
之外的所有存储引擎使用表级锁定(而不是页级、行级或列级锁定)。锁定操作本身没有太多开销。但由于一次只能有一个会话写入一个表,因此为了在这些其他存储引擎中获得最佳性能,主要将它们用于经常查询且很少插入或更新的表。
在选择使用 InnoDB
还是其他存储引擎创建表时,请记住表级锁定的以下缺点
以下内容描述了一些避免或减少由表级锁定引起的争用的方法
考虑将表切换到
InnoDB
存储引擎,要么在设置期间使用CREATE TABLE ... ENGINE=INNODB
,要么对现有表使用ALTER TABLE ... ENGINE=INNODB
。有关此存储引擎的更多详细信息,请参见 第 17 章,InnoDB 存储引擎。优化
SELECT
语句以更快地运行,以便它们锁定表的时间更短。您可能需要创建一些汇总表来完成此操作。使用 mysqld 启动
--low-priority-updates
。对于仅使用表级锁定的存储引擎(如MyISAM
、MEMORY
和MERGE
),这会使所有更新(修改)表的语句的优先级低于SELECT
语句。在这种情况下,前面场景中的第二个SELECT
语句将在UPDATE
语句之前执行,并且不会等待第一个SELECT
语句完成。要指定在特定连接中发出的所有更新都应以低优先级进行,请将
low_priority_updates
服务器系统变量设置为 1。为了提高特定
SELECT
语句的优先级,请使用HIGH_PRIORITY
属性。参见第 15.2.13 节,“SELECT 语句”。使用较低的值启动 mysqld 的
max_write_lock_count
系统变量,强制 MySQL 在对表执行特定数量的写锁(例如,插入操作)后,暂时提升所有等待表的SELECT
语句的优先级。这允许在一定数量的写锁后进行读锁。如果您在混合
SELECT
和DELETE
语句方面遇到问题,DELETE
的LIMIT
选项可能会有所帮助。参见第 15.2.2 节,“DELETE 语句”。在
SELECT
语句中使用SQL_BUFFER_RESULT
可以帮助缩短表锁的持续时间。参见第 15.2.13 节,“SELECT 语句”。将表内容拆分为单独的表可能会有所帮助,因为这样可以允许查询针对一个表的列运行,而更新仅限于另一个表的列。
您可以更改
mysys/thr_lock.c
中的锁定代码以使用单个队列。在这种情况下,写锁和读锁将具有相同的优先级,这可能有助于某些应用程序。