!> Mysql面试题重点围绕事务、隔离级别、锁、索引、存储引擎
考察点如下:
这种结果告诉我们其实在MySQL可重复读的隔离级别中并不是完全解决了幻读的问题(因为select查询的时候是在可重复读的情况下将会快照读,也就是直接复用之前的查询结果),而是解决了读数据情况下的幻读问题。而对于修改的操作依旧存在幻读问题(对于修改操作,将会是当前读,也就是执行修改操作的时候去数据库里面查询最新的结果,可能之前我们查询的是没有这一条记录,但是现在我们要修改的时候去查询,发现会有记录因此就会出现幻读的情况,所以这种基于修改的幻读情况在RR隔离级别是无法避免的,但是这只是对数据修改的操作(update、insert、delete)当前读产生的结果,他其实不是幻读)。
因此最后是如何解决幻读的呢?
在 MySQL 中,事务支持是在引擎层实现的,有的存储引擎支持事务,有的不支持事务。 MySQL是一个支持多引擎的系统,但并不是所有的引擎都支持事务。比如MySQL原生的 MyISAM 引擎就不支持事务,这也是 MyISAM 被 InnoDB 取代的重要原因之一
!>事务是什么:事务是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。事务是逻辑上的一组操作,要么都执行,要么都不执行。
类似问题: 数据库用的是什么?说说数据库事务的特性。 类似问题:ACID 是什么?具体介绍一下。
!> ACID:分别对应原子性atomicity,一致性consistency,隔离性isolation,持久性durability
“脏读”面试关注点:
“不可重复读”面试关注点:
“幻读”面试关注点: 案例:事务 A 读了一次商品表,得到最后的 ID 是 3,事务 B 也同样读了一次,得到最后 ID 也是 3。接下来事务 A 先插入了一行,然后读了一下最新的 ID 是 4,刚好是前面 ID 3 加上 1,然后事务 B 也插入了一行,接着读了一下最新的 ID 发现是 5,而不是 3 加 1。这时,你发现在使用 ID 做判断或做关键数据时,就会出现问题,这种现象就像是让事务 B 产生了幻觉一样,读取到了一个意想不到的数据,所以叫幻读。当然,不仅仅是新增,删除、修改数据也会发生类似的情况。
要想解决幻读不能升级事务隔离级别到“可串行化”,那样数据库也失去了并发处理能力。
注意:MySQL 的 Innodb 引擎通过 MVCC 和 next-key lock已经解决了幻读问题
MVCC原理: 从多版本和锁机制来讲
undo log里面存储的数据都是我们操作的反向数据,比如我们这次是插入操作,那么我们就会存储一个delete在undo log里面,
类似问题:事务的隔离级别 类似问题:mysql 隔离级别 类似问题:mysql 的事务隔离级别有几种啊 !> 越往下效率越低
理解:SQL 标准定义了四个隔离级别:
!> 为了解决不可重复读,或者为了实现可重复读,MySQL 采用了 MVVC (多版本并发控制) 的方式。 实现:MVVC机制以及undo_log
隔离级别 | 内容 | 解决的问题以及出现的问题 | 实现原理 |
---|---|---|---|
READ-UNCOMMITTED(读取未提交) | 最低的隔离级别,允许读取尚未提交的数据变更, | 可能会导致脏读、幻读或不可重复读。 | 读无锁。改启用行级共享锁 |
READ-COMMITTED(RC读取已提交) | 允许读取并发事务已经提交的数据, | 可以阻止脏读,但是幻读或不可重复读仍有可能发生。 | 读取:行级共享锁;改:行级排它锁 |
REPEATABLE-READ(可重复读) | 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改 | 可以阻止脏读和不可重复读,但幻读仍有可能发生。 | 读取共享锁直到事务结束释放, 写排它锁直到事务结束释放 |
SERIALIZABLE(可串行化) | 最高的隔离级别,对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰, | 该级别可以防止脏读、不可重复读以及幻读。 | 读取表级共享锁直到事务结束释放。写表级排它锁直到事务结束释放 |
如何实现参考极客时间课程mysql实战45讲与https://blog.csdn.net/sanyuesan0000/article/details/90235335
读未提交实现:因为读不会加任何锁,所以写操作在读的过程中修改数据,所以会造成脏读。好处是可以提升并发处理性能,能做到读写并行。换句话说,读的操作不能排斥写请求。
读已提交实现: 为什么读已提交产生不可重复读:这跟 READ COMMITTED 级别下的MVCC机制有关系,在该隔离级别下每次 select的时候新生成一个版本号,所以每次select的时候读的不是一个副本而是不同的副本。在每次select之间有其他事务()或实例(都是在同一个事务)更新了我们读取的数据并提交了,那就出现了不可重复读。
因为读已提交是在每次select的时候会生成一个read-view,所以同一个事务select之间可能有其他事务修改了数据,或者自己这个事务也可能修改数据,因为自己的修改也是可以读取到的。
读的时候不加锁,写的时候会加写锁
可重读实现: 读的时候加读锁,写的时候加写锁
序列化实现:
其他同上 !> 日常应用中推荐将隔离级别设计为已提交读
原因:
生产中使用RC隔离级别主要原因如下:
使用RR隔离级别,
以下答案来自于极客时间的mysql实战45讲 在实现上,数据库里面会创建一个视图,访问的时候以视图的逻辑结果为准。在“可重复读”隔离级别下,这个视图是在事务启动时创建的,整个事务存在期间都用这个视图。 在“读提交”隔离级别下,这个视图是在每个 SQL 语句开始执行的时候创建的。“读未提交”隔离级别下直接返回记录上的最新值,没有视图概念;而“串行 化”隔离级别下直接用加锁的方式来避免并行访问。
实现:MVVC机制以及undo_log
简单讲,如果没有MVCC,当想要读取的数据被其他事务用排它锁锁住时,只能互斥等待;而这时MVCC可以通过提供历史版本从而实现读取被锁的数据的历史版本,从而避免了互斥等待。
InnoDB采用的MVCC实现方式是:在需要时,通过undo日志构造出历史版本
两个实现⽅式:
如何实现参考极客时间课程mysql实战45讲与https://blog.csdn.net/sanyuesan0000/article/details/90235335
!> 类似问题: 如何实现事务 我就回答了MVCC + 一顿猛吹
!> 事务的特性以及对应的问题同上
那ACID靠什么保证的呢? 参考: https://blog.csdn.net/weixin_39524574/article/details/111693947
至于数据库事务锁,分为悲观锁和乐观锁,“悲观锁”认为数据出现冲突的可能性很大,“乐观锁”认为数据出现冲突的可能性不大。那悲观锁和乐观锁在基于 MySQL 数据库的应用开发中,是如何实现的呢?
悲观锁一般利用 SELECT … FOR UPDATE 类似的语句,对数据加锁,避免其他事务意外修改数据。
乐观锁利用 CAS 机制,并不会对数据加锁,而是通过对比数据的时间戳或者版本号,实现版本判断。
类似问题:那可重复读能解决什么 读未提交:出现脏读,不可重读,幻读问题 读已提交:解决脏读问题,出现不可重读,幻读问题 可重读:出现幻读问题,解决脏读,不可重读 序列化:解决脏读,不可重读,幻读问题
如何实现参考极客时间课程mysql实战45讲与https://blog.csdn.net/sanyuesan0000/article/details/90235335
聚簇索引,是每一个叶子节点最终都保留了一整行的记录信息,不需要进行回表,直接可以查找到 但是非聚簇索引是每一个叶子节点都保留对应的主键值,通过主键进行回表来获取对应的记录信息,需要查两次
类似问题: 数据库索引结构是什么样的(我回答B+树,然后问对磁盘有什么优势夺命追问,我说降低IO次数,问为什么) 类似问题: 数据库使用b+树的好处 类似问题: b+树的特性,为啥要用到这 类似问题: B+ Tree 类似问题: 谈谈索引的数据结构?说了 B+树 类似问题: B+树和 B-树的区别以及优点? 类似问题: 为什么不用搜索树? 类似问题: B+树的特点 类似问题: mysql 索引 2次 类似问题:mysql索引结构。
索引的数据结构和具体存储引擎的实现有关,在MySQL中使用较多的索引有Hash索引,B+树索引,全文索引等,而我们经常使用的InnoDB存储引擎的默认索引实现为:B+树索引。对于哈希索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;其余大部分场景,建议选择BTree索引。
别人的: 这个问题会涉及到mysql的存储数据结构,B+tree 多叉搜索树,有序,类似二叉搜索树(特性:中序遍历是有序的);curd的时间复杂度都是logN; 再谈谈mysql的索引结构,innodb引擎中分主键(聚簇索引)索引树和二级索引树; Innodb的主键索引树的叶子节点上存储行数据,非叶子结点只存储主键id,简单讲就是聚簇索引相当于物理内存地址(一级指针),查询快; 而二级索引树的每个节点只会存储索引字段值和主键id; 2种索引查询对比: 主键索引树:主键id=>叶子结点row数据 二级索引树: 二级索引树上找到对应的id=>主键索引树上的id=>主键索引树上的叶子结点行记录
上面“二级索引树=>主键索引树”的过程叫做“回表”,可以通过“索引覆盖”,“索引下推”优化
个人总结,可能不准确的地方
不一定,通常,通过索引查询数据比全表扫描要快。但是我们也必须注意到它的代价。 索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时,索引本身也会被修改。 这意味着每条记录的INSERT,DELETE,UPDATE将为此多付出4,5 次的磁盘I/O。 因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢。使用索引查询不一定能提高查询性能,索引范围查询(INDEX RANGE SCAN)适用于两种情况:
参考:https://zhuanlan.zhihu.com/p/140876416
自己说有效减少磁盘IO次数,可以提高
追问:B树同样也是一样的树高也可以做的很低呀,
B树占用内存比较大,B+树只是在叶子节点存放我们需要的数据
追问:占用很大内存怎么理解
B+树搜索经过路径中节点的时候,比如主键,只会保存主键的值,并不会保存其他列的记录信息,只是在最后到叶子节点的时候才会保存一整行的记录,所以B+树会比B树占用内存小,
追问:既然mysql索引是b+树,有一种特殊的索引是联合索引你知道么,
类似问题:对于数据结构里面,二叉树,二叉搜索树,B树,B+树,这四种树你能谈一下你的理解么 B树与B+树的区别 B树每个节点都存储数据,所有节点组成这棵树。B+树只有叶子节点存储数据(B+数中有两个头指针:一个指向根节点,另一个指向关键字最小的叶节点),叶子节点包含了这棵树的所有数据,所有的叶子结点使用链表相连,便于区间查找和遍历,所有非叶节点起到索引作用。
B树中叶节点包含的关键字和其他节点包含的关键字是不重复的,B+树的索引项只包含对应子树的最大关键字和指向该子树的指针,不含有该关键字对应记录的存储地址。
B树中每个节点(非根节点)关键字个数的范围为m/2(向上取整)-1,m-1,并且具有n个关键字的节点包含(n+1)棵子树。B+树中每个节点(非根节点)关键字个数的范围为m/2(向上取整),m,具有n个关键字的节点包含(n)棵子树。
B+树中查找,无论查找是否成功,每次都是一条从根节点到叶节点的路径。
B树的优点
B+树的优点 所有的叶子结点使用链表相连,便于区间查找和遍历。B树则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。 b+树的中间节点不保存数据,能容纳更多节点元素。 B树和B+树的共同优点 考虑磁盘IO的影响,它相对于内存来说是很慢的。数据库索引是存储在磁盘上的,当数据量大时,就不能把整个索引全部加载到内存了,只能逐一加载每一个磁盘页(对应索引树的节点)。所以我们要减少IO次数,对于树来说,IO次数就是树的高度,而“矮胖”就是b树的特征之一,m的大小取决于磁盘页的大小。
从数据结构的角度看,常用的索引可以分为full-text索引,hash索引,b+树索引:
在创建表时,InnoDB 存储引擎默认使用表的主键作为主键索引,该主键索引就是聚簇索引(Clustered Index),如果表没有定义主键,InnoDB 就自己产生一个隐藏的 6 个字节的主键 ID 值作为主键索引,而创建的主键索引默认使用的是 B+Tree 索引。
所以 B+Tree 相比于 B 树和二叉树来说,最大的优势在于查询效率。
那么问题来了,如果你当前查询数据时候,不是通过主键 ID,而是用商品编码查询商品,那么查询过程又是怎样的呢?
通过非主键(辅助索引)查询商品数据的过程
如果你用商品编码查询商品(即使用辅助索引进行查询),会先检索辅助索引中的 B+Tree 的 商品编码,找到对应的叶子节点,获取主键值,然后再通过主键索引中的 B+Tree 树查询到对应的叶子节点,然后获取整行数据。这个过程叫回表。
以上就是索引的实现原理。
如果你被问到“为什么 MySQL 会选择 B+Tree 当索引数据结构?”其实在考察你两个方面: B+Tree 的索引原理; B+Tree 索引相比于其他索引类型的优势。
我们刚刚已经讲了 B+Tree 的索引原理,现在就来回答一下 B+Tree 相比于其他常见索引结构,如 B 树、二叉树或 Hash 索引结构的优势在哪儿?
B+Tree 相对于 B 树 索引结构的优势
B+Tree 只在叶子节点存储数据,而 B 树 的非叶子节点也要存储数据,所以 B+Tree 的单个节点的数据量更小,在相同的磁盘 I/O 次数下,就能查询更多的节点。
另外,B+Tree 叶子节点采用的是双链表连接,适合 MySQL 中常见的基于范围的顺序查找,而 B 树无法做到这一点。
B+Tree 相对于二叉树索引结构的优势
对于有 N 个叶子节点的 B+Tree,其搜索复杂度为O(logdN),其中 d 表示节点允许的最大子节点个数为 d 个。在实际的应用当中, d 值是大于100的,这样就保证了,即使数据达到千万级别时,B+Tree 的高度依然维持在 3~4 层左右,也就是说一次数据查询操作只需要做 3~4 次的磁盘 I/O 操作就能查询到目标数据(这里的查询参考上面 B+Tree 的聚簇索引的查询过程)。
而二叉树的每个父节点的儿子节点个数只能是 2 个,意味着其搜索复杂度为 O(logN),这已经比 B+Tree 高出不少,因此二叉树检索到目标数据所经历的磁盘 I/O 次数要更多。
B+Tree 相对于 Hash 表存储结构的优势
我们知道范围查询是 MySQL 中常见的场景,但是 Hash 表不适合做范围查询,它更适合做等值的查询,这也是 B+Tree 索引要比 Hash 表索引有着更广泛的适用场景的原因。
至此,你就知道“为什么 MySQL 会选择 B+Tree 来做索引”了。在回答时,你要着眼于 B+Tree 的优势,然后再引入索引原理的查询过程(掌握这些知识点,这个问题其实比较容易回答)。
索引优化: 对于执行计划,参数有 possible_keys 字段表示可能用到的索引,key 字段表示实际用的索引,key_len 表示索引的长度,rows 表示扫描的数据行数。
这其中需要你重点关注 type 字段, 表示数据扫描类型,也就是描述了找到所需数据时使用的扫描方式是什么,常见扫描类型的执行效率从低到高的顺序为(考虑到查询效率问题,全表扫描和全索引扫描要尽量避免):
ALL(全表扫描);
index(全索引扫描);
range(索引范围扫描);
ref(非唯一索引扫描);
eq_ref(唯一索引扫描);
const(结果只有一条的主键或唯一索引扫描)。
总的来说,执行计划是研发工程师分析索引详情必会的技能(很多大厂公司招聘 JD 上写着“SQL 语句调优” ),所以你在面试时也要知道执行计划核心参数的含义,如 type。在回答时,也要以重点参数为切入点,再扩展到其他参数,然后再说自己是怎么做 SQL 优化工作的。
常见索引优化方法: 前缀索引优化
前缀索引就是用某个字段中,字符串的前几个字符建立索引,比如我们可以在订单表上对商品名称字段的前 5 个字符建立索引。使用前缀索引是为了减小索引字段大小,可以增加一个索引页中存储的索引值,有效提高索引的查询速度。在一些大字符串的字段作为索引时,使用前缀索引可以帮助我们减小索引项的大小。
但是,前缀索引有一定的局限性,例如 order by 就无法使用前缀索引,无法把前缀索引用作覆盖索引。
覆盖索引优化
覆盖索引是指 SQL 中 query 的所有字段,在索引 B+tree 的叶子节点上都能找得到的那些索引,从辅助索引中查询得到记录,而不需要通过聚簇索引查询获得。假设我们只需要查询商品的名称、价格,有什么方式可以避免回表呢?
我们可以建立一个组合索引,即商品ID、名称、价格作为一个组合索引。如果索引中存在这些数据,查询将不会再次检索主键索引,从而避免回表。所以,使用覆盖索引的好处很明显,即不需要查询出包含整行记录的所有信息,也就减少了大量的 I/O 操作。
联合索引
联合索引时,存在最左匹配原则,也就是按照最左优先的方式进行索引的匹配。比如联合索引 (userpin, username),如果查询条件是 WHERE userpin=1 AND username=2,就可以匹配上联合索引;或者查询条件是 WHERE userpin=1,也能匹配上联合索引,但是如果查询条件是 WHERE username=2,就无法匹配上联合索引。
另外,建立联合索引时的字段顺序,对索引效率也有很大影响。越靠前的字段被用于索引过滤的概率越高,实际开发工作中建立联合索引时,要把区分度大的字段排在前面,这样区分度大的字段越有可能被更多的 SQL 使用到。
区分度就是某个字段 column 不同值的个数除以表的总行数,比如性别的区分度就很小,不适合建立索引或不适合排在联合索引列的靠前的位置,而 uuid 这类字段就比较适合做索引或排在联合索引列的靠前的位置。
区分度公式:
总结:
查找过程可以理解为:最左匹配原则 参考
二叉排序树(Binary Sort Tree),又称为二叉查找树,它或者是一颗空树,或者是具有下列性质的二叉树:
平衡二叉树(self-Balancing Binary Search Tree,也叫做AVL树),是一种二叉排序树,其中每一个节点的左右子树的高度差至多等于1 前提首先是一颗二叉排序树,而后需要保持平衡特性所以就叫做平衡二叉树。
2-(我们称为2节点)或三个孩子(我们称为3节点)
一个2节点包含一个元素和两个孩子(或没有孩子),且与二叉排序树类似,左子树包含的元素小于该元素,右子树包含的元素大于该元素,不过与二叉排序树不同的是,这个2节点要么没有孩子,要么就有两个,不能只有一个孩子。
一个3节点包含一小一大两个元素和三个孩子(或没有孩子),一个3节点要么没有孩子,要么具有3个孩子,如果某个3节点有孩子的话,左子树包含小于较小元素的元素,右子树包含大于较大元素的元素,中间元素包含介于两元素之间的元素。
2-3-4树包含了4节点的使用,一个4节点包含小中大三个元素和四个孩子(或没有孩子),一个4节点要么没有孩子,要么具有4个孩子,如果某个4节点有孩子的话,左子树包含小于最小元素的元素,第二子树包含大于最小元素、小于第二元素的元素,第三子树包含大于第二元素,小于最大元素的元素,右子树包含大于最大元素的元素
B树是一种平衡的多路查找树,2-3树与2-3-4树都是B树的特例,节点最大的孩子数目称为B树的阶。因此,2-3树是3阶B树,2-3-4树是4阶B树
B+树参照《大话数据结构》P352
假设我们有张表,结构如下:
create table user( id int(11) not null, age int(11) not null, primary key(id), key(age) );
覆盖索引指的是在一次查询中,如果一个索引包含或者说覆盖所有需要查询的字段的值,我们就称之为覆盖索引,而不再需要回表查询。
而要确定一个查询是否是覆盖索引,我们只需要explain sql语句看Extra的结果是否是“Using index”即可。
以上面的user表来举例,我们再增加一个name字段,然后做一些查询试试。
explain select * from user where age=1; //查询的name无法从索引数据获取 explain select id,age from user where age=1; //可以直接从索引获取
后面的问题:为什么用 b+树 b 和 b+区别
参考 + 自己总结的mysql MVCC中的涉及到锁的笔记
InnoDB 的锁,与索引类型,事务的隔离级别相关。InnoDB 到底是行锁还是表锁取决于你的 SQL 语句。如果查询没有命中索引,也将退化为表锁。InnoDB 的行锁是实现在索引上的,而不是锁在物理行记录上。所以如果访问没有命中索引,也无法使用行锁,将要退化为表锁。
间隙锁:间隙锁是可重复读级别下才会有的锁,结合MVCC和间隙锁可以解决幻读的问题。我们还是以user举例,假设现在user表有几条记录
e data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal"> 当我们执行:
begin; select * from user where age=20 for update; begin; insert into user(age) values(10); #成功 insert into user(age) values(11); #失败 insert into user(age) values(20); #失败 insert into user(age) values(21); #失败 insert into user(age) values(30); #失败
只有10可以插入成功,那么因为表的间隙mysql自动帮我们生成了区间(左开右闭)
(negative infinity,10],(10,20],(20,30],(30,positive infinity)
由于20存在记录,所以(10,20],(20,30]区间都被锁定了无法插入、删除。
如果查询21呢?就会根据21定位到(20,30)的区间(都是开区间)。
需要注意的是唯一索引是不会有间隙索引的。
有这样一个查询 select id,name,age where name=.... 如何建立索引,并且使用到覆盖索引
用你刚刚设计的表来给我查询出全校所有高数在 85 分一以上的人的名字
SQL:userId(主播 Id) de..Id(设备 Id),怎么实现对主播与主播之间的重合数(共同关注数)
所以,从性能和存储空间方面考量,自增主键往往是更合理的选择。
有没有什么场景适合用业务字段直接做主键的呢?还是有的。比如,有些业务的场景需求是这样的:
你一定看出来了,这就是典型的 KV 场景。 由于没有其他索引,所以也就不用考虑其他索引的叶子节点大小的问题。 这时候我们就要优先考虑上一段提到的“尽量使用主键查询”原则,直接将这个索引设置为主键,可以避免每次查询需要搜索两棵树。
在 InnoDB 存储引擎下,一条 update 语句在 MySQL 内部执行大概会经历下面五个步骤: 1、执行器先找引擎取 id=2 这一行数据,如果 ID=2 这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。 2、执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。 3、引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务。 4、执行器生成这个操作的 binlog,并把 binlog 写入磁盘。 5、执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。
问题:
redolog 用于日志重放,宕机时,可以保证数据未提交的数据,正常提交 undolog 用于 mvccc ,事务回滚 binlog 是 server 层的,其它两个是引擎层的.binlog同步和恢复数据,
日志只要看这3篇文章就可以了:
b站的表同步好像就是订阅的binlog undo原子性,redo持久性
mvcc只有RC 和 RR级别有, 读提交和可重复读是 mvcc RR级别通过 Next-Key锁防止幻读
大家一般用哪个级别?我看互联网都是RC 并发量大的用RC
RR通过Next-key锁解决幻读
RR有next-key lock解决了幻读 = RR没幻读 next-key lock 是 行锁 + 间隙锁 RR下会产生幻读 但是 InnoDB和XtraDB通过MVCC解决幻读了 MVCC是解决不可重复读
我能想到的思路是从分布式出发 1.先从 cap 理论将其 2.然后从常用的 mysql 的主从同步是最终一致性将其 3.可以的话从服务发现分析(go的etcd,consult,还有常用的zk) 4.从业务场景出发,是保证强一致性(秒杀业务),还是最终一致性(实时性要求不高的业务)
一条sql语句的执行过程:https://mp.weixin.qq.com/s/xVWq3u-rekmg6HNGKRncng
这里有点疑问: 所以是先写 redo log 设置为 prepare ,再写 binlog,之后提交事务设置redolog 为 commit。因为 Master thread 在提交事务和每秒都会将 redo log buffer 刷进 redo log 里面 提交事务时,先将 redo log 刷进盘,标识为 prepare,之后 binlog 刷盘,再 redo log commmit 设置,完成事务
没有整理的题目: 设计题:设计一个购物车,给出应该有哪些数据表,每个表包含哪些字段
3、 InnoDB 的索引类型
针对每个连接维护一个线程,开销很大,如何优化(其实我也不懂,就瞎扯了 NIO……)
情景题:显示热门评论,按赞数倒序排序,写SQL(当场去世)
select 字段名与 select *的区别(索引失效)
索引为什么用B+树而不是二叉树(当场去世)
1.mysql 的主从(不了解)
sql:三句查询,要求建立索引来优化查询
mysql,innodb 和 myisam 引擎区别
怎么实现查表时候的内连接?
数据库事务回滚方法
MySQL 的存储引擎用的是什么?为什么选 InnoDB?
MySQL 的聚簇索引和非聚簇索引有什么区别?
B+树和二叉树有什么区别和优劣?
针对一个场景设计索引,考察的是联合索引与列选择性的知识
现有一个新的查询场景, 要怎么解决?
假如要查 A in () AND B in (), 怎么建索引?
查 A in () AND B in () 时, MySQL 是怎么利用索引的?
假如查询 A in (), MySQL 是针对 N 个值分别查一次索引, 还是有更好的操作?
第二轮就难很多。问了 innodb 怎么实现,(我乱猜了 hashtable,后来看了网上是 lru。。 难为小哥听我这个错到离谱的答案了)
然后 dict 怎么实现,我说了 hash key,然后每个 key 后面有 linked list,然后问我如果 key collision 太多怎么办,回 答扩容,怎么扩,我说 copy 到新的地方,然后 copy 的时候 mutex_lock。感觉答错 了。。但面试官也没接着说。(妈耶我真的好菜)