MySQL知识点整理【2023】
2023-06-30 14:08:39 2 举报
AI智能生成
MySQL知识点整理【2023】
作者其他创作
大纲/内容
事务
什么是事务<br>
是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位<br>
事务的基本特征<br>
原子性 Atomicity<br>
指的是⼀个事务中的操作要么<font color="#ff0000"><b>全部成功</b></font>,要么<font color="#ff0000"><b>全部失败</b></font><br>
一致性 Consistency<br>
指的是<font color="#ff0000"><b>数据库执行事务的前后,数据是—致的,不会出现数据丢失</b></font><br>
隔离性 Isolation<br>
指的是一个事务的修改在最终提交前,对其他事务<b style=""><font color="#ff0000">是不可见的,相互隔离</font></b><br>
持久性 Durability<br>
指的是—旦事务提交,所做的修改就会<b><font color="#ff0000">永久保存到数据库中</font></b><br>
问题:<b>那ACID是靠什么保证的?</b><br>
A <font color="#ff0000"><b>原子性</b></font> 由undo log日志保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sqI<br>
C <b><font color="#ff0000">一致性</font></b> 一般由代码层面来保证(由其它三个特性保证)<br>
Ⅰ <font color="#ff0000"><b>隔离性</b></font> 由MVCC来保证<br>
D <b><font color="#ff0000">持久性</font></b> 由内存+redo log日志来保证,mysql修改数据同时在内存和redo log 记录这次操作,事务提交的时候通过redo log刷盘,宕机的时候可以从redo log恢复<br>
事务的隔离级别
隔离级别
read uncommit(读未提交)
可能会读到其他事务未提交的数据,也叫做<font color="#ff0000"><b>脏读</b></font>
read commit(读已提交)
两次读取结果不—致,叫做不可重复读。<font color="#ff0000"><b>不可重复读解决了脏读的问题</b></font>,他只会<font color="#ff0000"><b>读取已经提交的事务</b></font>
repeatable read(可重复读)
mysql的默认级别,就是<b><font color="#ff0000">每次读取结果都一样</font></b>,但是<font color="#ff0000"><b>有可能产生幻读</b></font>
serializable(串行化)
给<b><font color="#ff0000">每一行读取的数据加锁</font></b>,会<font color="#ff0000"><b>导致大量超时和锁竞争的问题</b></font>。不管多少事务,都是<font color="#ff0000"><b>「依次按序一个一个执行」</b></font>
事务造成的三个问题<br>
脏读
脏读指的是「<font color="#ff0000"><b>读到了其他事务未提交的数据</b></font>」,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并一定最终存在的数据,这就是脏读
不可重复读
对比可重复读,不可重复读指的是在同一事务内,「<font color="#ff0000"><b>不同的时刻读到的同一批数据可能是不一样的</b></font>」
幻读
<b><font color="#ff0000">幻读是针对数据插入(INSERT)操作来说的</font></b>。假设事务A对某些行的内容作了更改,但是还未提交,此时事务B插入了与事务A更改前的记录相同的记录行,并且在事务A提交之前先提交了,而这时,在事务A中查询,会发现「好像刚刚的更改对于某些数据未起作用」,但其实是事务B刚插入进来的这就叫幻读
事务的传播行为(7种)
PROPAGATION_REQUIRED (默认)
如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置
PROPAGATION_REQUIRED_NEW
创建新事务,无论当前存不存在事务,都创建新事务
PROPAGATION_SUPPORTS
支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行
PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
PROPAGATION_MANDATORY
支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常
PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常
PROPAGATION_NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作
MySQL中有哪些日志
binlog
定义: binlog是<b><font color="#ff0000">归档日志</font></b>,属于Server 层的日志,是一个二进制格式的文件,用于「<b><font color="#ff0000">记录用户对数据库更新的SQL语句信息</font></b>」
主要作用:<b style=""><font color="#000000">主从复制 数据恢复</font></b>
undolog
定义: undolog是<b><font color="#ff0000">InnoDB</font></b>存储引擎的日志,是<b><font color="#ff0000">回滚日志</font></b>,用于保证数据的原子性,「<b><font color="#ff0000">保存了事务发生之前的数据的一个版本,也就是说记录的是数据是修<br>改之前的数据,可以用于回滚</font></b>」,同时可以提供<font color="#ff0000"><b>多版本并发控制下的读(MVCC)</b></font>
主要作用: <b style=""><font color="#000000">事务回滚 MVCC</font></b>
redolog
定义: redolog 是「<b><font color="#ff0000">InnoDB存</font></b>储引擎所特有的一种日志」,是<font color="#ff0000"><b>重做日志</b></font>,用于记录事务操作的变化,记录的是数据修改之后的值,不管事务是否提交都会记录下来。
主要作用 <br>可以做「<b>数据恢复并且提供crash-safe 能力</b>」<br>当有增删改相关的操作时,会先记录到 Innodb中,并修改缓存页中的<br>数据,「等到mysql闲下来的时候才会真正的将redolog中的数据写入到磁盘当中(刷盘)」<br>
relaylog
定义: relaylog是<b><font color="#ff0000">中继日志</font></b>,「<b><font color="#ff0000">在主从同步的时候使用到</font></b>」,它是一个<b><font color="#ff0000">中介临时的日志文件</font></b>,用于存储从master节点同步过来的binlog日志内容。
主要作用 <br>master主节点的 binlog传到 slave 从节点后,从结点开启io线程写入relay log里。然后从节点的sql线程从relaylog里读取日志然后应用到slave从节点本地。从而<b>「使从服务器和主服务器的数据保持一致」</b><br>
errorlog
定义:记录 MySQL 服务器运行过程中的错误信息,默认开启无法关闭
slowlog
定义: MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的SQL语句,具体是指运行时间超过 long_query_time 值的SQL,这样的SQL则会被记录到慢查询日志中。long_query_time 的默认值为10秒
general log
定义: 查询日志里面记录了数据库执行的所有命令,不管语句是否正确,都会被记录,默认是关闭的
问题:<b>redolog是怎么记录日志的?</b>
InnoDB的redo log是固定大小的,比如可以配置为一组4个文件,每个文件的大小是1GB,那么总共就可以记录4GB的操作。<font color="#ff0000"><b>「从头开始写,写到末尾就又回到开头循环写」。</b></font><br>所以,如果数据写满了但是还没有来得及将数据真正的刷入磁盘当中,那么就会发生「内存抖动」现象,从肉眼的角度来观察会发现mysql 会宕机一会儿,此时就是正在刷盘了
问题:<b> redolog 和 binlog的区别?</b><br>
<b>所属层次</b>
1. [redolog」是「Innodb」独有的日志,而「binlog」是「server」层的,所有的存储引擎都有使用到
<b>记录内容</b>
2. 「 redolog」记录了「具体的数值」,对某个页做了什么修改,「binlog」记录的「操作内容」
<b>文件大小</b>
3. [binlog」大小达到上限或者flush log 「会生成一个新的文件」,而「redolog」有固定大小「只能循环利用J
<b>其它</b>
4. 「binlog日志没有crash-safe 的能力」,只能用于归档。而redo log 有crash-safe能力
执行过程
图解
小结
<b><font color="#ff0000">连接器</font></b>: 建立连接,管理连接、校验用户身份;<br><b><font color="#ff0000">查询缓存</font></b>: 查询语句如果命中查询缓存则直接返回,否则继续往下执行。MySQL 8.0已删除该模块;<br><b><font color="#ff0000">解析SQL</font></b>: 通过解析器对SQL查询语句进行词法分析、语法分析,然后构建语法树,方便后续模块读取表名、字段、语句类型;<br><b><font color="#ff0000">执行SQL</font></b>: 执行SQL 共有三个阶段:<br>1)预处理阶段:检查表或字段是否存在;将select *中的*符号扩展为表上的所有列。<br>2)优化阶段:基于查询成本的考虑,选择查询成本最小的执行计划;<br>3)执行阶段:根据执行计划执行SQL查询语句,从存储引擎读取记录,返回给客户端;<br>
索引
问题: <b>什么是索引,有什么优缺点?</b>
定义:索引是一种帮助<font color="#ff0000"><b>快速查找数据的数据结构</b></font>,可以把它理解为书的目录,通过索引能够快速找到数据所在位置。
索引数据结构有:<br>Hash表(通过hash算法快速定位数据,但不适合范围查询,因为需要每个key都进行一次hash) .<br>二叉树(查找和修改效率都比较高),但是在InnoDB引擎中使用的索引是B+Tree,相较于二叉树,B+Tree这种多叉树,更加矮宽,更适合存储在磁盘中。<br>使用索引增加了数据查找的效率,但是相对的由于索引也需要存储到磁盘,所以增加了存储的压力,并且新增数据时需要同步维护索引。<br>但是合理的使用索引能够极大提高我们的效率!<br>
问题:<b>说下mysql的索引有哪些?</b>
按照<b><font color="#ff0000">数据结构</font></b>来分
B+树索引
Hash索引
按照<b><font color="#ff0000">物理存储</font></b>来分
聚簇索引(主键索引)
二级索引(辅助索引)
按照<b><font color="#ff0000">字段</font></b>来分
主键索引
唯一索引
普通索引
前缀索引
按照<b><font color="#ff0000">个数</font></b>来分
单列索引
联合索引
全文索引
对内容进行分词搜索,仅可用于Myisam,更多用ElasticSearch做搜索ALTER TABLE table_name ADD FULLTEXT ( filed_name )
问题:<b>聚簇和非聚簇索引又是什么?</b>
聚簇索引
定义:<b><font color="#ff0000">叶子节点包含索引列和数据</font></b>,这种数据和索引在一起存储的索引方式叫做聚簇索引
一张表只能有一个聚簇索引,一般会选择主键作为聚簇索引,没有定义主键,InnoDB会选择一个唯一的非空字段代替,如果都没有的话则会隐式定义一个主键作为聚簇索引
非聚簇索引
定义:<b><font color="#ff0000">叶子结点包含索引列和主键ld值</font></b>,这一点和MylSAM保存的是数据地址是不同的
问题:<b>什么时候适合用索引?什么时候不适合?</b>
适合的情况
1.字段有<font color="#ff0000"><b>唯一性</b></font><br>2.<font color="#ff0000"><b>where条件</b></font>经常用到的字段<br>3.<b><font color="#ff0000">group by</font></b>和<font color="#ff0000"><b>order by</b></font>经常用到的字段<br>
不适合的情况
1.字段<b><font color="#ff0000">频繁变化</font></b><br>2.字段数据<font color="#ff0000"><b>大量重复</b></font><br>3.<font color="#ff0000"><b>不经常用</b></font>的字段<br>4.<font color="#ff0000"><b>数据太少</b></font><br>
问题: <b>普通索引和唯一索引该怎么选择?</b>
查询场景
当<b><font color="#ff0000">普通索引</font></b>为条件时查询到数据会一直扫描,直到<b><font color="#ff0000">扫完整张表</font></b>。<br>当<b><font color="#ff0000">唯一索引</font></b>为查询条件时,<b><font color="#ff0000">查到该数据会直接返回</font></b>,不会继续扫表<br>
更新场景
<b><font color="#ff0000">普通索引</font></b>会直接将操作更新到change buffer中,然后结束。唯一索引需要判断数据是否冲突
总结
<font color="#ff0000"><b>唯一索引</b></font><font color="#2196f3">更加适合查询的场景</font><br><font color="#ff0000"><b>普通索引</b></font><font color="#81c784">更适合插入的场景</font><br>
问题: <b>为什么采用B+树,而不是B-树作为索引的数据结构?</b>
B+树只在<b><font color="#ff0000">叶子结点储存数据</font></b>,非叶子结点不存具体数据,只存 key,查询更稳定,增大了广度,<b><font color="#ff0000">而一个节点就是磁盘一个内存页,内存页大小固定</font></b>,那么相比B树,B-树这些「<b><font color="#ff0000">可以存更多的索引结点</font></b>」,宽度更大,树高矮,节点小,拉取一次数据的磁盘IO次数少,并且B+树在叶子节点上加了双向指针,因此<b><font color="#ff0000">只需要去遍历叶子节点就可以实现整棵树的遍历</font></b>。而且在数据库中基于范围的查询是非常频繁的,效率更高。
问题:<b> 索引什么时候会失效?</b>
<b><font color="#ff0000">联合索引非最左匹配</font></b><br>
对索引<font color="#ff0000"><b>使用函数/表达式计算</b></font><br>
索引字段上<b><font color="#ff0000">使用(!=或者<>)判断时</font></b>,会导致索引失效而转向全表扫描
索引字段上<b><font color="#ff0000">使用is null / is not null判断时</font></b>,会导致索引失效而转向全表扫描
联合索引的前面索引列<font color="#ff0000"><b>使用范围查询(<,> ,like)</b></font>,会导致后续的索引失效
索引字段使<b><font color="#ff0000">用like以通配符开头</font></b>(‘%字符串’)时,会导致索引失效而转向全表扫描,也是最左前缀原则。
索引字段<font color="#ff0000"><b>是字符串,但查询时不加单引号</b></font>,会导致索引失效而转向全表扫描
索引字段<b><font color="#ff0000">使用or时</font></b>,会导致索引失效而转向全表扫描(取决于or链接的字段是否都使用索引)
索引覆盖
定义: 指的是在<b><font color="#ff0000">一次查询</font></b>中,如果一个索引(二级索引)包含或者说<b><font color="#ff0000">覆盖所有需要查询的字段的值</font></b>,我们就称之为覆盖索引,而不再需要回表查询
举个栗子
table表 id,name,age,gender,address<br>id主键,name普通索引
select id,name from table where name='zhangsan';
查找过程:直接根据name的值去name的B+树上找到id和name,不需要进行回表,此时叫做索引覆盖
回表查询
定义:指的是一次查询,走的是二级索引,<b><font color="#ff0000">没有覆盖需要查询的字段</font></b>,需要拿到主键ld去聚簇索引中二次查询,多扫描一次索引树
举个栗子
table表 id,name,age,gender,address<br>id主键,name普通索引
select * from table where name='zhangsan';
查找过程:首先根据name的值去name的B+树上找到叶子节点中存储的id值,然后再根据id的值去id的B+树上查找整行的记录,这个过程叫做回表。<br>回表效率较低,尽量避免回表
最左匹配
定义:最左前缀其实说的是,在<b><font color="#ff0000">where条件中出现的字段</font></b>,「<b><font color="#ff0000">如果只有组合索引中的部分列,则这部分列的触发索引顺序</font></b>」,是按照定义索引的时候的顺序从前到后触发,最左面一个列触发不了,之后的所有列索引都无法触发。
举个栗子
table表 id,name,age,gender,address<br>id主键,(name,age)组合索引
select * from table where name=zhangsan and age = 20;<br>select * from table where age = 20;<br>select * from table where name=zhangsan ;<br>select * from table where age = 20 and name=zhangsan;优化器优化调整顺序
索引下推
定义: 如果存在某些被索引的列的判断条件时,MySQL将这一部分判断条件传递给存储引擎,然后由存储引擎通过判断索引是否符合MySQL服务器传递的条件,「<b><font color="#ff0000">只有当索引符合条件时才会将数据检索出来返回给MySQL服务器</font></b>」。
举个栗子
-- 查看是否开启了 索引下推 index_condition_pushdown 默认是on<br>show VARIABLES like '%optimizer_switch%';
table表 id,name,age,gender,address<br>id主键,(name,age)组合索引
select * from table where name=zhangsan and age = 12;
没有索引下推之前:先根据name的值从存储引擎中把所有符合条件的数据拉取到server层,然后在server层中对age进行数据筛选<br>有了索引下推之后:直接根据name,age的值从存储引擎中找到符合条件的数据,不需要在server层进行数据筛选了
锁
MySQL锁家族
按照<b><font color="#ff0000">数据类型操作</font></b>来分<br>
共享锁<b><font color="#ff0000"> S</font></b>(Shared Lock)/ 读锁(read lock)<br>
排它锁 <b><font color="#ff0000">X</font></b>(Exclusive Lock)/ 写锁 (write lock)<br>
按照<b><font color="#ff0000">锁粒度角度</font></b>来分<br>
表级锁<br>
表级别的S锁和X锁<br>
加锁
LOCK TABLES t READ :InnoDB存储引擎会对表 t 加表级别的 S锁 。 <br>LOCK TABLES t WRITE :InnoDB存储引擎会对表 t 加表级别的 X锁 。<br>
小结
意向锁<br>
定义: InnoDB 支持 多粒度锁(multiple granularity locking),它允许 行级锁 与 表级锁 共存,而意向<br>锁就是其中的一种 表锁<br>
意向锁分为两种
意向共享锁(intention shared lock, <b><font color="#ff0000">IS</font></b>):事务有意向对表中的某些行加共享锁(S锁)
意向排他锁(intention exclusive lock, <b><font color="#ff0000">IX</font></b>):事务有意向对表中的某些行加排他锁(X锁)
小结
1. InnoDB 支持 <b><font color="#ff0000">多粒度锁</font></b> ,特定场景下,<font color="#ff0000"><b>行级锁可以与表级锁共存</b></font>。<br>2. 意向锁之间互不排斥,但除了 IS 与 S 兼容外, <font color="#ff0000"><b>意向锁会与 共享锁 / 排他锁 互斥</b></font> 。 <br>3. IX,IS是表级锁,不会和行级的X,S锁发生冲突。只<b><font color="#ff0000">会和表级的X,S发生冲突</font></b>。<br>4. 意向锁在保证并发性的前提下,实现了 <font color="#ff0000"><b>行锁和表锁共存</b></font> 且 <font color="#ff0000"><b>满足事务隔离性</b></font> 的要求。<br>
自增锁<br>
在使用MySQL过程中,我们可以为表的某个列添加 AUTO_INCREMENT 属性。<br>
MDL锁<br>
MySQL5.5引入了meta data lock,简称MDL锁,属于<font color="#ff0000"><b>表锁</b></font>范畴。MDL 的作用是,保证读写的正确性
比如,如果一个查询正在遍历一个表中的数据,而执行期间另一个线程对这个 表结构做变更 ,增加了一<br>列,那么查询线程拿到的结果跟表结构对不上,肯定是不行的。<br>因此,<b><font color="#ff0000">当对一个表做增删改查操作的时候,加 MDL读锁;当要对表做结构变更操作的时候,加 MDL 写<br>锁</font></b>。<br>
行级锁<br>
记录锁(Record Locks)<br>
定义: 记录锁也就是仅仅把一条记录锁上,官方的类型名称为: LOCK_REC_NOT_GAP
小结
记录锁是有S锁和X锁之分的,称之为 <b><font color="#ff0000">S型记录锁</font></b> 和 <font color="#ff0000"><b>X型记录锁 </b></font><br>1.当一个事务获取了一条记录的S型记录锁后,其他事务也可以继续获取该记录的S型记录锁,但不可<br>以继续获取X型记录锁;<br>2.当一个事务获取了一条记录的X型记录锁后,其他事务既不可以继续获取该记录的S型记录锁,也不<br>可以继续获取X型记录锁。
间隙锁(Gap Locks)<br>
<b><font color="#ff0000">间隙锁之间不冲突</font></b>。唯一目的是防止其他事务插入间隙。<br>只锁定一个范围【<b><font color="#ff0000">锁左不锁右</font></b>】,不包含记录本身【加的排他锁】<br>
Select * from emp where empid > 100 for update;
目的:<font color="#ff0000">防止幻读</font>
对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)"<br>
场景
默认地,只有在RR下才有gap lock,用于保护两条数据之间的gap,防止事务过程中被写入/删除数据,引发幻读问题<br>
但事实上,即在RC级别,如果往一个有唯一约束属性的索引中(包含主键索引,唯一索引)插入新数据前,会对相应的位置加载一个共享的nextkey lock,而我们知道next-key lock是包含gap lock的,因此在这种特殊情况下也是有gap lock的<br>
临键锁(Next-Key Locks)<br>
间隙锁和行锁合称next-key lock,mysql是通过next-key lock来<font color="#ff0000">防止幻读的 [ RR隔离级别 ]</font>
锁定的范围是( ],左开右闭
降级情况
当查询<font color="#ff0000">未命中</font>任何记录时,会<font color="#ff0000">降级为间隙锁(Gap Locks</font>)<br>
当使用<font color="#ff0000">主键</font>或者<font color="#ff0000">唯一索引</font>命中了一条记录时,会降级为<font color="#ff0000">记录锁(Record Locks)</font><br>
插入意向锁(Insert Intention Locks)<br>
页级锁<br>
按照<b><font color="#ff0000">对锁的态度</font></b>来分<br>
悲观锁(Pessimistic Locking)<br>
悲观锁是一种思想,顾名思义,就是很悲观,对数据被其他事务的修改持保守态度,会通过数据库自身的锁机制来实现,从而保证数据操作的排它性<br>
乐观锁(Optimistic Locking)<br>
乐观锁认为对同一数据的并发操作不会总发生,属于小概率事件,不用每次都对数据上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,也就是不采用数据库自身的锁机制,而是通过程序来实现<br>
小结
总结一下乐观锁和悲观锁的适用场景:<br>1. <font color="#ff0000">乐观锁 适合 读操作多 的场景</font>,相对来说写的操作比较少。它的优点在于 程序实现 , 不存在死锁<br>问题,不过适用场景也会相对乐观,因为它阻止不了除了程序以外的数据库操作。<br><br>2. <font color="#ff0000">悲观锁 适合 写操作多 的场景</font>,因为写的操作具有 排它性 。采用悲观锁的方式,可以在数据库层<br>面阻止其他事务对该数据的操作权限,防止 读 - 写 和 写 - 写 的冲突。<br>
加锁方式
隐式锁
当多个客户端并发访问同一个数据的时候,为了保证数据的一致性,数据库管理系统会自动的为该数据加锁、解锁,这种被称为隐式锁。隐式锁无需开发人员维护(包括锁粒度、加锁时机、解锁时机等)
显示锁
通过<font color="#ff0000">特定的语句进行加锁</font>,我们一般称之为显示加锁
显示加共享锁<br>select .... lock in share mode<br>显示加排它锁<br>select .... for update<br>
其它
死锁
原因:指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环<br>
几种死锁场景
1.如果两个session访问两个表的顺序不同,发生死锁的机会就非常高!但如果以相同的顺序来访问,死锁就可能避免
⒉.在程序以批量方式处理数据的时候,如果事先对数据排序,保证每个线程按固定的顺序来处理记录,也可以大大降低死锁的可能
3.在事务中,如果要更新记录,应该直接申请足够级别的锁,即排他锁,而不应该先申请共享锁,更新时再申请排他锁,甚至死锁
4.在RR隔离级别下,如果两个线程同时对相同条件记录用SELIECT.FOR UPDATE加排他锁,在没有符合该记录情况下,两个线程都会加锁成功。程序发现记录尚不存在,就试图插入一条新记录,如果两个线程都这么做,就会出现死锁。这种情况下,将隔离级别改成READ COMMITTED,就可以避免问题
解决死锁的两种策略 :<br>一,<font color="#ff0000">直接进入等待,直到超时</font>。这个超时时间可以通过参数<font color="#ff0000">innodb_lock_wait_timeout</font> 来设置。<br>二,发起死锁检测,发现死锁后,<font color="#ff0000">主动回滚死锁链条中的某一个事务</font>(将持有最少行级排他锁的事务进行回滚),让其他事务得以继续执行。将参数<font color="#ff0000"> innodb_deadlock_detect </font>设置为on ,表示开启这个逻辑。
锁监控
innodb lock waits和innodb_trx两张表里的信息 innodb_locks表<br>
全局锁
全局锁的命令<br>Flush tables with read lock<br>
典型使用 场景 是:做 全库逻辑备份
存储引擎
innoDB
innodb主键使用自增bigint效率比uuid高<br>1.方便比较大小<br>⒉.不会破坏B+TREE结构<br>
聚集索引:索引和数据在同—张表<br>非聚集索引:索引在—张表,数据在─张表
innodb使用b+tree存索引和数据不使用hash的原因:<br>范围查找使用hash不合适,需要全表扫描,hash(主键)直接存储到位置,因此一般使用B+Tree
支持行锁
支持事务
myisam
myisam使用非聚集索引,主键和其他索引都是指向数据表<br>
不支持事务
只支持表锁
MVCC
定义: Multi_Version_Concurrency_Control <b><font color="#ff0000">多版本并发控制</font></b>,是现代数据库(包括MySQL、Oracle、PostgreSQL等)引擎实现中常用的处理读写冲突的手段,目的在于<b>「<font color="#ff0000">提高数据库高并发场景下的吞吐性能</font>」</b><br>
MVCC最大的优势:<b><font color="#ff0000">读不加锁,读写不冲突</font></b>。<font color="#ff0000">读写不冲突</font>是非常重要的,极大的增加了系统的并发性能。<font color="#ff0000">MVCC机制也是乐观锁的一种体现</font>。
MVCC解决了什么问题
MVCC在MySQL InnoDB中的实现主要是为了<b>提高数据库并发性能</b>,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,<b>非阻塞并发读</b>
在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,<b>提高了数据库并发读写的性能</b>
同时还可以解决<b>脏读,幻读,不可重复读</b>等事务隔离问题,但不能解决更新丢失问题
当前读
select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)这些操作都是一种当前读。
<b>当前读就是它读取的是记录的最新版本</b>,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁
快照读
在RR时普通查询就是快照读
快照读的<b>前提</b>是隔离级别不是<font color="#ff0000">串行</font>级别,串行级别下的快照读会退化成当前读
快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本
<b><font color="#ff0000">TIPS</font></b>
<font color="#ff0000">MVCC只在RR和RC两个隔离级别下工作</font>
MVCC实现原理
MVCC由三部分组成:隐藏字段,undolog,readview
【<font color="#ff0000">隐藏字段</font>】每一行记录有三个隐藏键,分别为DATA_TRX_ID、DATA_ROLL_PTR、DB_ROW_ID
<font color="#ff0000">readview</font>: 当执行SQL语句查询时会产生一致性视图 【创建快照读这一刻,包含该条数据的所有活跃事务ID的列表】
SQL调优
问题: <b>一条Sql语句查询一直慢会是什么原因</b>?
「1.<b><font color="#ff0000">没有用到索引</font></b>」<br>比如函数导致的索引失效,或者本身就没有加索引
「2.<font color="#ff0000"><b>表数据量太大</b></font>」考虑分库分表吧
「3.<font color="#ff0000"><b>优化器选错了索引</b></font>」<br>「考虑使用」force index强制走索引
问题: <b>一条Sql语句查询偶尔慢会是什么原因</b>?<br>
「1.<b><font color="#ff0000">数据库在刷新脏页</font></b>」<br>比如「 redolog 写满了」,「内存不够用了」释放内存如果是脏页也需要刷,mysql「正常空闲状态刷脏页」<br>
「2.<b><font color="#ff0000">没有拿到锁</font></b>」<br>
问题: <b>说说你的Sql调优思路</b>?<br>
预防
1.「<font color="#ff0000">表结构优化</font>」<br>1.1拆分字段<br>1.2字段类型的选择<br>1.3字段类型大小的限制<br>1.4合理的增加冗余字段<br>1.5新建字段一定要有默认值<br>
4.「<font color="#ff0000">分库分表</font>」<br>
执行
2.「<font color="#ff0000">索引方面</font>」<br>2.1索引字段的选择<br>2.2利用好mysql支持的索引下推,覆盖索引等功能<br>2.3唯一索引和普通索引的选择<br>
3.「<font color="#ff0000">查询语句方面</font>」<br>3.1避免索引失效<br>3.2合理的书写where条件字段顺序<br>3.3小表驱动大表<br>3.4可以使用force index()防止优化器选错索引<br>
其它
问题: <b>WAI是什么?有什么好处?</b><br>
WAL就是Write-Ahead Logging,其实就是「所有的修改都先被写入到日志中,然后再写磁盘」,用于保证数据操作的原子性和持久性。
1.「读和写可以完全地并发执行」,不会互相阻塞<br>2.先写入 log中,磁盘写入从「随机写变为顺序写」,降低了client端的延迟。并且,由于I顺字写入大概率是在一个磁盘块内,这样产生的io次数也大大降低<br>3.写入日志当数据车崩溃的时候「可以使用日志来恢复磁盘数据」
<ol><li>问题:<b>缓冲池 buffer pool是做什么的?</b></li></ol>
buffer pool是一块内存区域,为了「<font color="#ff0000">提高数据库的性能</font>」,当数据库操作数据的时候,把硬盘上的数据加载到 buffer pool,不直接和硬盘打交道,操作的是 buffer pool里面的数据,数据库的增删改查都是在buffer pool上进行
预读机制:<br>Buffer Pool有一项特技叫预读,存储引擎的接口在被Server层调用时,会在响应的同时进行预判,将下次可能用到的数据和索引加载到Buffer Pool
0 条评论
下一页