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概念点整理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程