表锁定问题
InnoDB
表使用行级锁定,因此多个会话和应用程序可以同时读取和写入同一个表,而不会彼此等待或产生不一致的结果。对于此存储引擎,请避免使用该LOCK TABLES
语句,因为它不提供任何额外的保护,而是减少了并发性。自动行级锁定使这些表适合于具有最重要数据的最繁忙的数据库,同时由于不需要锁定和解锁表,还简化了应用程序逻辑。因此,InnoDB
存储引擎是MySQL中的默认引擎。
MySQL对所有存储引擎都使用表锁定(而不是页面锁定,行锁定或列锁定)InnoDB
。锁定操作本身没有太多的开销。但是,由于一次只能有一个会话可以写入表,因此要与其他存储引擎一起获得最佳性能,请主要将它们用于经常查询且很少插入或更新的表。
- 性能方面的考虑有利于InnoDB
- 锁定性能问题的变通办法
性能方面的考虑有利于InnoDB
选择是使用表InnoDB
还是使用其他存储引擎创建表时,请记住表锁定的以下缺点:
- 表锁定使许多会话可以同时从一个表读取数据,但是如果一个会话要写入一个表,则必须首先获得互斥访问,这意味着它可能必须先等待其他会话才能完成对该表的访问。在更新期间,所有要访问此特定表的其他会话都必须等待,直到更新完成。
- 在会话等待期间,表锁定会导致问题,因为磁盘已满,会话开始之前需要释放可用空间。在这种情况下,所有要访问问题表的会话也将处于等待状态,直到有更多磁盘空间可用为止。
- 一个
SELECT
是需要很长的时间,从更新表的同时,使其他场次出现缓慢或无响应运行防止其他会话声明。当会话正在等待获取表的独占访问权以进行更新时,其他发出SELECT
语句的会话将在其后排队,从而即使对于只读会话也降低了并发性。
锁定性能问题的变通办法
以下各项描述了避免或减少表锁定引起的争用的一些方法:
- 考虑在安装过程
InnoDB
中使用CREATE TABLE ... ENGINE=INNODB
或ALTER TABLE ... ENGINE=INNODB
将现有表用于将表切换到存储引擎。有关此存储引擎的更多详细信息,请参见。 - 优化
SELECT
语句以使其运行更快,以便它们在较短的时间内锁定表。您可能必须创建一些汇总表才能执行此操作。 - 启动mysqld的使用
--low-priority-updates
。对于仅使用表级锁(如存储引擎MyISAM
,MEMORY
和MERGE
),这给所有的语句更新(修改),比表低优先级SELECT
的语句。在这种情况下,SELECT
前面场景中的第二条语句将在该UPDATE
语句之前执行,而不会等待第一条语句SELECT
完成。 - 要指定应以低优先级完成在特定连接中发布的所有更新,请将
low_priority_updates
服务器系统变量设置为1。 - 要给特定的
INSERT
,UPDATE
或DELETE
语句降低优先级,请使用LOW_PRIORITY
属性。 - 要赋予特定
SELECT
语句更高的优先级,请使用HIGH_PRIORITY
属性。请参见“ SELECT语句”。 - 在系统变量的值较低的情况下启动mysqld,
max_write_lock_count
以强制MySQLSELECT
在对表进行特定次数的插入之后暂时提高所有等待表的语句的优先级。这允许READ
一定数量的锁之后的WRITE
锁。 - 如果您在与
INSERT
结合使用时遇到问题SELECT
,请考虑切换到MyISAM
支持并发SELECT
和INSERT
语句的表。(请参见“并发插入”。) - 如果您在混合
SELECT
和DELETE
语句方面遇到问题,则LIMIT
可以选择DELETE
。请参见“ DELETE语句”。 - 使用
SQL_BUFFER_RESULT
withSELECT
语句可以帮助缩短表锁定的持续时间。请参见“ SELECT语句”。 - 通过允许对一个表中的列运行查询,而将更新限制在另一个表中的列,将表内容拆分为单独的表可能会有所帮助。
- 您可以更改锁定代码
mysys/thr_lock.c
以使用单个队列。在这种情况下,写锁和读锁将具有相同的优先级,这可能对某些应用程序有所帮助。