高并发,高性能,高可用MySQL 实战-如何处理数据更新
1. 数据库动起来之后,会发生什么?
- 数据库日志
- 客户端之间因为锁而互相影响
总结,数据库动起来之后会产生一些列性能问题
需要理解日志、锁、事务的底层原理,才能应对问题
2. 什么日志不是给人看的
- mysql日志体系
- mysql为了满足主从复制,事务等, 有复杂的日志体系
- server层产生的binlog日志,用来进行数据复制
- InnoDB产生的undo log和redo log 用来实现事务ACID
- mysql的日志体系不是主要用来看的,而是运行必要的
-
binlog归档日志
-
undo log回滚日志
-
redo log重做日志
一条数据是如何更新的
-
redo log刷盘
-
bin log刷盘
-
持久化分析
-
为什么redo log在bin log之前
总结:
怎么平衡功能与性能
锁
-
全局锁
-
表锁
-
元数据锁
-
行锁
加锁流程图
总结:锁是mysql高效执行事务的必备基础,锁会引发很多性能问题如等待或死锁,锁还会引发很多功能问题脏读和不可重复读
InnoDB的杀手锏ACID
InnoDB的杀手锏(事务隔离级别)
- 读未提交 read uncommitted
- 读提交 read committed
- 可重复读 repeatable read
- 串行化 serializable
总结:事务是InnoDB最核心的功能点,事务是使mysql和InnoDB最流行的影响点,事务也是引发性能问题最多的点
因为事务涉及到了日志,涉及到了锁
MVCC是怎么做到千人千面的
-
快照度(一致性非锁定读)
-
当前读(一致性锁定读)
- 读已提交和可重复读都是快照度,而串行化是当前读
- 隔离问题
- 脏读:读到了其它事务未提交的数据
- 不可重复读:同样的查询读到的数据内容不一样
- 幻读:同样的查询读到了更多的数据
-
mysql不同隔离级别的问题
-
如何解决幻读问题
- mysql在可重复读级别时,通过next-key锁部分解决了幻读问题
- Next-Key锁是行锁+间隙锁
- 间隙锁的功能与行锁相同,只是针对间隙加锁
- 间隙锁不分读写,也可以认为是读锁,不允许在间隙插入
- 可重复读加锁时,将同时锁住数据和左右间隙
总结:
- InnoDB使用undo log实现了行记录历史查询
- 快照度不需要加行锁,属于乐观锁的一种思路
- 当前读需要加行锁,为了并发控制
- Next-Key Lock解决了可重复读下的幻读问题
间隙锁把全表都锁住了怎么办
- Next-Key lock的加锁逻辑
总结:
目的:在可重复读的隔离级别下部分预防幻读
手段:Next-Key lock(行锁+间隙锁)
特点:规则复杂,个人认为并不优雅
注意:当前读时,不要查询没有索引的项目,有可能导致全表上锁。
mysql也有垃圾回收吗
- mysql并没有所谓的垃圾回收
- 但是会发现数据库卡几秒,磁盘IO很高
- 此时mysql正在刷脏页
- mysql脏页的产生
- 什么是刷脏
- 为什么要刷脏
- 内存中的脏页太多,内存不足
- redo log文件写满,需要推进check point
- 系统空闲,提前刷脏,预防上述情况
- mysql关闭前,保存数据
- 前两种会产生性能问题,导致mysql卡住
如何避免被迫刷脏
- 正确告知InnoDB,服务器的硬盘性能
- 配置合理的脏页比例上线
- 控制顺便刷脏策略
-
服务器IO配置
-
配置合理的脏页比例上线
-
控制"顺便刷脏"策略
总结:
如何解决死锁问题
- 长事务的危害
-
锁无法释放
-
死锁是如何产生的
元数据锁是如何导致数据库崩溃的
- MDL锁
- 事务访问数据时,会自动给表加MDL读锁
- 事务修改元数据时,会自动给表加MDL写锁
-
如何查看影响性能的锁
-
业务上的建议
- 控制长事务,没有必要的情况下不开启事务
- 数据修改(当前读),尽量放在事务后部,降低锁时间
总结:
- 长事务可能会造成行锁死锁,MDL锁等待
- 可以通过参数调整,降低锁影响
- 可以通过系统表识别长事务和锁
- 业务上尽量将加锁的操作后移,降低锁时间