MySQL 使用 locking来管理表内容的争用:
Internal locking 发生在MySQL服务器内部,来管理多线程导致的表内容争用。这种锁是内部的,因为它完全是服务器产生的,而不是其他程序。参见 Section 8.11.1, “Internal Locking Methods”。
External locking 发生在服务器和其他程序锁住 MyISAM 表文件来协商该时间点哪个程序可以访问改表的时候。参见 Section 8.11.5, “External Locking”。
行级锁 Row-Level Locking
MySQL 使用row-level locking 给 InnoDB 表来支持不同session的同时写,使得适用于多用户、高并发、以及OLTP应用。
要在并发写某个InnoDB 表的时候避免 deadlocks ,通过在事务开头对要修改的行提交 SELECT ... FOR UPDATE来获取必要的锁,即使在稍后事务会修改这些数据。如果事务修改或锁定多个表,那么应用的语句在每个事务内都要以同样的顺序执行。死锁会影响性能,而不是一个严重的错误,因为InnoDB自动的 detects 死锁状态,然后回滚其中一个受影响的事务。
行级锁的优势:
不同session访问不同行的时候,产生更少锁的冲突。
回滚更少的变更。
可以长时间锁某单行。
表级锁 Table-Level Locking
MySQL使用table-level locking 给 MyISAM、 MEMORY、 和 MERGE 表,一次只允许一个连接更新表。 这种锁使得存储引擎更适合于只读、读多写少、或者单用户应用。
这些存储引擎通过在开始查询时即获取所有需要的锁,然后以同样的顺序来锁住这些表来规避deadlocks 。相对妥协的是该策略降低了并发性能;其他会话修改数据必须等到当前修改数据的语句结束。
表级锁的优势:
相对小的内存需求 (行锁需要锁定的每行或者行组都分配内存)
在使用表的大范围内容的时候快,因为仅一个锁
在经常在大范围数据执行 GROUP BY 操作,或者必须频繁执行全表扫描的时候快
MySQL通过如下授权表写锁:
如果表上没锁,那么推一个写锁给表
或者,推锁的请求进写锁队列
MySQL通过如下授权读锁:
如果表上没锁,那么推一个读锁给表
或者,推锁的请求进读锁队列
表更新的优先级高于表的检索。因此,当一个锁释放了,先对写锁队列的请求可用,然后对读锁队列的请求可用。这就保证了即使该表有一个很大的SELECT,也不会导致更新等待。那么,如果该表有很多更新,SELECT 语句会等待直到没有更新为止。
InnoDB 表使用行级锁,这样多连接和应用可以同时读取和写入到同一个表,而不需要等待或产生不一致的结果。对于InnoDB引擎,避免使用 LOCK TABLES statement,因为它不提供任何保护反而降低了并发。自动的行级锁使这些表适用于你最忙的数据库,同时简化了应用逻辑因为你不需要去锁和解锁表。 因此,InnoDB 存储引擎成为了MySQL的默认引擎。
除了InnoDB,其他所有的存储引擎MySQL都使用表锁 (而不是page, row, or column 锁)。锁操作自身没什么开销。但是因为同时只能有一个连接可以写入表, 为了这些引擎的最佳性能,它们主要用于查询多,插入、更新少的表。
Ext