mysql高级(尚硅谷周阳)

mysql高级

    • mysql的架构分析
    • sql优化分析
      • 性能下降sql慢
      • join分析
    • 索引
      • 索引数据结构及原理
      • 那些情况需要建立索引
      • 那些情况不要建立索引
      • 性能分析
      • 索引优化
      • 查询截取分析
      • 慢查询日志
    • 数据库锁
    • 主从复制
    • 事务、MVCC
        • MVCC
        • ACID的实现原理
          • 原子性
          • 一致性
          • 隔离性
          • 持久性
      • 一条sql的执行流程
        • 对于查询语句
        • 对于更新语句
    • 总结
      • mysql Innodb随笔
      • 行锁的三种算法

mysql的架构分析

  • mysql 高级(包括) (很多公司的mysql的优化有专门的DBA)
    • Mysql高级
    • sql优化攻城狮
    • mysql服务器的优化
    • 各种参数常量的设定
    • 查询语句优化
    • 主从复制
    • 软硬件升级
    • 容灾备份
    • sql编程
  • 这里注意视频那个启动mysql老了应该用 service mysqld start
  • mysql逻辑架构
    mysql高级(尚硅谷周阳)_第1张图片
  • mysql支持多种存储引擎
  • 与其他数据库相比, mysql有点与众不同, 他的架构可以在多种不同场景中应用并发挥良好的作用, 主要体现在存储引擎的架构下, 插件式的存储引擎架构将查询处理和其他的系统任务以及数据的存储提取和分离, 这种架构可以根据业务的需求和实际需要选择合适的存储引擎。
  • 连接层 mysql高级(尚硅谷周阳)_第2张图片
    mysql高级(尚硅谷周阳)_第3张图片

mysql高级(尚硅谷周阳)_第4张图片

sql优化分析


性能下降sql慢

  • 出现的两种可以划分的情况
    1、执行时间长
    2、 等待时间长
  • 查询语句写的烂
  • 索引失效
    • 索引分为单值索引以及复合索引
    • 单值索引
      create index idx_user_name on user(name)
  • 关联查询太多join(设计缺陷或不得已的需求)
  • 服务器调优及各个参数的设置(缓冲、线程数等)

join分析

  • sql执行顺序
    • 手写的mysql高级(尚硅谷周阳)_第5张图片
  • 机器
    mysql高级(尚硅谷周阳)_第6张图片
    • 机器sql执行总结
      mysql高级(尚硅谷周阳)_第7张图片
  • join
    在这里插入图片描述

索引


索引:

  • 是帮助Mysql高效获取数据的数据结构。 可以得到索引的本质: 索引是数据结构。
  • 提高查找效率, 可以类比字典。
  • 排好序的快速查找数据结构, 会影响条件和orderby
    在数据之后, 数据库系统还维护着满特定查找算法的数据结构, 这些数据结构以某种方式引用数据, 这样就可以在这些数据结构上实现高级查找算法, 这种数据结构, 就是索引。
    mysql高级(尚硅谷周阳)_第8张图片
  • 索引本身也很大, 不可能全部存储到内存中, 因此索引往往以索引文件的形式存储在磁盘上。
  • 我们平常所说的索引, 如果没有特别指明, 都是指B树(多路搜索树)组织结构的索引, 其中聚集索引, 次要索引, 复合索引, 前缀索引, 唯一索引默认都是使用B+树索引, 统称索引, 当然, 除了B+树这种类型的索引之外, 还有hash索引。
  • 对于MyISAM来说索引跟数据是分开放的, 有三个文件 结构数据和索引, 索引的数据部分为表数据的物理地址, 先查到索引如果要查数据, 还要再一次访存。
  • 对于INNOdB引擎, 有且必须有一个聚集索引, 一般是主键, 数据和聚集索引放到一起, 如果没有主键, 找第个不为NULL的唯一列, 如果还没有Innodb会给加一个隐藏列作为聚集索引。而其他索引的数据部分都是聚集索引, 通过聚集索引找到目标的位置。
  • 对于Innodb索引建议用自增的int数据作为主键, 原因:首先int比varchar()较为好比较, 其次int比varchar()省空间。 为什么要自增的呢: 原因: 对于B+树来说数据全在叶子节点上, 其次在叶子节点上从左到右是有序的双链表,而自增会顺序的添加到一页中, 这样会使b+树的分裂次数减少, 而如果使随机的, 由于B+必须保持叶子节点的有序所以, 就要查到B+树叶子节点的中间故就会导致B+树不必要的分裂, 则会导致性能较差, 当进行随机插入它的分裂是取页的中间的, 这样就会导致数据内部碎片, 而且分裂需要三个页的移动和加载。
    • 自增的主键的值是顺序的,所以Innodb把每一条记录都存储在一条记录的后面。当达到页面的最大填充因子时候(innodb默认的最大填充因子是页大小的15/16,会留出1/16的空间留作以后的修改):
    • ①下一条记录就会写入新的页中,一旦数据按照这种顺序的方式加载,主键页就会近乎于顺序的记录填满,提升了页面的最大填充率,会有页的浪费
    • ②新插入的行一定会在原有的最大数据行下一行,mysql定位和寻址很快,不会为计算新行的位置而做出额外的消耗
    • ③减少了页分裂和碎片的产生 参考博客
  • 优势: 提高数据索引的效率, 降低数据库IO成本,降低数据排序的成本, 降低了cpu的消耗。
  • 缺点: 实际上索引也是一张表, 该表保存了主键与索引字段, 并指向实体表的记录, 所以索引列也是要占用空间的。虽然索引大大提高了查询速度, 同时却会降低更新表的速度, 如对表进行INSERT、update、delete。因为更新表时, 不仅要保存数据, 还要保存以下索引文件每次更新添加了索引列的字段, 都会调整因为更新带来的键值变化的索引信息。索引只是提高效率的一个因素, 如果mysql有大量的数据, 就要花时间建立最优秀的索引。
  • 索引分类
    • 单值索引
      即一个索引只包含单个列, 一个表可以有多个单列索引。一张表的索引一般不要超过5个
    • 唯一索引
      索引列的值必须唯一, 但允许有空值
    • 复合索引
      一个索引包含多个列
      对于复合(联合)索引来说, 排序是先按第个排, 如果第一个相同的时候才会按第二个排, 接着, 这也是为什么索引要遵循最左原则。
    • 基本语法
      create 【UNIQUE 加唯一索引】Index indexName On mytable(名字)
      表级建立
      Alter table add [unique] index indexname on table(名字)
      查看 show index from table
      mysql高级(尚硅谷周阳)_第9张图片

索引数据结构及原理

  • 原理
    mysql高级(尚硅谷周阳)_第10张图片
    mysql高级(尚硅谷周阳)_第11张图片

那些情况需要建立索引

1、主键自动建立聚簇索引
2、频繁作为查新条件的字段应该创建索引
3、查询中与其他表关联的字段, 外键关系建立索引。
4、频繁更新的字段不适合创建索引
5、Where条件里用不到的字段不创建索引
6、 单键/组合索引的选择问题
7、查询中排序字段, 排序字段若通过索引去访问将大大提高排序速度。
8、查询中统计或者分组字段(分组之前必排序)

那些情况不要建立索引

1、表记录少
2、经常增删改的表: 提高了查询速度, 降低了更新表的速度, 更新表的时候还要改变索引文件
3、数据重复且分布平均的字段
mysql高级(尚硅谷周阳)_第12张图片

性能分析

  • mysql Query Optimizer(查询优化器)
    mysql高级(尚硅谷周阳)_第13张图片
  • 常见瓶颈:
    • cpu: cpu在饱和的时候一般发生在数据装入内存或从磁盘上读取数据的时候
    • IO:磁盘I/O瓶颈发生在装入数据远大于内存容量的时候
    • 服务器硬件的性能瓶颈:
  • Explain
    • 使用EXPLAIN关键字可以模拟优化器执行SQL查询语句, 从而直到MYSQL时如何处理你的sql语句的。分析你的查询语句或时表结构的性能瓶颈
    • 用法: explain + sql语句
    • 用来做什么:
      • 表的读取顺序
      • 数据读取操作的操作类型
      • 那些索引可以使用
      • 那些索引被实际使用
      • 表之间的引用
      • 每张表有多少行被优化器查询
    • 执行计划包含的信息
      在这里插入图片描述
      • id: select 查询的序列号, 包含一组数字, 标识查询中执行select子句或操作表的顺序
        • 三种情况:
          • id相同, 执行顺序由上到下
          • id不同, id的序号递增, id值越大优先级越高, 越先被执行。
            mysql高级(尚硅谷周阳)_第14张图片
        • id 相同还存在不同, 数字大的先执行, 相同的从上到下 derived = 内部衍生的虚表
          mysql高级(尚硅谷周阳)_第15张图片
      • select_type: 查询的类型, 主要用于区别普通查询, 联合查询, 子查询等复杂的查询
        • simple : 简单的select查询, 查询中不包含子查询和UNION
        • primary 查询中若包含任何复杂的子部分, 最外层查询被标记为primary
        • subquery: 再select或where列表中包含了子查询
        • derived: 再from列表中包含的子查询被标记为DERived, MYSQL会递归执行这些子查询, 把结果放到临时表中。
        • UNION 若第二个select出现在UNION之后, 则被标记为UNION, 若union包含在from子句的子查询中, 外层select将被标记为DERIVED;
        • union RESULT: 从union表获取结果的select
    • table: 这一行数据是那张表
    • type: 访问类型 取值有:ALL、 index、 range、 ref、 eq_Ref、 const, system
      • 从好到差: system > const > eq_ref > ref > range >index > all
      • system: 表只有一行记录(等于系统表), 这是const类型的特列, 平时不会出现, 这个也可以忽略
      • const :
        (1)命中主键(primary key)或者唯一(unique)索引;
        (2)被连接的部分是一个**常量(const)**值;
      • eq_ref: 唯一性索引扫描, 对于每个索引键, 表中只有一条记录与之匹配, 常见于主键或 唯一索引扫描
        • join查询;
        • 命中主键(primary key)或者非空唯一(unique not null)索引;
        • 等值连接;
        • eq_ref扫描的条件为,对于前表的每一行(row),后表只有一行被扫描(与当前本行只有一条记录对应)(且后表是主键或者唯一为连接条件)。
      • ref:非唯一性索引 与eq_ref相同唯一一点就是后边的连接条件只是普通的索引不是唯一索引。
      • range: 再索引列的范围查询。(select * from user where id>3;)
      • index: index类型,需要扫描索引上的全部数据。只遍历索引树, 通常索引文件都比数据文件小
      • ALL: 全表扫描
    • possible_keys: 理论上是否用到索引, 或者使用了那个索引。显示可能应用在这张表中的索引, 一个或者多个。 查询涉及到的字段上若存在索引, 则该索引列被列出, 但不一定被查询实际使用, (初步推测要使用的索引)
    • keys: 实际使用的索引。 如果为NULL, 则没有使用索引。 查询中若使用了覆盖索引, 则该索引仅出现再key列表中(不会出现再possible_keys)。
      * 查询的字段与建的复合索引的顺序和个数一致, 就叫覆盖索引
      *keys_len: 表示索引中使用的字节数, 可以通过该列计算查询中使用的索引长度。 再不损失精确度的情况下, 长度越短越好, key_len显示的值为索引字段的最大可能长度, 并非实际使用长度, 即key_len是根据表定义计算而得, 不是通过表内检索出的, where后跟的索引条件的长度。 只指示where用于条件过滤的时候选中的索引列
      • 对于varchar
        公式:
        key_len = 定义长度*3 + NULL(1)+可变(2)
      • 对于char是 key_len = 定义长度*3 + NULL(1)
      • a、一般地,key_len 等于索引列类型字节长度,例如int类型为4-bytes,bigint为8-bytes;
      • b、如果是字符串类型,还需要同时考虑字符集因素,例如:CHAR(30) UTF8则key_len至少是90-bytes;
      • c、若该列类型定义时允许NULL,其key_len还需要再加 1-bytes;
      • d、若该列类型为变长类型,例如 VARCHAR(TEXT\BLOB不允许整列创建索引,如果创建部分索引,也被视为动态列类型),其key_len还需要再加 2-bytes;
    • ref 字段表示 和另一表进行表连接的实际用到的索引字段,const代表是常量值连接
    • rows : 根据表统计信息及索引选用情况, 大致估算出找出所需记录所需要的读取的行数 越小越好
    • extra: 其他额外重要的信息。
      • usering filesort: mysql会对数据使用一个外部的索引排序, 而不是按照表内的索引顺序进行读取。 mysql中(使用了索引)但是无法利用索引完成的排序操作称为“文件排序” 没有建索引orderby肯定是useing filesort, 建了索引要遵循最左原则从左到右,有左边才能有右边不能断, 另外挑选的列也应该是索引列。否则就会出现

        • use temporary: 使用了临时表保存中间结果, mysql再对查询结果排序时使用了临时表。 常见于排序orderby和分组查询groupby
      • useing index, 使用了覆盖索引, 避免访问变得数据行, 如果同时出现useing where, 表面索引用来执行索引键值的查找, 如果没有就是用来读取数据

        • 没有主键和非空唯一键, innodb会自动生成自增列作聚集索引
        • 聚集索引 是要具有唯一性的字段,比如:主键、唯一索引(unique index)所在字段,虽然id不在复合索引里头,但是mysql里所有的二级索引的叶子节点,都会存储聚簇索引的信息,而id是主键,所以所有的叶子节点,都会有id的信息,因此还是可以走覆盖索引。
          在这里插入图片描述
          在这里插入图片描述
      • usering where 使用了where

      • 查询内容不在索引内,where条件是索引最左列,extra为using where,type是ref,因为where的索引列是有序的,所以走了ref,又因为查询内容不在索引内,所以没有using index,因为产生了过滤,所以有using where。

      • useing join buffer: 使用了缓存

      • impossible where : false, 不符合逻辑, 不能获取任何元素。

索引优化

  • 索引优化

    • 范围字段后面的复合索引失效(中间不能断)
      mysql高级(尚硅谷周阳)_第16张图片
      mysql高级(尚硅谷周阳)_第17张图片
    • 外连接: 左连接建在右边, 右连接建在左边。
    • 内连接: 小表驱动大表, 索引建在大表上 索引最好设置在需要经常查询的字段中
    • join语句优化
    • 可能减少join语句中的循环总次数: “永远用小结果集驱动大的结果集”
    • 优先优化内层语句
    • 保证Join语句中被驱动表上Join条件字段已经被索引
    • 当无法保证被驱动表的Join条件字段被索引且内存资源充足的前提下, 不要太吝啬JoinBuffer的设置
    • 当两个出现可供选择的两个索引的会走索引区分度较高的
      mysql高级(尚硅谷周阳)_第18张图片
      mysql高级(尚硅谷周阳)_第19张图片
  • 索引失效(应该避免)

    • 如何避免?
      • 全值匹配我最爱: 就是利用符合索引进行等值符合索引全用。
      • 最佳左前缀法则: 如果索引了多列, 要遵循最左前缀法则, 指的是查询从索引的最左前列开始并且不跳过索引中的列。, 老大不能死, 中间不能断
      • 不要再索引列上做任何操作(计算、函数、(自动或者手动)类型转换), 会导致索引失效而转向全表扫描。
      • 存储引擎不能使用索引中范围条件右边的列。: 范围之后全失效。
      • 尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)), 减少select *
      • mysql在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描
      • isnull, is not null也无法使用索引
      • like以通配符开头的(‘%abc…’)mysql索引失效会变成全表扫描。 尽量加在右边 当%在右边的时候后面的索引还是能使用到。
        • 如何解决like左右通配符, 利用覆盖索引解决
      • 字符串不加单引号索引失效
      • 少用or, 用它来间接时会索引失效 改为in
    • 建议:mysql高级(尚硅谷周阳)_第20张图片
      mysql高级(尚硅谷周阳)_第21张图片
      mysql高级(尚硅谷周阳)_第22张图片

查询截取分析

  • 分析
    1、慢查询的开启并捕获
    2、 explain+慢Sql分析
    3、 show profile查询sql在mysql服务器里面的执行细节和生命周期的情况
    4、 Sql数据库服务器的参数调优
  • 小表驱动大表:
    mysql高级(尚硅谷周阳)_第23张图片
    在这里插入图片描述
  • orderby排序的优化
    • 尽量使用index排序, 避免using filesort
    • orderby默认升序。 复合索引如果一个是升一个是降就会出现内排序, 同是升跟同是降都可以。
    • 文件排序又分为: 单路排序和双路排序
      • 双路排序(又称回表): 两次扫描磁盘, 得到数据, 读取行指针和orderby列, 对他门进行排序, 然后扫描已经排好序的列表,按照列表中的值重新从列表中读取对应的数据输出, 从磁盘取排序字段, 在buffer进行排序, 再从磁盘中取其他字段
      • 单路算法: 从磁盘中读取查询的所有列, 按照orderby列在buffer对它们进行排序, 然后扫描排序后的列表进行输出因为它的效率更快一些, 避免了第二次读取数据。 并且把随机IO变成了顺序IO, 但是它会使用更多的空间,因为它把每一行都保存在内存中。
      • 结论总结: 总的来说单路比双路好但是
      • 至于mysql优化器使用双路排序还是单路排序是有自己的算法判断的,如果查询的列字段大于max_length_for_sort_data变量,则会使用双路排序,反之则会使用单路排序,单路排序速度是更快的,不过比较占据内存,如果在内存空间允许的情况下想要使用单路排序的话,可以增加max_length_for_sort_data变量的大小,max_length_for_sort_data变量默认为1024字节。
        mysql高级(尚硅谷周阳)_第24张图片
        mysql高级(尚硅谷周阳)_第25张图片
      • 第四
        • MYsql两种排序方式: 文件排序或扫描有序索引排序
        • Mysql能为排序与查询使用相同的索引。
          mysql高级(尚硅谷周阳)_第26张图片
      • groupby优化
        mysql高级(尚硅谷周阳)_第27张图片

慢查询日志

  • mysql的慢查询日志mysql的日志, 它用来记录mysql中响应时间超过了阈值的语句, 具体指运行时间超过long_query_time值的SQL, 则会被记录到慢查询日志中。默认为10
  • 默认情况下, MYsql数据库没有开启慢查询的功能, 如果不是调优需要, 一般不启动
  • 查询开启 SHOW VARIABLES LIKE ‘%slow_query_log%’; 开启反射光hi set global slow_query_log = 1;
  • 查询日志分析工具 mysqldumpslow --help.
    mysql高级(尚硅谷周阳)_第28张图片
  • show Profile;
    • 是mysql提供可以用来分析当前会话语句执行的资源消耗情况, 可以用于SQL的调优的测量
    • show profile cpu, block, io for query ID;
    • show profiles; 查询所有执行过的sql
    • 结论:.
      看:
      mysql高级(尚硅谷周阳)_第29张图片
  • 全局查询日志

数据库锁

  • 锁时计算机协调多个线程或进程并发访问共享资源的机制
  • 锁的分类
    • 对数据操作的类型分为:
      • 读锁(共享锁): 针对同一份数据, 多个读操作可以同时进行而不会互相影响
      • 写操作(排他锁): 当前写操作没有完成前, 它会阻断其他写锁和读锁。
    • 对数据操作的粒度分为:
      • 行锁
      • 写锁
    • 三锁
      • 表锁(偏读)
        • 偏向MyISAM存储引擎, 开销小, 无死锁, 锁定的力度大, 发生所冲突的概率最高, 并发度最低
        • 手动加表锁: lock table 表名字 read(write), 表名字2 read(write);unlock tables;
          • 对于一个会话加了表锁的读锁的话,
            • 这个会话可以查看锁的表, 另一个会话也能查看锁的表
            • 自己的会话不能修改自己加读锁的表(因为写锁时排他锁, 写的时候不能有其他锁), 另一个会话修改 当前表会被阻塞,直到表被解锁
            • 自己的会话也不能查看其他的表, (只有把当前表锁给释放了才能操作其他表)。
            • 读锁可共享, 其他会话修改阻塞
          • 加写锁
            • 本会话可以读, 不能读其他表
            • 本会话可以写
            • 其他会话不论时读还是写 都是阻塞
              mysql高级(尚硅谷周阳)_第30张图片
          • 结论: 就是读锁会阻塞写, 但是不会阻塞读, 而写锁则会把读和写都堵塞。
          • 查看:
            mysql高级(尚硅谷周阳)_第31张图片
        • Myisam的读写锁调度是写有优先, 这也是myisam不适合做写为主的引擎, 因为写锁后, 其他线程不能做任何操作, 大量的更新会使查询很难得到锁,从而造成永远阻塞。
      • 行锁(偏写)
        • 偏向InnoDB存储引擎, 开销大, 加锁慢, 会出现死锁, 锁定的粒度最小, 发生锁的冲突的概论最低, 并发度也最高。Innodb与MyISAM的最大不同就是一是支持事务, 二是采用了行级锁。
        • 事务的4个属性
          mysql高级(尚硅谷周阳)_第32张图片
          • 在一个会话的事务中数据库默认的隔离级别是RpeatedRead
          • 行锁只要是不同行都没事
          • 当一个会话更新这一行但是不提交, 另一个如果想更新这一行就只能阻塞
          • 索引失效很容易导致行锁升级为表锁(varchar不写单引号很容易造成)
          • 间隙锁: 当我们用范围条件而不是相等条件作为检索数据, 并请求共享或排他锁时, InnoDB会给符合条件的已有数据记录的索引加锁, 对于键值在条件范围内但并不存在的记录, 叫做间隙 Innodb也会对这个间隙加锁, 这种锁机制就是所谓的间隙锁。
            • 危害: 因为在Query执行过程中通过范围查找的话, 他会锁定整个范围内所有的索引键值, 即使这个键值并不存在。 弱点: 当锁定一个范围的键值之后, 即使某些不存在的键值也会被无辜的锁定, 而造成在锁定的时候无法插入锁定键值范围内的任何数据, 在某些场景下这可能对性能造成巨大的影响
          • 如何锁定一行?
            • 第一步 begin 第二部 select * from table where 行 for update 第三步commit
              mysql高级(尚硅谷周阳)_第33张图片
        • 总结: Innodb存储引擎由于实现了行级锁定, 虽然在锁定机制的实现方面所带来的性能的损耗可能比表级锁定会更高一些, 但是在整体并发处理能力方面要远远由于MyIsam的表级锁定的, 当系统并发量较高的时候, Innodb的整体性能和MyIsam相比就会有比较明显的优势了。 但是, Innodb的行级锁定同样有其脆弱的一面, 当我们使用不当的时候, 可能会让Innodb的整体性能表现不仅不能比MyIsam高甚至更差
        • 查看各个状态 show status like ‘innodb_row_lock%’
          mysql高级(尚硅谷周阳)_第34张图片
        • 优化建议
          mysql高级(尚硅谷周阳)_第35张图片
      • 页锁

主从复制

  • 复制的基本原理:
    • slave会从master读取binlog来进行数据同步
    • 原理:
      mysql高级(尚硅谷周阳)_第36张图片
  • 复制的原则
    • 每个slave只有一个master
    • 每个slave只能由一个唯一的服务器Id
    • 每个master可以有多个slave
  • 配置:
    • server-id :必须配主服务器的唯一Id
    • log-bin=自己本地的路径/mysqlbin 必须启用二进制日志
      mysql高级(尚硅谷周阳)_第37张图片
  • 从机必选 服务器唯一ID

事务、MVCC

MVCC

  • 多版本并发控制利用其原理提升读写效率
  • 当前读: 读取的是数据的最新版本, 总是读取到最新的数据、
    • select …lock in share mode 加读锁
    • select … for update
  • 快照读:读取的是历史版本的记录
    mysql高级(尚硅谷周阳)_第38张图片
  • MVCC的实现原理
    mysql高级(尚硅谷周阳)_第39张图片
  • 第二部分: undolog(回滚日志)
    • 它存的是历史版本状态, 当非创建事务进行修改, 会在uodolog存一个上个版本的历史记录
      mysql高级(尚硅谷周阳)_第40张图片
      mysql高级(尚硅谷周阳)_第41张图片
      在这里插入图片描述
    • 现在有了事务4, 那么事务4读取到的数据是那个版本的数据? 看事务的开启时间
  • 第三部分
    • readView : 事务在进行快照读的时候产生的读视图(在进行读的时候才会出现读视图, 所以能否读到, 取决于第一次读的时间)
      在这里插入图片描述
      mysql高级(尚硅谷周阳)_第42张图片
      在这里插入图片描述

mysql高级(尚硅谷周阳)_第43张图片

ACID的实现原理

原子性

靠undolog来实现的

一致性

其他三个特性共同实现了一致性。

隔离性

通过: MVCC实现

持久性

通过:redolog来实现
对于redolog有一个二阶段提交:

mysql高级(尚硅谷周阳)_第44张图片
mysql高级(尚硅谷周阳)_第45张图片

mysql高级(尚硅谷周阳)_第46张图片

  • 使用两阶段提交,
    • 当主机在写完redolog会把redolog置为prepare断电了, 恢复的时候先从binlog开始, 而binlog没有数据, 再去处理redo有数据且状态为prepare状态, 直接回滚。
    • 当在binlog后断电了在redolog以及binlog都找到了, 就把redo prepare提交
  • 这个不用两阶段提交会出现的错误
    mysql高级(尚硅谷周阳)_第47张图片
  • 如果一个事务的全部操作都是快照读那么不会出现幻读, 如果当前读和快照读就有可能出现幻读。

一条sql的执行流程

  • server 层是不管执行器是什么都是共用的它分为
    • 连接器
      连接器主要和身份认证和权限相关的功能相关,就好比一个级别很高的门卫一样。主要负责用户登录数据库,进行用户的身份认证,包括校验账户密码,权限等操作,如果用户账户密码已通过,连接器会到权限表中查询该用户的所有权限,之后在这个连接里的权限逻辑判断都是会依赖此时读取到的权限数据,也就是说,后续只要这个连接不断开,即时管理员修改了该用户的权限,该用户也是不受影响的。
    • 查询缓存(mysql8.0删除)
    • 分析器
      MySQL 没有命中缓存,那么就会进入分析器,分析器主要是用来分析 SQL 语句是来干嘛的,分析器也会分为几步:
      • 第一步,词法分析,一条 SQL 语句有多个字符串组成,首先要提取关键字,比如 select,提出查询的表,提出字段名,提出查询条件等等。做完这些操作后,就会进入第二步。
      • 第二步,语法分析,主要就是判断你输入的 sql 是否正确,是否符合 MySQL 的语法。
      • 语义解析
    • 优化器
      优化器的作用就是它认为的最优的执行方案去执行(有时候可能也不是最优,这篇文章涉及对这部分知识的深入讲解),比如多个索引的时候该如何选择索引,多表查询的时候如何选择关联顺序等可以说,经过了优化器之后可以说这个语句具体该如何执行就已经定下来。
    • 执行器
      当选择了执行方案后,MySQL 就准备开始执行了,首先执行前会校验该用户有没有权限,如果没有权限,就会返回错误信息,如果有权限,就会去调用引擎的接口,返回接口执行的结果。

对于查询语句

如果权限通过, 开始对语句进行词法分析以及语法分析, 选用它自己认为最优的方案, 进行权限校验,如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎接口,返回引擎的执行结果。

对于更新语句

前面的跟其一样, 但是还会有执行引擎来做一些步骤

  • 对于第五步就已经提交事务, 但是只是把bufferpool里面的数据改了,redolog只是进入prepare状态。
  • binlog是在server层的每一个存储引擎所共享的
    mysql高级(尚硅谷周阳)_第48张图片

总结

本课程最主要的就是sql的优化, 如何去分析sql等一系列面试经常问的mysql问题。完结撒花

mysql Innodb随笔

  • show index from table 出出来有一个信息代表这个索引有必要建立么, Cardinality的值除以表的rows总记录越接近一越好, 代表这个表的重复记录越少, 索引的分度越大。
  • 它的值实在存储引擎上统计的, 它使用的是抽样统计,先得到总页数, 随机抽出8页, 统计里面的不重复数据 /8 * pages, 就得到了本数据
  • 它什么是时候更新呢?
    • 当表中1/16的数据已经发生变化
    • stat_modified_counter>20亿的时候
      mysql高级(尚硅谷周阳)_第49张图片

行锁的三种算法

  • 总的来说MVCC通过一致性非锁定的方式解决了不可重复读, 通过对读加锁解决幻读的问题。

  • 在可重复读的隔离级别, 可以利用下面的显示加锁来解决幻读的结果。

  • Record Lock: 单个行记录上锁

  • GapLock: 间隙锁, 锁定一个范围, 但不包含记录本神 对于RC级别是没有间隙锁的 当前的这个索引到上一个索引以及到下一个索引都会加锁。

  • Next-Key Lock: Gap Lock + Record Lock, 锁定一个范围, 并且锁定记录本身, 上述表的索引值有10、11、13、20 当插入12的时候会锁住(10, 11] ,(11, 12], (12,13): innodb利用这一个算法来解决不可重复读的问题。

  • 如果对利用辅助索引锁定 加写锁来锁定一行的话, 利用的行锁的算法是

  • 而利用聚集索引或者(有唯一属性)的话加写锁来锁定某一行的时候, 会降级到 Record Lock; 对于范围的话 加的还是Next-Key Lock(临建锁) 对于唯一键值(复合)若查询的是其中的一个还是会用Next-key-lock

  • 无索引更新会导致锁升级为表锁。
    mysql高级(尚硅谷周阳)_第50张图片

  • 对于自增长列来说, mysql底层会维护一个自增长的计数器, 但这种锁是一个表锁机制, 但他也是在自增长指插入的sql语句后立即释放

  • 对于自增列来说:

    • 首先说明插入类型分为 simple inserts(再插入前就已经知道要插入的行数了) bulk inserts(在插入钱不能确定插入行数的语句), mixed-mode inserts.
    • 对自增列的锁的方式由参数innodb_autoinc_lock_mode 以及各个设置下对自增的影响, 其总共有三个有效值可供设定, 即
      • traditional : 0, 这个是mysql5.2之前的版本默认使用的, 他是通过对计数器上一个表锁 auto_inc来实现的, 它只有等自增语句完成的时候才会释放锁。
      • consecutive: 1, 这个是对0的一个优化, 它对于simple插入语句来说, 不会等待自增语句完成之后才释放, 只是利用互斥量对计数器进行累加操作。 但是对于bulk insert, 还是利用传统的表锁AUTO_INC方式, 在这种配置下如果不考虑回滚操作, 对于自增值还是连续的。
      • interleaved 2, 这个是并发度最大一个模式, 对于所有的插入语句都是使用的互斥量来进行的自增的, 由于并发插入的存在, 在每次插入的, 自增长的值可能是不连续的, 最重要的是基于statement-Base主从复制会出现问题, 故利用这个模式要使用row-base replication, 这样才能主从复制数据的一致
  • 对于外键来说, 肯定时先查父表, 这时使用的不是一致性非锁定读, 而是对读到的数据进行加s锁, 这样就可阻塞对数据的修改导致的数据不一致的问题

  • 对于redolog物理日志是存储引擎层的,表示的是对页的物理修改日志 随着事务的进行开始写的并不是事务进行commmit才开始写

  • 对于binlog逻辑日志存的是sql语句, 只有在事务提交的时候才会开始写

  • 对于undolog 逻辑日志存的是对一行操作的日志 数据的一致性 以及事务回滚和MVCC的实现, 对于undolog日志的回滚, 并不是把数据回到原始状态, 而是执行相反的操作, 比如insert就执行delete, undolog会产生redolog, 也就是undolog 的产生会伴随这redolog的产生, 这是因为undo log 也需要持久性的保护。

    • insert undolog 日志 事务完成就可以删除了
    • update undolog 日志 事务完成不能立即删除, 而是交给purge线程进行操作, 因为要实现MvCC, 若该行记录已经不被其他事务引用, 就可执行真正的delete操作

你可能感兴趣的:(mysql)