MySQL中的表锁和行锁(新手必看)
MySQL 与其他数据库在锁定机制方面最大的不同之处在于,对于不同的存储引擎支持不同的锁定机制。例如,InnoDB 存储引擎支持行级锁和表级锁,默认情况下采用行级锁;MyISAM 存储引擎采用的是表级锁。
MyISAM 表级锁的优化建议如下:
1) MyISAM 表级锁的锁定级别是固定的,所以在考虑 MyISAM 表级锁优化时,重点考虑如何提高并发的效率。
2) 减少锁定的时间,让查询的时间尽可能短。要减少比较复杂的查询语句,可以考虑将复杂的查询分解成多个小的查询。尽可能建立足够高效的索引,让数据检索更迅速。尽量让 MyISAM 存储引擎的表控制字段类型。利用合理的机会优化 MyISAM 表数据文件。
3) MyISAM 表级锁可以分离能并行的操作。对于读锁互相阻塞的表级锁,可能会觉得存储引擎的表上只能是完全的串行化,没有办法再并行了,可是 MyISAM 的存储引擎还有一个非常有用的特性,就是 Concurrent Insert 特性。可以考虑设置 Concurrent Insert 的值为 2,此时无论 MyISAM 存储引擎的数据文件的中间部分是否存在空洞(因为删除数据而留下的空闲空间),都允许在数据文件尾部进行插入操作。
4) MyISAM 的表级锁定对于读和写有不同优先级别设定,默认情况下写操作的优先级别高于读操作的优先级别,可以考虑根据应用的实际情况来设置读锁和写锁的优先级别,即通过设置系统参数 low_priority_updates=1,设置写的优先级比读的优先级低。
当系统并发量较高的时候,InnoDB 的整体性能和 MyISAM 相比优势就比较明显了,所以说在选择使用哪种锁的时候,应该考虑应用是否有很大的并发量。
想要合理使用 InnoDB 的行级锁,应该扬长避短,尽量做到以下几点:
MyISAM 表级锁优化建议
对于 MyISAM 存储引擎,虽然使用表级锁在实现过程方面比行级锁和页级锁所带来的附加成本要小,所消耗的资源也是最小的,不过 MyISAM 表级锁的颗粒比较大,在数据库并发处理过程中产生的数据资源争用的情况会比其他的锁定级别要多,从而在较大程度上降低了并发处理能力。MyISAM 表级锁的优化建议如下:
1) MyISAM 表级锁的锁定级别是固定的,所以在考虑 MyISAM 表级锁优化时,重点考虑如何提高并发的效率。
2) 减少锁定的时间,让查询的时间尽可能短。要减少比较复杂的查询语句,可以考虑将复杂的查询分解成多个小的查询。尽可能建立足够高效的索引,让数据检索更迅速。尽量让 MyISAM 存储引擎的表控制字段类型。利用合理的机会优化 MyISAM 表数据文件。
3) MyISAM 表级锁可以分离能并行的操作。对于读锁互相阻塞的表级锁,可能会觉得存储引擎的表上只能是完全的串行化,没有办法再并行了,可是 MyISAM 的存储引擎还有一个非常有用的特性,就是 Concurrent Insert 特性。可以考虑设置 Concurrent Insert 的值为 2,此时无论 MyISAM 存储引擎的数据文件的中间部分是否存在空洞(因为删除数据而留下的空闲空间),都允许在数据文件尾部进行插入操作。
4) MyISAM 的表级锁定对于读和写有不同优先级别设定,默认情况下写操作的优先级别高于读操作的优先级别,可以考虑根据应用的实际情况来设置读锁和写锁的优先级别,即通过设置系统参数 low_priority_updates=1,设置写的优先级比读的优先级低。
InnoDB行级锁优化建议
InnoDB 存储引擎由于实现了行级锁,而行级锁的颗粒更小、实现更为复杂,因此带来的性能损耗比表级锁更高,但是 InnoDB 行级锁在并发性能上要远远高于表级锁。当系统并发量较高的时候,InnoDB 的整体性能和 MyISAM 相比优势就比较明显了,所以说在选择使用哪种锁的时候,应该考虑应用是否有很大的并发量。
想要合理使用 InnoDB 的行级锁,应该扬长避短,尽量做到以下几点:
- 尽量控制事务的大小,减少锁定的资源量和锁定时间长度;
- 尽可能让所有的数据检索都通过索引来完成,从而避免因为无法通过索引加锁而升级为表级锁定;
- 尽可能减少基于范围的数据检索过滤条件,避免因为间隙锁带来的负面影响而锁定了不该锁定的记录;
- 在业务环节允许的情况下,尽量使用较低级别的事务隔离,以减少因为事务隔离级别锁而带来的附加成本;
- 合理使用索引,让 InnoDB 在索引上面加锁的时候更加准确;
- 在应用中,尽可能按照相同的访问顺序来访问,防止产生死锁;
- 在同一个事务中,尽可能做到一次锁定所需的所有资源,减少产生死锁的概率;
- 对于容易产生死锁的业务,可以放弃使用 InnoDB 行级锁定,尝试使用表级锁定来减少死锁产生的概率;
- 不要申请超过实际需要的锁级别。