5.什么时候使用表锁
对于InnoDB表,在绝大部分情况下都应该使用行级锁,因为事务和行锁往往是我们之所以选择InnoDB表的理由 。但在个别特殊事务中,也可以考虑使用表级锁:
(1)事务需要更新大部分或全部数据,表又比较大,如果使用默认的行锁,不仅这个事务执行效率低,而且可能造成其他事务长时间锁等待和锁冲突,这种情况下可以考虑使用表锁来提高该事务的执行速度 。
(2)事务涉及多个表,比较复杂,很可能引起死锁,造成大量事务回滚 。这种情况也可以考虑一次性锁定事务涉及的表,从而避免死锁、减少数据库因事务回滚带来的开销 。
当然,应用中这两种事务不能太多,否则,就应该考虑使用MyISAM表了 。
在InnoDB下,使用表锁要注意以下两点 。
(1)使用LOCK TABLES虽然可以给InnoDB加表级锁,但必须说明的是,表锁不是由InnoDB存储引擎层管理的,而是由其上一层──MySQL Server负责的,仅当autocommit=0、InnoDB_table_locks=1(默认设置)时,InnoDB层才能知道MySQL加的表锁,MySQL Server也才能感知InnoDB加的行锁,这种情况下,InnoDB才能自动识别涉及表级锁的死锁,否则,InnoDB将无法自动检测并处理这种死锁 。
(2)在用 LOCK TABLES对InnoDB表加锁时要注意,要将AUTOCOMMIT设为0,否则MySQL不会给表加锁;事务结束前,不要用UNLOCK TABLES释放表锁,因为UNLOCK TABLES会隐含地提交事务;COMMIT或ROLLBACK并不能释放用LOCK TABLES加的表级锁,必须用UNLOCK TABLES释放表锁 。正确的方式见如下语句:
例如,如果需要写表t1并从表t读,可以按如下做:
SET AUTOCOMMIT=0;LOCK TABLES t1 WRITE, t2 READ, ...;[do something with tables t1 and t2 here];COMMIT;UNLOCK TABLES;6.InnoDB行锁优化建议
InnoDB存储引擎由于实现了行级锁定,虽然在锁定机制的实现方面所带来的性能损耗可能比表级锁定会要更高一些,但是在整体并发处理能力方面要远远优于MyISAM的表级锁定的 。当系统并发量较高的时候,InnoDB的整体性能和MyISAM相比就会有比较明显的优势了 。但是,InnoDB的行级锁定同样也有其脆弱的一面,当我们使用不当的时候,可能会让InnoDB的整体性能表现不仅不能比MyISAM高,甚至可能会更差 。
(1)要想合理利用InnoDB的行级锁定,做到扬长避短,我们必须做好以下工作:
a)尽可能让所有的数据检索都通过索引来完成,从而避免InnoDB因为无法通过索引键加锁而升级为表级锁定;
b)合理设计索引,让InnoDB在索引键上面加锁的时候尽可能准确,尽可能的缩小锁定范围,避免造成不必要的锁定而影响其他Query的执行;
c)尽可能减少基于范围的数据检索过滤条件,避免因为间隙锁带来的负面影响而锁定了不该锁定的记录;
d)尽量控制事务的大小,减少锁定的资源量和锁定时间长度;
e)在业务环境允许的情况下,尽量使用较低级别的事务隔离,以减少MySQL因为实现事务隔离级别所带来的附加成本 。
(2)由于InnoDB的行级锁定和事务性,所以肯定会产生死锁,下面是一些比较常用的减少死锁产生概率的小建议:
a)类似业务模块中,尽可能按照相同的访问顺序来访问,防止产生死锁;
b)在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率;
c)对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率 。
(3)可以通过检查InnoDB_row_lock状态变量来分析系统上的行锁的争夺情况:
mysql> show status like 'InnoDB_row_lock%';+-------------------------------+-------+| Variable_name | Value |+-------------------------------+-------+| InnoDB_row_lock_current_waits | 0 || InnoDB_row_lock_time | 0 || InnoDB_row_lock_time_avg | 0 || InnoDB_row_lock_time_max | 0 || InnoDB_row_lock_waits | 0 |+-------------------------------+-------+InnoDB 的行级锁定状态变量不仅记录了锁定等待次数,还记录了锁定总时长,每次平均时长,以及最大时长,此外还有一个非累积状态量显示了当前正在等待锁定的等待数量 。对各个状态量的说明如下:
InnoDB_row_lock_current_waits:当前正在等待锁定的数量;
InnoDB_row_lock_time:从系统启动到现在锁定总时间长度;
InnoDB_row_lock_time_avg:每次等待所花平均时间;
InnoDB_row_lock_time_max:从系统启动到现在等待最常的一次所花的时间;
InnoDB_row_lock_waits:系统启动后到现在总共等待的次数;
对于这5个状态变量,比较重要的主要是InnoDB_row_lock_time_avg(等待平均时长),InnoDB_row_lock_waits(等待总次数)以及InnoDB_row_lock_time(等待总时长)这三项 。尤其是当等待次数很高,而且每次等待时长也不小的时候,我们就需要分析系统中为什么会有如此多的等待,然后根据分析结果着手指定优化计划 。
推荐阅读
- tvb当红女星有哪些 tvb明星排名女
- MySQL不为人知的主键与唯一索引约束
- 安溪产茶始于唐末 至明代茶叶盛产 并有了名气明末清初
- 微服务架构下,Mysql读写分离后,数据库CPU飙升卡壳问题解析
- 如何查看磁盘上的MySQL表大小
- 阿里P8架构师谈:MySQL数据库的索引原理、与慢SQL优化的5大原则
- 玻璃门斜了怎么调整 门用久有点倾斜了怎么调整
- Trim指令是如何提高固态硬盘寿命的?
- 为什么分布式一定要有Redis?
- 男性心理要健康 判断有标准
