[TOC]
关键词
B树,B+树,红黑树,联合索引存储
主从复制,宕机恢复,8.0相比5.0的改进
事务,隔离级别,实现原理,MVCC
在线改表原理,redolog,undolog,binlog,group commit原理问题解决
零拷贝的场景,主键自增id而不是uuid
什么场景使用索引不使用更慢,
锁的数据结构
分库分表扩容,当nosql,开发mysql引擎如何接口对接
死锁,
谈谈主从复制
复制(replication)是MySQL数据库提供的一种高可用高性能的解决方案,一般用来建立大型的应用。
replication的工作原理分为以下3个步骤:
1)主服务器(master)把数据更改记录到二进制日志(binlog)中。
2)从服务器(slave)把主服务器的二进制日志复制到自己的中继日志(relay log)中。
从服务器有2个线程,一个是I/O线程,负责读取主服务器的二进制日志,并将其保存为中继日志;另一个是SQL线程,复制执行中继日志
3)从服务器重做中继日志中的日志,把更改应用到自己的数据库上,以达到数据的最终一致性
异步实时 中间存在主从服务器之间的执行延时,如果主服务器的压力很大,则可能导致主从服务器延时较大
事务
在事务中的操作,要么都做修改,要么都不做 分类:扁平、带有保存点、链事务、嵌套事务、分布式事务
原子性、一致性、持久性通过数据库的redo log和undo log来完成。 redo log称为重做日志,用来保证事务的原子性和持久性。 undo log用来保证事务的一致性
redo log:两部分组成
一是内存中的重做日志缓冲(redo log buffer),其是易失的;
二是重做日志文件(redo log file),其是持久的
binlog
二进制日志(binlog),其用来进行POINT-IN-TIME(PIT)的恢复及主从复制(Replication)环境的建
redo 区别:
产生:redo是在innodb,binlog是在mysql上层
内容:redo是物理格式日志,记录页修改;binlog是逻辑日志,记录SQL语句
写入时间:redo事务中不断写入,binlog事务提交时写入
恢复:
innodb每次启动都会恢复重做日志 redolog,checkpoint表示已经刷新到磁盘页上的LSN,从checkpoint中开始部分即可
undo:
回滚日志,数据修改时会产生,存放在共享表空间的一个段中
MVCC控制,当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过undo读取之前的行版本信息,以此实现非锁定读取
undo log会产生redo log,也就是undo log的产生会伴随着redo log的产生,这是因为undo log也需要持久性的保护
purge:
因为存在MVCC,决定最终是否删除,如果没被任何事务引用,可以删除,之前的删除只是改了个标志
执行清理时,historyList 找undo log 然后再从undo page中找undo log,避免大量随机读写
太长了通过延时操作解决
group commit:
数据库都提供了group commit的功能,即一次fsync可以刷新确保多个事务日志被写入文件
为保证MySQL数据库上层二进制日志的写入顺序和InnoDB层的事务提交顺序一致,MySQL数据库内部使用了prepare_commit_mutex这个锁,会失效
解决:Binary Log Group Commit(BLGC)
binlog放入队列,多个事务可以一次fsync写入,然后直接调用引擎层的group commit即可
隔离级别
READ UNCOMMITTED READ COMMITTED REPEATABLE READ SERIALIZABLE
InnoDB存储引擎在RR事务隔离级别下,使用Next-Key Lock锁的算法,因此避免幻读的产生。
InnoDB存储引擎在默认的REPEATABLE READ的事务隔离级别下已经能完全保证事务的隔离性要求
锁机制
锁命令
SHOW ENGINE INNODB STATUS
锁原理
两种标准的行级锁: 共享锁(S Lock),允许事务读一行数据。 排他锁(X Lock),允许事务删除或更新一行数据。
支持在不同粒度上进行加锁操作,InnoDB存储引擎支持一种额外的锁方式,称之为意向锁(Intention Lock) InnoDB存储引擎支持意向锁设计比较简练,其意向锁即为表级别的 1)意向共享锁(IS Lock),事务想要获得一张表中某几行的共享锁 2)意向排他锁(IX Lock),事务想要获得一张表中某几行的排他锁
意向锁之间是互相兼容的,emmm……那你存在的意义是啥? 但是它会与普通的排他 / 共享锁互斥: 这里的排他 / 共享锁指的都是表锁!!!意向锁不会与行级的共享 / 排他锁互斥!!!
意向锁是有数据引擎自己维护的,用户无法手动操作意向锁,在为数据行加共享 / 排他锁之前,InooDB 会先获取该数据行所在在数据表的对应意向锁
3种行锁的算法,其分别是:
Record Lock:单个行记录上的锁,总锁住索引
Gap Lock:间隙锁,锁定一个范围,但不包含记录本身
Next-Key Lock∶
Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身;
在查询列是唯一索引下降级为record lock
锁问题
幻读问题:(同一事务读到之前不存在的行)
幻读指在同一事务下,连续执行两次同样的SQL语句可能导致不同的结果,
第二次的SQL语句可能会返回之前不存在的行
SELECT…FOR UPDATE对读取的行记录加一个X锁,其他事务不能对已锁定的行加上任何锁。
SELECT…LOCK IN SHARE MODE对读取的行记录加一个S锁,其他事务可以向被锁定的行加S锁,但是如果加X锁,则会被阻塞。
Next-Key Lock解决,锁住范围的插入, 通过对事务加X锁,就避免了这个问题
脏读:(不同事务读到没提交的行) 脏读指的就是在不同的事务下,当前事务可以读到另外事务未提交的数据,简单来说就是可以读到脏数据
不可重复读:(一个事务内两次读到的数据不一样) 脏读是读到未提交的数据,而不可重复读读到的却是已经提交的数据,但是其违反了数据库事务一致性的要求 默认事务隔离级别是READ REPEATABLE,采用Next-Key Lock算法,通过对事务加X锁,避免了不可重复读的现象
死锁: 死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象 除了超时机制,当前数据库还都普遍采用wait-for graph(等待图)的方式来进行死锁检测。
innodb不存在锁升级带来的性能问题。 因为其不是根据每个记录来产生行锁的,相反,其根据每个事务访问的每个页对锁进行管理的,采用的是位图的方式。 因此不管一个事务锁住页中一个记录还是多个记录,其开销通常都是一致的。
mysql中联合索引的存储方式
联合索引: 多个列索引,也是B+树,键值大于等于2; 键值都是排序的,通过叶子节点可以逻辑上顺序地读出所有数据, 对第二个键值也进行了排序处理,有时可以避免多一次的排序操作,比如某个用户的购买时间
覆盖索引: 从辅助索引就可以查到的记录,不需要查询聚集索引; 比如查主键,查联合索引的(a,b)中的b
聚集索引: b+树,索引节点和叶子节点,数据都在叶子节点上,顺序排列,相邻页双向链表连接 按照整张表主键构造B+树,叶子节点存放行记录,也称数据页,页间双向链表连接 因为按照主键,每张表只有一个聚集索引 聚集索引与辅助索引不同的是,叶子节点存放的是否是一整行的信息。
辅助索引: 叶子节点不包含行数据,包含的是键值和书签(行数据的聚集索引键) 非主键索引树搜索回到主键索引树搜索的过程称为:回表,
何时使用索引经验: 取值范围广,没有什么重复,适合使用B+树索引;性别、地区这种低选择性的没必要; SHOW INDEX结果中的列Cardinality来观察。
innodb引擎
InnoDB存储引擎表是索引组织表,即表中数据按照主键顺序存放 索引组织的表,数据段即为B+树的叶子节点,索引段即为B+树的非索引节点 B+树索引本身并不能找到具体的一条记录,能找到只是该记录所在的页。数据库把页载入到内存,然后通过Page Directory再进行二叉查找
区别: 事务 外键 聚集索引 行锁 没有保存具体行数
关键特性:
后台线程+内存(缓冲池,LRU列表,FREE,FLUSH,重做日志buff,checkpoint) 插入缓存:判断缓冲池不在则仿佛缓冲对象合并,慢慢插入到Insert BufferB+树 两次写:页的副本还原页,分为内存和共享表空间磁盘,脏页写到buff,到共享表空间磁盘,再同步磁盘 自适应哈希索引:AHI是通过缓冲池的B+树页构造而来,自动根据访问的频率和模式来自动地为某些热点页建立哈希索引 异步IO:优化IO 刷新邻居页:检测该页所在区页的脏页一起刷新
脏页
Update或Delete改变页中的记录,此时页是脏的,缓冲池中的页的版本要比磁盘的新 先写重做日志,再修改页记录,便于宕机恢复
检查点
Checkpoint之前的页已经刷新回磁盘。数据库只需对Checkpoint后的重做日志进行恢复。这样就大大缩短了恢复的时间。
B+树
若想最大性能地构造一棵二叉查找树,需要这棵二叉查找树是平衡
平衡二叉树的定义如下:
首先符合二叉查找树的定义,其次必须满足任何节点的两个子树的高度最大差为1
查询快,维护有时需要多次旋转
B树,减少磁盘IO次数的多叉自平衡树,一个节点可以有多个孩子,顺序排列
B+树是一种特殊的AVL,中间节点不保存数据,只用来索引(b树是每个关键字都保存数据),各叶子节点顺序排列指针连接
B+树的查找次数,取决于B+树的高度
红黑树
红黑树是在普通二叉树上,节点添加一个颜色属性形成的,同时需要同时满足一些性质:
性质一:节点是红色或者是黑色;
性质二:根节点是黑色;
性质三:每个叶节点(NIL或空节点)是黑色;
性质四:每个红色节点的两个子节点都是黑色的(也就是说不存在两个连续的红色节点);
性质五:从任一节点到其没个叶节点的所有路径都包含相同数目的黑色节点;
什么场景索引更慢
查询中很少使用或者参考的列 只有很少数据值的列 text, image和bit数据类型的 表记录太少,不需要创建索引 频繁更新的字段不适合创建索引,修改性能远远大于检索性能时 某些数据包含大量重复数据,因此他建立索引就没有太大的效果(性别)
MVCC
涉及到一致性非锁定读。 一致性的非锁定读指InnoDB存储引擎通过行多版本控制的方式来读取当前执行时间数据库中行的数据 读取操作不会因此去等待行上锁的释放。相反地,InnoDB存储引擎会去读取行的一个快照数据 快照数据是指该行的之前版本的数据,该实现是通过undo段来完成
RC下非一致性读总是读取被锁定行的最新一份快照数据 RR下非一致性读总是读取事务开始时的行数据版本
根据比较版本号来处理数据的是否显示,从而达到读取数据的时候不需要加锁
RC、RR 两种隔离级别的事务在执行普通的读操作时,通过访问版本链的方法,使得事务间的读写操作得以并发执行,从而提升系统性能。RC、RR 这两个隔离级别的一个很大不同就是生成 ReadView 的时间点不同,RC 在每一次 SELECT 语句前都会生成一个 ReadView,事务期间会更新,因此在其他事务提交前后所得到的 m_ids 列表可能发生变化,使得先前不可见的版本后续又突然可见了。而 RR 只在事务的第一个 SELECT 语句时生成一个 ReadView,事务操作期间不更新。
8.0相比5.0的改进
https://blog.csdn.net/ren6370/article/details/88414463
##全文索引 全文检索通常使用倒排索引来实现 倒排索引同B+树索引一样,也是一种索引结构。它在辅助表(auxiliary table)中存储了单词与单词自身在一个或多个文档中所在位置之间的映射。 其拥有两种表现形式: inverted file index,其表现形式为{单词,单词所在文档的ID} full inverted index,其表现形式为{单词,(单词所在文档的ID,在具体文档中的位置)}