MYSQL系列之 锁与死锁

MySQL 里面的锁大致可以分成全局锁、表级锁和行锁三类

全局锁

MySQL 提供了一个加全局读锁的方法,命令是 Flush tables with read lock (FTWRL)。
当你需要让整个库处于只读状态的时候,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。

风险:
1.如果在主库备份,在备份期间不能更新,业务停摆
2.如果在从库备份,备份期间不能执行主库同步的binlog,导致主从延迟
可重复读的隔离级别,可以让同一个事务拿到一致性视图,这个过程由MVCC支持 ,(MyISAM 不支持此事务所以需要FTWRL

表级锁

表锁:lock tables … read/write
元数据锁(MDL meta date lock): MDL 不需要显式使用,在访问一个表的时候会被自动加上

MDL 锁是系统默认会加的,给一个表加字段,或者修改字段,或者加索引,需要扫描全表的数据。而且事务中的 MDL 锁,在语句执行开始时申请,但是语句结束后并不会马上释放,而会等到整个事务提交后再释放
MDL 保证读写的正确性
当对一个表做增删改查操作的时候,加 MDL 读锁;当要对表做结构变更操作的时候,加 MDL 写锁。

行级锁

两阶段协议:
在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。

针对两阶段协议做的优化
顾客在电影院买票的大概流程:
1、顾客账户余额中扣除票钱
2、给影院增加账户余额
3、记录一条交易日志

可见,多名客户购买,需要修改的都会集中在步骤2,所以调整顺序 3、1、2,最大程度减少事务中停留的时间

死锁、死锁检查

诱因:不同线程循环资源依赖
在这里插入图片描述
事务 A 在等待事务 B 释放 id=2 的行锁,而事务 B 在等待事务 A 释放 id=1 的行锁。 事务 A 和事务 B 在互相等待对方的资源释放,就是进入了死锁状态。当出现死锁以后,有两种策略:
1、一种策略是,直接进入等待,直到超时。这个超时时间可以通过参数 innodb_lock_wait_timeout 来设置。InnoDB默认50s
2、另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑。
注: 死锁检查耗费大量的CPU资源。

死锁检查:

每当一个事务被锁的时候,就要看看它所依赖的线程有没有被别人锁住,如此循环,最后判断是否出现了循环等待,也就是死锁。

总结

mysql的行锁触发的死锁与死锁检测
死锁策略:1、设置超时时间,默认50s 2、死锁检查(高并发CPU大量消耗)
热点行更新性能问题:
1、临时关闭死锁检查
2、应用层阻塞队列、数据库层阻塞队列
3、逻辑上多行减少锁冲突(业务复杂解决锁冲突)
4、调整事务中逻辑顺序

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值