MySql 深入浅出之四 (数据库的锁)

锁的分类

每个数据库引擎都有自己锁的实现。例如Myisam引擎就支持表锁。因此总的来说锁分为 全局锁,表锁,行锁。 从粒度来说当然是粒度越细效率越高。但是其实每一种锁都有自己的使用场景。 

  1. 全局锁:可以是整个数据库属于只读状态。 因此可以用来做全局逻辑备份。
  2. 表锁:表锁分为两种一种是表锁,一种是元数据所(meta data lock,MDL)
    表锁的语法是:lock tables ... read/write
    可以用unlock tables主动释放锁,也可以在客户端断开的时候自动释放。lock tables语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。
    对于InnoDB这种支持行锁的引擎,一般不使用lock tables命令来控制并发,毕竟锁住整个表的影响面还是太大。
    MDL:不需要显式使用,在访问一个表的时候会被自动加上。
    MDL的作用:保证读写的正确性。
    在对一个表做增删改查操作的时候,加MDL读锁;当要对表做结构变更操作的时候,加MDL写锁。
    读锁之间不互斥。读写锁之间,写锁之间是互斥的,用来保证变更表结构操作的安全性。
    MDL 会直到事务提交才会释放,在做表结构变更的时候,一定要小心不要导致锁住线上查询和更新。、
  3. 行锁:并不是所有的引擎都支持行锁,比如Myisam就不支持行锁。 这也是Myisam被InnoDb替代的一大原因。下面会重点介绍一下行锁被什么因素影响效率。

行锁的效率:

  1. 影响行锁效率的因素1为两阶段锁:在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放, 而是要等到事务结束时才释放。因此如果在一个事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。
  2. 当两个不同的事务都在等待对方事务释放锁,那么就会出现死锁。当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态。
    解决方案:
    a、通过参数 innodb_lock_wait_timeout 根据实际业务场景来设置超时时间,InnoDB引擎默认值是50s。
    b、发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑(默认是开启状态)。
    如何解决热点行更新导致的性能问题?
    a、如果你能确保这个业务一定不会出现死锁,可以临时把死锁检测关闭掉。一般不建议采用
    b、控制并发度,对应相同行的更新,在进入引擎之前排队(可以使用合适的队列中间件进行排队)。这样在InnoDB内部就不会有大量的死锁检测工作了。
    c、将热更新的行数据拆分成逻辑上的多行来减少锁冲突,但是业务复杂度可能会大大提高。
  3. 重点:innodb行级锁是通过锁索引记录实现的,如果更新的列没建索引是会锁住整个表的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值