栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

MySQL基础篇(三)锁

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

MySQL基础篇(三)锁

目录

全局锁

概念

场景

提问

备份为什么需要加锁?

为什么不用一致性读?

为什么不使用 set global readonly = true?

表级锁

表锁

元数据锁(meta data lock,MDL)  

提问 

MDL  对小表结构变更的影响?

如何安全变更小表结构?

MDL 读读不互斥,为什么对同一张表进行更新会互斥? 

当备库用 single-transaction 做逻辑备份的时候,如果从主库的 binlog 传来一个 DDL 语句会怎么样? 

行锁

两阶段锁协议

问题

事务会锁多行,对操作进行排序? 

死锁定义/解决策略? 

如何解决热点行更新导致的性能问题? 


全局锁

概念

给整个数据库实例加锁,处于只读状态 ;数据更新语句(增删查),数据定义语句(建表修改表),更新类事务的提交语句均会被阻塞。

命令:Flush tables with read lock(FTWRL)

场景

全库逻辑备份 

主库备份:不能执行更新,业务基本停摆。

从库备份:不能执行主库同步来的 binlog,导致主从延迟。

提问

备份为什么需要加锁?

游戏购买业务:①账户余额扣除 -> ②游戏入库 

假如此时执行全库备份,并且未加锁,真正执行顺序如下:

 不加锁,备份系统得到的库不是一个逻辑时间点,视图逻辑不一致。

为什么不用一致性读?

官方自带逻辑备份工具 mysqldump,使用参数 single-transaction 时,会启动一个事务,确保拿到一致性视图。 MVCC 的支持,此时可以正常更新数据。

像 MyISAM 中引擎不支持事务,备份过程中更新,只能取到最新数据;所以 single-transaction 只适合所有表都使用事务的引擎库。

为什么不使用 set global readonly = true?

有些系统,readonly 用来判断是主库还是从库 。客户端发生异常后,整个库会一直保持 readonly 状态,会导致整个库长时间处于不可写状态;而执行 FTWRL,客户端因为异常断开后,MySQL 会自动释放全局锁,恢复正常更新状态。

表级锁

表锁

lock tables ... read/write 

会限制其他线程读写,也会限制自己。

如:lock tables t1 read, t2 write;

其他线程对 t1 只能读,对 t2 读写操作都会被阻塞。当前线程解锁前,对 t1 只能读,对 t2 只能读写。

元数据锁(meta data lock,MDL)  

MySQL5.5 引入

读锁:增删查改(读读不互斥)写锁: 表结构变更(读写/写写互斥)

提问 

MDL  对小表结构变更的影响?

MDL锁只有在事务提交时,才释放。 只要一处发生阻塞,后续所有加锁操作都会阻塞,表现为完全不可读写。

如何安全变更小表结构?

kill 掉长事务请求很频繁时,在 alter table 语句中加等待时间,超时则放弃,不阻塞后面业务;后续重试命令。 

MDL 读读不互斥,为什么对同一张表进行更新会互斥? 

在 MyISAM 上,线程 A B 要对同一张表执行更新操作(都需要 MDL读锁和表的写锁)

A 加 MDL读锁成功,加表的写锁成功。B 加 MDL读锁成功,加表的写锁失败(等待 A 释放)。所以看起来是互斥的。 

当备库用 single-transaction 做逻辑备份的时候,如果从主库的 binlog 传来一个 DDL 语句会怎么样? 

备份最重要步骤:

    获取表结构正式导数据(获取 MDL读锁)释放 MDL读锁

不同时刻到达的不同现象:

获取表结构前到达:无影响,备份拿到的为 DDL 后的结构。正式导数据前到达:表结构被改过,报错终止。释放 MDL读锁前到达:binlog 被阻塞,主从延迟,等待 MDL读锁释放。最后到达:无影响,备份拿到的为 DDL 前的结构。

行锁

两阶段锁协议

InnoDB 事务中,行锁需要时才加上,事务结束时才释放。 

问题

事务会锁多行,对操作进行排序? 

最可能造成锁冲突,最可能影响并发度的锁往后放。 

购买游戏涉及以下三种操作:

    修改用户账户余额(update)。修改平台账户余额(update)。用户游戏库添加游戏(insert)。

顺序为 3 1 2

死锁定义/解决策略?

死锁:并发系统中不同线程间存在循环资源依赖,涉及的线程都在等待其他线程释放资源,就会导致这些线程进入无限等待状态。 

策略:

设置超时时间:超时退出;时间过长,影响并发度;时间过短,容易误判。主动死锁检测:每个事务被锁住时,都要查看当前线程是否被锁住,时间复杂度为线性的 O(n);需要消耗大量 CPU 资源。

如何解决热点行更新导致的性能问题? 

临时关闭死锁检测:

确保业务不会出现死锁,可能会出现大量的超时(业务有损,死锁检测业务无损) 。

控制并发度:减少 InnoDB 内部死锁检测工作量

使用中间件实现或者修改 MySQL 源码:在进入引擎前排队。一行改成逻辑上的多行:平台账户余额记录设成十行(总额为十行之和),每次修改余额随机选择一条记录;资源数量翻倍,冲突概率也成倍降低。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/703651.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号