mysql

Q. InnoDB 与 MyISAM 区别
A.
最主要的区别:Innodb支持事务 后者不支持
Q. 解释一下事务的四大特性(ACID)
A.
原子性:事务里的操作要么全都成功,要么全都失败
一致性:事务操作的结果是符合预期的,例如a转账给b,a的钱扣减后b的钱会增多
隔离性:事务之间互相隔离,操作不受干扰
持久性:事务提交后,对数据库的改动是永久的
Q. 解释一下mysql的事务隔离级别
A.
关系型数据库的事务隔离级别有读未提交,读提交,可重复读,串行化四种。
mysql的默认事务隔离级别是可重复读,开始事务时会创建一个快照(一致性视图)之后事务中的查询都通过这个快照查询。
幻读只会发生在当前读(select … where … for update以及update, delete, insert),不会发生在普通查询也叫快照读(select … where …)(因为快照读的视图始终一致).
幻读的表现是两次查询,第二次查询读到了第一次查询没有的行。(在另一个事务新插入了行)
幻读产生的原因是行锁只能锁住行,而新插入数据是插入间隙,所以innodb在不可重复读这个级别引入间隙锁,和行锁配合一起称为next-key lock,解决了幻读问题(也就是说mysql innodb在可重复读级别也不会发生幻读)。
间隙锁只锁间隙,互相不锁,next-key lock是由间隙锁和行锁组成的。
最高级别是串行化,全部事务按顺序执行,性能会降低很多,一般不用。
Q. 解释一下乐观锁与悲观锁
A.
悲观锁就是修改数据前,先加锁,再修改。适用于写比较多的场景
乐观锁就是不加锁,先修改,最终更新数据时,会判断一下有没有其他线程更新这个数据,有则报错,可以使用版本号机制(提交数据时比较版本号是否对应)等来实现。
Q. 解释一下mysql的mvcc(多版本并发控制)机制
A.
是一种提高并发的技术。在这个机制下,只有写-写相互阻塞,读-读或者读-写不会相互阻塞。实现上依赖undo log和读视图read view
mysql每一行隐藏了一些字段,如事务id(创建的事务id或者最后修改的事务id)和回滚指针(指向这条记录的上一个版本)
事务id在每次select操作时会读取小于当前事务id的条目,写操作又会写入最新的事务id。
回滚指针通过undo log,链式指向上个记录版本。
每个事务开启时,会开启一个读视图(可重复读级别一个事务从始至终读视图一致,读已提交级别每个读查询会生成新的读视图)
Q. 除了undo log,还有binlog和redo log,分别是?
A.
binlog是mysql server层log,任何引擎都有,记录sql语句的原始逻辑,方便主从复制和数据还原,写满时会新增文件,不会覆盖
redo log是innodb特有的,sql执行时不是直接写入数据页而是先写入redo log,记录对数据页的修改,再在适当的时候写入磁盘(先写日志后写磁盘)大小固定,写满时落盘,然后循环写,主要用于在崩溃重启时恢复数据,确保持久性。
Q. 解释一下两阶段提交?
A.
两阶段提交是指写入redo log和bin log的时候,先写redo log标记为prepare,再写binlog,再写redo log标记为commit,让redo log和binlog保持一致
如果先写redo log后写binlog,或者反过来,如果后写的时候mysql崩溃了,就会导致之后恢复数据时出现不一致的现象。
Q. mysql的聚集索引与非聚集索引分别是?
A.
聚集索引也就是主键索引,叶子节点存储一整行的数据,每张表只能有一个聚集索引。
非聚集索引的叶子节点存储主键的值,每张表可以有多个非聚集索引。
非聚集索引通常(查询的字段包含索引未覆盖的字段)需要最后回表再查一次聚集索引
Q. mysql的覆盖索引和索引下推是?
A.
覆盖索引就是索引存储的字段刚好包含需要查询的字段,就不需要回表直接从索引里查,例如where条件里用非聚集索引但查询字段只有id,或者where条件里是联合索引的最左列,查询字段是联合索引的其他列。
索引下推是联合索引中,范围查询时可以直接根据索引存储的信息在叶子节点索引内部判断是否符合条件,而不需要每次都回表拿整行数据查询是否符合条件(mysql 5.6+)
最左匹配原则是通过mysql建立联合索引时,会先对第一个字段排序,再对第二个字段排序,再对第三个字段…来实现的,所以联合索引是(a, b)但where只有b=xx时,无法走联合索引。
Q. innodb主键为什么推荐用自增id?
A.
由于索引是有序的,自增id在插入数据时只需要跟着上一个的后面插入也就是在b+树的右边扩展,而uuid这样的随机id插入时,为了保证索引有序,可能会导致b+树频繁合并或分裂。
Q. mysql的索引为什么用b+树,不用hash,红黑树,b树呢?
A.
其实是InnoDB索引的实现采用b+树。mysql查询经常要范围查询,hash最大的问题是不能范围查询,只能全表扫描
红黑树是二叉平衡树,存储大批量数据时树的高度太高,磁盘查询比较慢
b树相对于b+树,叶子之间没有指针,并且在非叶子节点中存储数据,导致在查询连续数据时可能会带来更多的随机 I/O,而 B+ 树的所有数据存在叶子节点上,叶子节点之间通过指针相互连接,能够减少顺序遍历时产生的额外随机 I/O。
Q. 为什么mongo使用b树?
A.
mongo的数据通常来说是json序列化的数据,不太使用范围查找,并且由于b树的数据就存在每个节点上,索引可以直接查到数据。
Q. map是怎么用红黑树的?
A.
map在hash算法冲突时,会把hash冲突的元素存入链表,当链表较长时,会改为存入红黑树,避免线性查找变得太慢
红黑树是一种二叉排序树,避免了二叉树在极端情况下退化成链表的情况,同时相对于AVL来说,允许局部的不平衡,这样插入和删除元素时需要调整的代价较小
leetcode other