8.11.1 Internal Locking Methods
8.11.2 Table Locking Issues
8.11.3 Concurrent Inserts
8.11.4 Metadata Locking
8.11.5 External Locking
MySQL 使用locking 管理表内存的冲突:
内部locking 是通过MySQL server 本身来管理表内容的冲突,这种锁是内部的,因为它完全由服务器执行,没有涉及其他程序。
外部锁发生在服务器和其他程序lock MyISAM 表文件在它们之间协调,程序能访问表在任何时间。
8.11.1 Internal Locking Methods 内部锁方法:
本章讨论内部locking,即,locking 在MySQL server 本身管理表内容在多个会话下的冲突。
这种类型的locking 是内部的,它完全是有服务器执行的,并且没有调用其他程序。
Row-Level Locking 行级别锁定
MySQL 使用行级锁对于InnoDB 表来支持并发的读写,使它们适用于多个用户,高并发和OLTP应用。
为了避免死锁 当执行多个并发写操作在一个单独的InnoDB 表上,
获得必要的locks 在事务的开始通过执行SELECT .. FOR UPDATE语句对于每个期待修改的行。
即使DML语句在事务后面,如果事务修改或者lock 多个表,执行适当的语句在相当的顺序在每个事务中。
Deadlocks 影响性能相比表现出一个严重的错误,因为InnoDB 自动检测死锁条件,回滚其中一个受影响的事务。
行级锁的优点:
1.当不同的会话访问不同的记录,锁冲突越少
2.对于回滚变的更少
3.锁定一条记录很长时间
Table-Level Locking 表级锁
MySQL 使用表级锁对于MyISAM,MEMORY和MERGE 引擎表,
值允许一个会话同一时间更新那些表,让它们处于只读模式,或者单用户应用。
这些存储引擎避免死锁通过总是请求所有需要的锁在查询开始和总是以相同的顺序锁住表。
这种折衷是直接降低了冲突, 其他的会话需要修改表必须等待当前的DML完成。
MySQL 授于表写锁如下:
1.如果在表上没有锁, 放一把写锁在上面
2.否则,把锁请求放入write lock queue:
MySQL 授予表读锁如下:
1.如果没有写锁在表上, 放置一个read lock 在上面
2.否则,把锁请求在read lock 队列
表更新被给定一个更高的优先级相比表检索,因此,当一个锁被释放,锁变得可用对于请求在写锁队列,
然后请求在read lock 队列。确保了更新一个表不是被 “starved”,即使有严重的SELECT 活动。
然而, 如果你在表上有很多的更新,SELECT 语句等待直到这里没有更多的更新。
你可以分析表的lock 争用在你的系统上通过检查Table_locks_immediate和Table_locks_waited 变量,
这表明请求表锁的时间和等待的数量:
mysql> SHOW STATUS LIKE ‘Table%’;
+———————–+———+
| Variable_name | Value |
+———————–+———+
| Table_locks_immediate | 1151552 |
| Table_locks_waited | 15324 |
+———————–+———+
MyISAM 存储引擎支持并发的插入来降低冲突在读和写对于一个给定的表,
如果MyISAM 表没有足够的空闲快在数据文件中,行总是被插入到数据文件尾部。
在这种情况下,你可以自由的混合并发的INSERT和SELECT 语句对于MyISAM表而不需要锁,
也就说说, 你可以插入记录到一个MyISAM 表的同时其他客户端读取它们。
如果你会的一个表锁明确的使用LOCK TABLES,你可以请求一个READ LOCAL lock 而不是READ lock
让其他session 执行一个并发的插入当你的表被锁的时候。
执行很多的INSERT 和SELECT 操作在一个表 real_table 当并发的INSERT 是不可能的,
你可以insert 记录到一个临时表temp_table,用临时表的数据来更新real 表上
mysql> LOCK TABLES real_table WRITE, temp_table WRITE;
mysql> INSERT INTO real_table SELECT * FROM temp_table;
mysql> DELETE FROM temp_table;
mysql> UNLOCK TABLES;
表级锁的优点:
1.需要相对少的内存
- 当使用大部分表 ,因为只有一个锁被调用
3.如果你经常使用GROUP BY 操作在大数据表上或者你必须频繁的扫描整个表
InnoDB 支持表级锁和行级锁,MyISAM 只支持表级锁
通常表级锁使用于下面的情况:
1.表中的大多数语句都是读
2.表的语句是一个混合的读写,在这里写的是更新或删除一个单独的行,可以拿来一个键读:
UPDATE tbl_name SET column=value WHERE unique_key_col=key_value;
DELETE FROM tbl_name WHERE unique_key_col=key_value;