MySQL概念点整理
2021/9/8 19:06:34
本文主要是介绍MySQL概念点整理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
好久没更新随笔了。三个原因,1、工作上比较忙((*^▽^*));2、空余时间也一直在学习;3、懒
之前利用业余时间,重看了一下MySQL,在这里,特意把一些基础性的概念的东西整理一下,也算是一些初级的知识点。关于高级方面的东西,在我有时间的时候再进行整理,继而与大家分享。
1、SQL查询语句
1.1执行过程
2、SQL更新语句
2.1执行过程
- 查询语句过程
- 分析器
- 优化器
- 执行器
- 调用引擎查询接口,返回数据
- 将数据返回修改
- 调用引擎的更新接口
2.2执行过程中的关键点
- redolog
- InnoDB特有的
- WAL技术
- 先写日志后写磁盘
- 循环写
- crash-safe
- 物理日志,记录做了什么修改
- binlog
- MySQL的Server层
- 追加写
- 不具备crash-safe 的能力
- 没有记录哪些已经刷盘,哪些未刷盘
- 逻辑日志,记录语句的原始逻辑
- redolog 和 binlog 的两阶段提交
- 两阶段提交保证redolog 和binlog 的一致性
- 两阶段提交是跨系统维持数据逻辑一致性时常用的一个方案
3、事务
3.1ACID
- 原子性
- 一个事务的所有操作,要么全部成功,要么全部失败
- 一致性
- 事务前后数据的完整性必须保持一直
- 隔离性
- 读未提交
- 没有视图概念
- 读提交
- 事务中每句SQL执行钱获取视图
- 可重复读
- 事务开始时获取视图
- 串行化
- 直接用加锁的方式来避免并行访问
- 持久性
- 数据的改变永久保存在数据库中
3.2在引擎层实现
3.3InnoDB支持事务,MyISAM不支持事务
3.4事务隔离的实现(MVCC)
- undolog
- 记录回滚字段,每一个回滚段其实就是一个视图
- 当一个回滚段,也就是这个视图,以及之前的视图,没有被事务持有时,就可以删除了
- 长事务,会导致很久之前的视图无法被删除,回滚日志变的很大
3.5事务的启动方式
- 显式语句启动事务
- begin
- commit
- rollback
- start transaction
- commot
- rollback
- 非显式
- set autocommit=0
- 只要执行一个select 语句,就会开启事务,且不会自动提交
- set autocommit=1
- 只要执行一个select 语句,就会开启事务,且自动提交
4、索引(上)
4.1索引常见的数据模型
- 哈希表
- KV存储结构
- 通过索引列计算出哈希值
- 计算的哈希值作为key值
- 数据内容为value值
- key相同,拉出链表
- 特点
- 无序
- 插入简单
- 区间查询复杂,需要全部扫描
- 时间复杂度为O(N)
- 适合等值查询
- 时间复杂度为O(1)
- 有序数组
- 插入困难
- 适合静态存储引擎
- 插入需要做数据迁移
- 二分查找法
- 时间复杂度O(log(N))
- N叉树
- 平衡二叉树
- 时间复杂度O(log(N))
- B-树
- 时间复杂度O(log(N)),趋近O(1)
- B+树
- 时间复杂度O(log(N)),趋近O(1)
- 存储量
- InnoDB一个整数字段为索引,N约等于1200,树高为4的时候,可以存1200的3次方值,就是约17亿
- MySql中常见的索引
- B+树(MySQL底层是经过改进的B+树)
- 非叶子节点不存储数据,只存储键值对
- 根节点常驻内存
- 磁盘访问的数据也固定大小,InnoDB为16KB
- 哈希表
- 主键索引(聚集索引)
- 叶子节点存储郑航数据
- 普通索引(非聚集索引)
- 叶子节点存主键ID
- 查询到主键ID,再去主键索引进行检索检索的过程成为会标
- 索引维护
- B+树
- 保持有序性
- 页分裂
- 页合并
- 业务层的优化
- 使用自增主键
- 插入时追加数据,不会引起页分裂
- 逻辑删除,不会引起页合并
- 业务主键
- 最好只有一个索引
- 不需要考虑普通索引的叶子节点过大
- 如果有多个索引
- 不适合字段过长,不然会让普通索引占用空间过大
5、索引(下)
5.1回表
- 回表次数计算
- 找到一个主键ID,回表一次,计算一次回表(对于MySQL的Server层来说,是找引擎拿到的记录,得到的扫描行数,可能会比实际读取的行数要少)
- 避免回表过程
- 覆盖索引
- 联合索引
- 查询条件和查询项目都在该索引上
- 最左前缀原则
- 联合索引的最左N个字段
- 字符串索引的最左M个字段
- like 语句的使用
- 索引下推(MySQL5.6)
- 在索引内部进行条件的判断,不符合的数据直接跳过,减少回表的次数
6、全局锁和表锁
6.1全局锁
- Flush tables with read lock(FTWRL)
- 用途
- 用于做全库逻辑备份
- 弊端
- 无法更新,业务停摆
- 代替方案
- 可重复的隔离级别下,开启一个事务
- mysqldump single-transaction
- set global readonloy=true(有弊端,不建议用)
6.2表锁
- 显示表锁
- lock table ... read/write
- 元数据锁(MDL)
- 对表进行增删改数据(DML)时,自动加上MDL读锁
- 对表进行修改表结构的操作(DDL)时,会自动加上写锁
- 读锁之间不互斥
- 读写锁之间、写锁之间是互斥
- MySQL5.5引入MDL
- MDL的风险
- MDL读锁(长事务)
- MDL写锁(等待读锁释放)
- MDL读锁N个,等待写锁,线程爆满,卡死
- 解决方案
- 尝试kill 长事务
- 停掉DDL
- 事前给MDL写锁设定等待时间
7、行锁
7.1相关知识点
- 行锁时有各个引擎实现的
- InnoDB支持
- MyISAM不支持
- 行锁可以有效的控制并发
7.2两阶段锁协议
- 行锁时在需要的时候加上,事务结束时释放
- 由于两阶段锁协议,程序设计时,对并发高的行的SQL语句,尽量放在事务的后面
7.3死锁
- 概念及场景
- 事务A更新语句锁住行1
- 事务B更新语句锁住行2
- 事务A更新语句拿到行2的写锁,卡住
- 事务B更新语句拿到行1的写锁,卡住
- 死锁的解决方案
- 等待超时
- innodb_lock_wait_timeout设置具体超时时间
- 设置超时时间太长,高并发的业务无法接受
- 设置时间过短,会误杀部分正常的锁等待
- 死锁检测
- 判断自己加入是否会产生死锁的时间复杂度为O(N)
- 当访问同一行的线程较多时,例如1000个,死锁检测就是100万
- 死锁检测的关闭,可能回出现大量的超时
- 控制对行修改的并发量
- 一行变多行,负载均衡的思路
8、事务2
8.1一致性读视图(快照)consistent view
- RC读提交
- RP可重复读
8.2快照在MVCC的工作方式
- 事务ID
- 每个事务都有事务ID,事务ID严格递增
- 行数据版本ID, row trx_id
- 每行数据有可能有多个版本
- 事务在更新了该行后会将事务ID记录成改行的row trx_id
- 每个版本的数据,并非真实的物理妇女在,而是根据undolog 推算出来的
- 事务在启动后第一个SQL,拿到最新可见的row trx_id(可重复读)
- 产生了row trx_id,但是事务未提交,则不可见
- 产生了row trx_id,但是事务已经提交,则可见
- 事务在执行update语句(或行写锁语句)(可重复读)
- 重新拿到最可见的row trx_id(当前读)
- 额外说明
- 上面都是在RP可重复读的隔离级别下
- RC的隔离级别下,没一个SQL语句,都会执行当前读
这篇关于MySQL概念点整理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-15MySQL教程:初学者必备的MySQL数据库入门指南
- 2024-11-15MySQL教程:初学者必看的MySQL入门指南
- 2024-11-04部署MySQL集群项目实战:新手入门教程
- 2024-11-04如何部署MySQL集群资料:新手入门指南
- 2024-11-02MySQL集群项目实战:新手入门指南
- 2024-11-02初学者指南:部署MySQL集群资料
- 2024-11-01部署MySQL集群教程:新手入门指南
- 2024-11-01如何部署MySQL集群:新手入门教程
- 2024-11-01部署MySQL集群学习:新手入门教程
- 2024-11-01部署MySQL集群入门:新手必读指南