「MySQL高级篇」MySQL锁机制 && 事务( 四 )

行锁基本演示

  • 我们采用两个客户端,首先要关闭掉自动提交功能:set autocommit = 0;
    • 普通的select不加锁,没有什么影响
    • 而insert和update就不一样了,会加排它锁,其他客户端陷入阻塞状态,不能对该行(注意得两个客户端操作的是同一行,才会阻塞,因为是行锁)进行修改,直到加锁的客户端提交完事务(相当于释放锁)

「MySQL高级篇」MySQL锁机制 && 事务

文章插图

「MySQL高级篇」MySQL锁机制 && 事务

文章插图
无索引行锁升级为表锁
如果不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,实际效果跟表锁一样 。

「MySQL高级篇」MySQL锁机制 && 事务

文章插图
由于 执行更新时,name字段本来为varchar类型,我们是作为数组类型使用,存在类型转换,索引失效,最终行锁变为表锁 ;(字符串类型,在SQL语句使用的时候没有加单引号,导致索引失效,查询没有走索引,进行全表扫描,索引失效,行锁就升级为表锁)
InnoDB 行锁争用情况showstatus like 'innodb_row_lock%';
「MySQL高级篇」MySQL锁机制 && 事务

文章插图
  • Innodb_row_lock_current_waits: 当前正在等待锁定的数量
  • Innodb_row_lock_time: 从系统启动到现在锁定总时间长度
  • Innodb_row_lock_time_avg:每次等待所花平均时长
  • Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花的时间
  • Innodb_row_lock_waits: 系统启动后到现在总共等待的次数
当等待的次数很高,而且每次等待的时长也不小的时候,我们就需要分析系统中为什么会有如此多的等待,然后根据分析结果着手制定优化计划 。
总结InnoDB存储引擎由于实现了行级锁定,虽然在锁定机制的实现方面带来了性能损耗可能比表锁会更高一些 , 但是在整体并发处理能力方面要远远高于MyISAM的表锁的 。当系统并发量较高的时候,InnoDB的整体性能和MyISAM相比就会有比较明显的优势 。
但是,InnoDB的行级锁同样也有其脆弱的一面,当我们使用不当的时候 , 可能会让InnoDB的整体性能表现不仅不能比MyISAM高 , 甚至可能会更差 。
优化建议
  • 尽可能让所有数据检索都能通过索引来完成,避免无索引行锁升级为表锁 。
  • 合理设计索引,尽量缩小锁的范围 。
  • 尽可能减少索引条件 , 及索引范围,避免间隙锁 。
  • 尽量控制事务大?。跎偎ㄗ试戳亢褪奔涑ざ?。
  • 尽可使用低级别事务隔离(但是需要业务层面满足需求)
表级锁扩展全局锁
「MySQL高级篇」MySQL锁机制 && 事务

文章插图
特点
「MySQL高级篇」MySQL锁机制 && 事务

文章插图
备份的一致性问题来看下边这个场景 , 比如我们创建的购买操作,涉及到了用户余额表+订单表,流程顺序如下:
  1. 当前正在备份用户余额表,备份了小明同学的余额是100
  2. 此时小明刚好下了订单 , 理应扣减50元
    1. 但由于用户余额表已经备份完毕,余额表不会受到影响
  3. 小明下好单了,如今来备份订单表了,能够备份到小明刚下的单
到这里是否发现问题了,就是备份后的结果是:小明的余额没扣钱 , 但却有相关的订单数据 , 出现了数据不一致的情况