MYSQL
2022-07-28 17:37:19   0  举报             
     
         
 AI智能生成
  MYSQL知识图谱
    作者其他创作
 大纲/内容
  核心组件    
     连接器    
     管理连接,权限验证  
     查询缓存    
     mysql接收一个查询请求是,会先查询缓存,之前的sql语句为key,结果为value 缓存起来,如果命中缓存,就直接返回给给客户端  
     一般不建议使用查询缓存,因为查询缓存的更新太频繁了,表的数据更新,会清空所有的查询缓存,mysql8.0版本后取消了查询缓存  
     分析器
    
     进行词法分析、语法分析,判断是否符合mysql语法规范  
     优化器    
     对你的查询语句进行适当的优化,表中有多个索引时,决定使用哪个索引,多表关联(join)查询时,决定表的顺序。  
     执行器    
     执行语句,返回结果,这个过程还会校验是否有表的权限  
     存储引擎    
     InnoDB  
     Myisam  
     Memory等  
     binlog(归档日志)    
     binlog是mysql server 层维护的一种二进制日志  
     事务    
     ACID    
     Atomicity(原子性)    
     事务是一个不可分割的单位,其中的操作要么全部做,要么全部不做;事务中某一个sql执行失败,已执行的sql必须回滚,数据库回退到事务执行之前的状态。  
     Consistency(一致性)    
     事物执行结束后,数据库的完整性约束没有被破坏,事物执行的前后都是合法的数据状态。  
     Isolation(隔离性)    
     事务内部的操作与其他事务是隔离的,并发执行的各个事务之前不能互相干扰。  
     隔离级别    
     读未提交  
     读已提交  
     可重复读  
     可串行化  
     Durability(持久性)    
     指事务一旦提交,它对数据库的改变是永久性的,接下的其他操作和故障都不应该对其产生了遗憾。  
     MVCC    
     多版本并发控制:在同一时刻,不同事务读取的数据可能是不同的版本。让读写不冲突,读不需要加锁,作为一致性视图,用于读已提交,可重复读隔离级别的实现。  
     分类    
     当前读:sql读取到数据时,都是读取当前最新的数据。mysql通过锁机制确保获取数据时没有其它事务在修改数据,一般非select语句都是当前读。  
     快照读:不主动加锁的select语句就是快照读,读取的是数据的快照版本。innodb快照读,数据的读取由cache(原本数据)与undo(当前事务修改或者插入之前的数据)两部分组成 (在不同的隔离级别下,快照读是有区别的,在RC下,每次读取都会重新生成一个快照,所以每次快照都是最新的,也因此事务中每次select也可以看到其他事务commit的数据的更改,也就是不可重复读。但是在RR级别下,快照会在事务中第一次select语句执行时生成,只有在本事务中对数据修改才会更新快照,因此,只能看到第一次select之前已经提交事务的数据)  
     实现原理    
     mysql隐藏列           
     锁    
     分类    
     表级锁    
     特点    
     开销小,加锁快  
     不会出现死锁  
     锁粒度大,容易出现锁冲突,并发度低  
     类型划分    
     意向共享锁(intention shared lock, IS)    
     事物有意向对表中的某些行加共享锁(S锁)  
     意向排它锁(intention exclusive lock, IX)    
     事物有意向对表中的某些行加排它锁(X锁)  
     自增锁    
     事物在向包含AUTO_INCRMENT列的表中新增数据时会持有自增锁。假设事物A正在执行这个操作,此时另一个事物B尝试执行INSERT语句,事物B会被阻塞住,知道事物A释放自增锁。  
     行级锁    
     特点    
     开销大,加锁慢  
     会出现死锁  
     锁粒度小,不容易出现冲突,并发度高  
     类型划分    
     共享锁    
     允许一个事物读取数据,不允许修改数据,如果其他事务要再对改行进行加锁,只能加共享锁  
     加锁方式:select * from xx where id =x LOCK IN SHARE MODE  
     排他锁    
     事务在修改数据时加点锁,可以读取和修改数据,一旦一个事物对改行加排它锁,其他事务不能再对改行数据加任何锁。  
     加锁方式:delete/update/insert默认加上X锁,查询:select * from xxx where id =x for update;  
     行锁算法    
     记录锁    
     锁住具体的索引项,当sql执行按照唯一索引进行数据检索的时候,查询条件等值匹配的时候并且数据存在的时候,这个sql加上的就是记录锁  
     间隙锁    
     锁住数据不存在的区间(左开右闭(]),在sq执行按照索引进行数据检索的时候,查询数据不存在,这时SQL加上的锁为间隙锁,锁住了不存在的区间  
     邻键锁    
     等于(Record locks+Gap locks)(左开右闭(]),当sql执行按照索引进行数据检索时,查询条件为范围查找,并有数据命中,这个sql语句加上的锁就是临键锁,锁住记录+区间(这个锁解决了幻读问题)  
     死锁    
     是指两个或者两个一上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,他们将无法推进下去  
     产生原因    
     因为系统资源不足  
     进程运行推进的顺序不合适  
     资源分配不当等  
     产生死锁的四个必要条件    
     互斥条件:一个资源每次只能被一个进程使用  
     请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放  
     不剥夺条件:进程已获得的资源,在未用完之前,不能强行剥夺。  
     循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系  
     如任避免死锁    
     加锁顺序一致性  
     基于primary或者unique key更新数据  
     单次操作数据量不宜过多,表尽量少  
     减少表上的索引,减少单次定的资源  
     死锁检测    
     innodb_deadlock_detect 默认为0n,50s发现 死锁就好超时退出、  
     索引    
     索引的本质    
     一种排好序的数据结构  
     优缺点    
     优点    
     大大提高查询速度  
     通过创建唯一索引,可以保证数据库每一行数据的唯一性  
     可以加深表与表之间的连接  
     可以显著减少查询中分组和排序的时间  
     缺点    
     创建索引和维护索引需要时间,而且数据量越大时间越长  
     创建索引需要占磁盘空间,如果有大量索引,可能比数据文件更快达到最大文件尺寸  
     当对表中的数据进行增加、修改、删除的时候,索引也要同时维护,降低了数据的维护速度  
     分类    
     从存储结构上划分    
     Btree索引(B+tree、B-tree) Mysql默认索引    
     优缺点    
     优点    
     相比较于传统二叉树,避免了数据量大时造成的树的高度较高,而导致I/O次数高,速度变慢,B+TREE树的高度很低,从而减少了查找数据时的I/O次数  
     缺点    
     增加了额外的空间  
     添加,删除,修改索引列时,会伴随索引分裂,页空洞等性能损耗  
     存储方式分类    
     聚簇索引    
     将索引与数据放在一起,并且在叶子节点存放数据(innodb中主键索引就是聚簇索引)  
     非聚簇索引    
     通过索引检索到行号,再通过行号找到数据(Innodb是找到对应的主键id,再通过主键id找到对应的数据)  
     功能分类    
     普通索引  
     唯一索引    
     索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。  
     主键索引    
     主键是一种唯一性索引,但它必须指定为“PRIMARY KEY”,且不允许有空值。  
     全文索引  
     哈希索引    
     优缺点    
     优点    
     检索速度快,时间复杂度O(1)  
     缺点    
     数据量较大的情况下,出现大量哈希碰撞,导致检索效率降低  
     无法排序,范围查找  
     不支持最左匹配原则  
     full-index 全文索引  
     Rtree(空间数据索引)  
     索引创建规范    
     单张表索引数量不超过5个,单个索引中的字段不超过5个  
     表必须有主键,推荐使用自增字段作为主键(自增id、雪花算法等)  
     禁止冗余索引(索引|(a,b,c),索引|(a,b)),禁止重复索引(索引|(a),索引|(a,主键ID))  
     联表查询时,join列的数据类型必须相同,并且要建立索引  
     不在低基数列建立索引,如性别  
     选择区分度大的列建立索引,组合索引中,区分度大的放前面  
     合理创建组合索引(a,b,c)相当于(a),(a,b),(1,b,c)  
     合理使用覆盖索引减少IO跟避免排序  
     索引优化分析    
     EXPLAIN SELECT * from ** WHERE *** =****  
     执行计划字段解释    
     id:编号    
     id值相同,从上往下 顺序执行  
     id值越大越优先查询 (本质:在嵌套子查询时,先查内层 再查外层)  
     select_type :查询类型    
     SIMPLE    
     简单查询(不包含子查询、union)  
     PRIMARY    
     包含子查询SQL中的 主查询 (最外层)  
     SUBQUERY    
     包含子查询SQL中的 子查询 (非最外层)  
     DERIVED    
     衍生查询(使用到了临时表)  
     table :输出结果集的表  
     type :访问类型    
     从左到右,性能由好到最差,system>const>eq_ref>ref>range>index>all (ref到range之间还有一些其他的不过不太常见)(要对type进行优化的前提:有索引)(一般优化后的type必须在range以上)  
     分类    
     system    
     只有一条数据的系统表 ;或 衍生表只有一条数据的主查询(基本不能达到可忽略)  
     const    
     仅仅能查到一条数据的SQL ,用于Primary key 或unique索引 (类型 与索引类型有关)  
     eq_ref    
     唯一性索引:对于每个索引键的查询,返回匹配唯一行数据(有且只有1个,不能多 、不能0)  
     ref    
     非唯一性索引,对于每个索引键的查询,返回匹配的所有行(0,多)  
     range    
     检索指定范围的行 ,where后面是一个范围查询(between ,> < >=, 特殊:in有时候会失效 ,从而转为 无索引all)  
     index    
     全索引扫描,查询全部索引中数据  
     all    
     全表扫描,查询全部表中的数据  
     possible_keys :可能用到的索引  
     key :实际使用的索引  
     key_len :实际使用索引的长度    
     用于判断复合索引是否被完全使用 (a,b,c)  
     demo    
     在utf8编码中:1个字符占3个字节,如果索引的字段可以为null,则会使用一个字节用来标识 ,如果是varchar这种,会用两个字节表示可变
例如 :某个字段 name(varchar(20)),如果用到了这个字段的索引那么lenth就是 20*3+1(null)+2(可变字符) =63
    例如 :某个字段 name(varchar(20)),如果用到了这个字段的索引那么lenth就是 20*3+1(null)+2(可变字符) =63
 ref :表之间的引用  
     rows: 被索引优化查询的 数据个数 (实际通过索引而查询到的 数据个数)  
     Extra :额外的信息    
     using index    
     性能提升; 索引覆盖(覆盖索引)。原因:不读取原文件,只从索引文件中获取数据 (不需要回表查询)只要使用到的列 全部都在索引中,就是索引覆盖using index  
     using where    
     表示进行了回表查询  
     using filesort    
     性能消耗大;需要“额外”的一次排序(查询) 。常见于 order by 语句中。  
     using temporary    
     性能损耗大 ,用到了临时表。一般出现在group by 语句中。  
     impossible where    
     where子句永远为false  
     避免索引失效的一些原则    
     复合索引,不能跨列使用(index(a,b,c),你的索引使用就不要 where a=x,c=x)  
     复合索引尽量使用全索引匹配  
     不要在索引上进行任何操作(计算,函数,类型转换),否则索引失效  
     复合索引不要使用不等(!= ,<>,>),这样会导致自身以及右侧的索引失效**(这个不是一定的有概率的**)  
     like尽量以“常量”开头,不要以'%'开头,否则索引失效  
     尽量不要使用or,否则索引失效(字段都是单值索引是可以的)  
     常见问题    
     为什么我们经常被要求,只查询需要的字段?    
     在例如你查询只用到name时,select * from user where iphone=xxx,索引为(iphone,name)的时候,我们根据上面的innodb的索引结构学习到,你要查询索引中没有的字段的时候,需要先通过辅助索引找到主键索引的值,然后再找到对应的数据值(过程叫做回表),这样就多了I/O操作,如果你的sql改成select name from user where iphone=xxx,这个name值在辅助索引中已经有了,所以不需要再去主键索引中找数据,就提高了查询效率(这种情况叫做覆盖索引)  
     经常在数据量很大的情况下我们要把主键用整数代替字符串,并且是增长的?    
     在使用BigInt的时候比UUID(为保证不重复一般都是UUID),占用的字节少,那么在B+Tree的结构中,就能存储更多的值。  
     比字符串好排序  
     如果你生成的是自增的(分布式id生成策略中都是增加的),在插入时,就可以尽可能减少页分裂  
     主从复制    
     基本原理    
     master上所有的修改都会保存二进制binary log中,slave开启一个I/O thread,来读binary log然后写到本地的一个realy log里面。同时slave上开启一个sql thread 进行执行获取到的realy log  
    
 
 
 
 
  0 条评论
 下一页
  
   
   
   
   
  
  
  
  
  
  
  
  
  
  
 