MySQL----InnoDB表级锁、死锁以及锁的优化条件

InnoDB表级锁

在绝大部分情况下都应该使用行锁,因为事务和行锁往往是选择InnoDB的理由,但个别情况下也使用表级锁;

  • 事务需要更新大部分或全部数据,表又比较大,如果使用默认的行锁,不仅这个事务执行效率低,而且可能造成其他事务长时间等待和锁冲突;
  • 事务涉及多个表,比较复杂,很可能引起死锁,造成大量事务回滚。
    如:
    LOCK TABLE user READ;读锁锁表
    LOCK TABLE user WRITE; 写锁锁表
    事务执行…
    COMMIT/ROLLBACK; 事务提交或者回滚
    UNLOCK TABLES; 本身自带提交事务,释放线程占用的所有表锁

死锁

死锁是指多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。死锁产生的4个必要条件:

  • 互斥条件:进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某 资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。

  • 不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。

  • 请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源 已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。

  • 循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被 链中下一个进程所请求

MyISAM 表锁是 deadlock free 的, 这是因为 MyISAM 总是一次获得所需的全部锁,要么全部满足,要么等待,因此不会出现死锁。但在 InnoDB 中,除单个 SQL 组成的事务外,锁是逐步获得的,即锁的粒度比较小,这就决定了在 InnoDB 中发生死锁是可能的。

在这里插入图片描述
注意:

  • 事务被阻塞了,或者死锁了,mysqld是有事务阻塞的超时时间,事务处理失败!
  • mysqld直接能够监测到死锁问题的发生,并进行事务的回滚操作!!!
  • 死锁问题一般都是我们自己的应用造成的,和多线程编程的死锁情况相似,大部分都是由于我们多个线程在获取多个锁资源的时候,获取的顺序不同而导致的死锁问题。因此我们应用在对数据库的多个表做更新的时候,不同的代码段,应对这些表按相同的顺序进行更新操作,以防止锁冲突导致死锁问题。

多个事务/线程,获取多个相同资源锁的时候,应该按照同样的顺序,获取资源的锁!这样就不会发生死锁问题。

锁的优化建议

  1. 尽量使用较低的隔离级别
  2. 设计合理的索引并尽量使用索引访问数据,使加锁更加准确,减少锁冲突的机会提高并发能力
  3. 选择合理的事务大小,小事务发生锁冲突的概率小
  4. 不同的程序访问一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序存取表中的行。这样可以大大减少死锁的机会
  5. 尽量用相等条件访问数据,这样可以避免间隙锁对并发插入的影响
  6. 不要申请超过实际需要的锁级别
  7. 除非必须,查询时不要显示加锁
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值