PHP面试宝典之Mysql数据库高级篇(一)

聚簇索引和非聚簇索引的区别?

聚簇索引:是索引结构和数据一起存放的索引,一个表只能有一个,存储记录是物理上的连续,在innodb表中如果有主键,那聚簇索引就等于主键索引

非聚簇索引:是索引结构和数据分开存放的索引,一个表可以存在多个,存储记录是逻辑上的连续,非聚簇索引就是普通索引

每张表都会有一个主键索引和随便几个普通索引,每个索引都会构建属于自己的索引树

索引树

主键索引树、二级索引树

主键索引树:叶子节点保存的是行数据

二级索引树:叶子节点保存的是索引值和主键ID

回表:就是通过二级索引,找到主键ID,再通过主键ID查找到行数据

索引结构?

二叉树,红黑树,哈希表,b+树

B+树和哈希的区别?

B+树:范围查询性能更优;
哈希:全值匹配效率更高如:= 和in等

为什么b+树是范围查询更优?

因为b+树的叶子节点,使用了指针顺序(链表)从小到大连接,树叶节点两两相连,增加区间访问性,只需要遍历叶子节点就可以实现整棵树的遍历,而b树的叶子节点是独立的,无法查找区间

mysql为什么使用b+树?不使用b树?

1:b树只适合随机检索;b+树同时支持随机检索和顺序检索

2:b+树空间利用率更高(b+树,索引节点不存数据,只存索引,可以存更多,索引树就变的更矮,减少了i/o次数)

3:b+树查询效率更稳定

4:b+树范围查询性能更优

5:b+树增删索引节点时,效率更高

慢sql该如何处理?

explain关键字

table:操作的表

type:访问类型,查询级别,最好ref,至少要range,最后是index,all

possible_keys:可能应用的索引

key:使用的索引

rows:查询行数

MYSQL分库分表?

垂直分表和水平分表

垂直分表:按字段、功能、重要程度拆分

水平分表:按数据逻辑拆分,如ID范围、ID奇偶数;
例:创建总表:保留ID、子表名、子表ID范围;创建子表,存储数据;查询时:先查总表,得到子表名,再去子表查询

为什么要分库分表?

分库:单库的存储能力(磁盘容量)是固定的,单库连接数是有限的;

分表:单条sql执行过长,单表行数过多;(单表超过500万行、容量超过2G,如果预计三年后达不到这个级别,创建表时就不需要分库分表)

mysql都有哪些日志类型?

redo log重做日志,保证持久性

undo log回滚日志,保证原子性

bin log保证一致性

MySQL隔离级别?

序列化、可重复读、提交读、未提交读

序列化:最高隔离级别,按先后顺序执行事务

可重复读:mysql默认隔离级别;在当前事务提交前,对同一字段的多次读取,结果都一致,除非数据是被自己修改(可能导致:幻读,事务中插入报错)

提交读:其他数据库默认级别;允许读取已经提交的数据(可能导致:不可重复读、幻读)

未提交读:可以读取到,其他尚未提交的数据变更(可能导致:脏读、不可重复读、幻读);

脏读:正在执行的事务,读取到其他事务,未提交的数据

不可重复读:正在执行的事务,读取到其他事务,已提交的数据,导致前后不一

幻读:正在执行的事务,多次读取数据不变,但插入时,因其他事务的插入,造成插入失败

如何解决幻读问题?

1:在可重复读隔离级别下:
1):快照读,通过mvcc避免幻读
2):当前读,通过next-key(间隙锁+行级锁)避免幻读
2:使用序列化的隔离级别

什么是mvcc机制?

多版本 并发控制;是为了读取数据时,不加锁,提高读取效率和并发性;
解决的是:读写时的线程安全问题,线程不去争抢读写锁;

什么是当前读,快照读?

快照读:普通select,在读写时不加锁,但可能会读到历史数据,基于mvcc

当前读:悲观锁实现,读取时对数据加锁,读到的是最新数据;

提交读、可重复读这两种隔离机制,使用的都是快照读,基于mvcc实现

mvcc是如何实现提交读、可重复读的隔离级别的?

提交读:rc;在每次读取时,都会获得最新的 readview(事务修改前,事务提交后)

可重复读:rr;在事务执行之前读取一个 readview,之后每次读取的都是同一个,所以每次结果都一样

什么是readview?

我叫它 可读视图;当我们读取数据时,会有多个版本的数据,我们需要哪个版本并不知道,这时,readview就会根据条件,返回适合我们读取的版本数据;

什么是间隙锁?

使用范围查询,并请求共享锁或排它锁时,innodb会给符合条件的已有数据加锁,对于键值在条件范围内,但又不存在的记录,叫做间隙;例:ID:1~5,其中2、3、4被删除了不存在,但如果查询范围小于5时,被删除的数据,所在的记录就是间隙锁

事务的四大特性ACID?

原子性、一致性、隔离性、持续性

原子性:要么都做,要么都不做(undolog实现)

一致性:要么都成功,要么都失败(undolog、redolog、隔离性共同实现)

隔离性:并发情况下,事务数据不冲突,互不干涉(当前读、加锁,或mvcc快照读实现)

持续性:事务一旦提交,对数据库的改变是永久性的(redolog实现)

锁是为了解决什么问题?

锁是为了解决事务的隔离性问题,为了使事务之间互不影响,每个事务操作时都会对数据加锁,防止其他事务同时操作数据

锁是基于什么实现的?

锁是基于索引实现的,如果sql命中了锁,那锁住的就是索引所在节点(行级锁),如果没有命中索引,锁住的就是整个索引树(表级锁)

乐观锁、悲观锁?

乐观锁:认为操作无害,不会导致数据冲突;可以通过代码逻辑实现
实现:新增版本号字段,更新语句时:where子句中,当前版本号做为条件,更新字段中,当前版本号加一

悲观锁:认为操作有害,会导致数据冲突,所以每次操作都要先获取锁再进行操作
实现:共享锁、排它锁

共享锁:允许多事务同时查询当前数据
排它锁:只能由一个事务操作当前数据

注:详情可参考悲观锁、乐观锁

什么是死锁?

所谓死锁,是两个或两个以上进程,在执行过程中,由于竞争资源或彼此通信,造成的一种阻塞现象,如果没有外力作用,它们将无法继续执行,这就是死锁

出现死锁如何解决?

超时机制、死锁检测

超时机制:设置事务超时时间

死锁检测:等待图,判断事务是否存在回路,若存在则回滚最小事务

死锁场景及处理方案?

1:逻辑冲突,两个事务同时操作关联的a、b两表,但修改顺序交叉

2:并发修改同一记录(悲观锁、乐观锁)

3:索引使用不当,导致全表扫描

4:事务运行时间过长,操作范围过大

5:网络问题导致死锁

解决死锁:
1:使用乐观锁

2:事务中关联表的修改,前后顺序保持一致

3:减少事务的运行时间和修改范围

事务的底层是如何实现的?

通过dbms数据库管理系统实现的;
1:日志系统:是基础;记录所有数据库操作的详细信息,包括事务开始和结束的时间、操作类型、数据变化等,系统崩溃也可以使用日志恢复

2:读写锁定机制:避免数据冲突,通过读锁多事务共享,通过写锁,由一个事务独占

3:事务管理器:是核心;负责管理事务的生命周期,包括开始、提交、回滚等操作。当事务开始时,分配一个唯一标识,用于在日志系统中标记,当事务提交或回滚时,事务管理器将相关信息记录到日志中,并释放所有相关资源,包括读写锁,数据库连接等等;

4:内存缓存:为了提高数据库性能,使用内存缓存频繁访问的数据和索引,在事务中,缓存的更新会被缓存到内存中,直到事务提交时,才会写到磁盘中的数据库文件

5:数据库引擎:核心组件之一,负责管理数据的存储和检索。数据库引擎需要支持,原子性、一致性、隔离性和持久性,确保事务的所有操作要么全部成功,要么全部回滚到原始状态

事distinct 和 group by的区别

1:distinct 是为了字段去重,在select语句后,针对的是主句中所有字段
2:group by是对结果集进行分组,跟在where条件后,针对的是一个或对个列
3:更推荐group by,原因:语义更清晰,可以对数据进行更复杂的处理,更灵活
4:在语义相同,有索引的情况下:group by和distinct都能使用索引,效率相同。
5:在语义相同,无索引的情况下:distinct效率高于group by。原因是distinct 和 group by都会进行分组操作,但group by可能会进行排序,触发filesort,导致sql执行效率低下。(还有种说法加不加索引group by都比distinct更快,未印证)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值