mysql性能调优——锁优化
影响mysql server性能的相关因素
需求和架构及业务实现优化:55%
Query语句优化:30%
数据库自身优化:15%
很多时候大家看到数据库应用系统中性能瓶颈出现在数据库方面,就希望通过数据库的优化来解决问题,但不管DBA对数据库多么了解,对Query语句的优化多么静态,最终还是很难解决整个系统的性能问题,原因在于并没有找到根本的症结所在。
所以数据库的优化实际上是一个需要多方面配合多方面优化才能根本性改善的事情,可以概括性的归为:商业需求合理化、系统架构最优化、实现逻辑精简化、硬件设施理性化。
mysql数据库锁定机制
mysql各存储引使用了三种锁定机制:行级锁定、表级锁定和页级锁定。这里主要谈一下InnoDB存储引擎实现的行级锁定(NDB Cluster也是行级锁定的存储引擎)。InnoDB和其他数据库的行级锁定机制类似,都有共享锁S和排他锁X,为了让行级锁定和表级锁定共存,
InnoDB同样使用了意向锁的概念(表级锁定),就有了意向共享锁IS和意向排他锁IX。共享锁可以共存,但排他锁不可以,InnoDB和其他数据库最大的不同是实现行锁的机制,其他数据库时通过在需要锁定的某行记录所在的物理Block上的事务槽上面添加锁定信息,而
InnoDB的锁定是通过指向数据记录的第一个索引建之前和最后一个索引建之后的空域表级锁定信息实现行级锁定,被称为间隙锁。间隙锁有很多弱点:
1.锁定一个范围键值之后即使某些不存在的键值也会被锁定,这就造成了锁定范围内无法插入数据,会对性能带来影响。
2.当Query无法命中索引的时候,InnoDB会放弃行锁定而改用表锁定,造成并发性能降低
众所周知,行级锁定会造成死锁的存在,死锁产生的原因:
1.不同表,相同的记录(事务A和事务B操作两张表的相同记录,顺序不一致)
2.相同表记录(事务A和事务B操作同一张的表的相同记录,顺序不一致:jobA处理的的id列表为[1,2,3,4],而job处理的id列表为[8,9,10,4,2])
3.不同的索引冲突:事务A在执行时,除了在二级索引加锁外,还会在聚簇索引上加锁,在聚簇索引上加锁的顺序是[1,4,2,3,5],而事务B执行时,只在聚簇索引上加锁,加锁顺序是[1,2,3,4,5],这样就造成了死锁的可能性
InnoDB监测死锁的机制是选择较小的事务回滚,标准是衡量插入或者更新删除数据的多少。
InnoDB行锁优化建议:
1.尽可能让所有数据检索都通过索引来完成,避免升级为表级锁定
2.合理设计索引,可以缩小行锁的锁定范围,避免造成不必要的锁定影响其他Query执行
3.尽可能减少基于范围的数据检索过滤条件,避免间隙锁锁定不该锁定的记录
4.控制事务大小,减少锁定的资源量和锁定时间长度
5.使用较低级别的事务隔离
减少死锁建议:
1.尽可能按照相同顺序的来访问资源
2.在同一个事务中尽可能做到一次性锁定所有资源,减少死锁的概率
3.对于非常容易产生死锁的业务部分尝试升级锁的粒度,通过表级锁定来减少死锁产生的概率
系统锁定争用情况查询:
表级锁定:SHOW STATUS LIKE 'table%';Table_locks_immediate(表级锁定的次数),Table_locks_waited(表级锁定争用次数)
行级锁定:SHOW STATUS LIKE 'innodb_row_lock%';Innodb_row_lock_current_waits(当前正在锁定的数量),Innodb_row_lock_time(从系统启动到现在锁定总时间长度),Innodb_row_lock_time_avg/max(平均时间/最长的一次时间),Innodb_row_lock_waits(等待次数)