【面试必背】数据库篇

数据库

MySQL

架构

插件式存储引擎,将查询处理和数据存储提取分离
连接层
	客户端连接,连接处理、授权认证、安全方案
服务层
	核心服务,查询解析、分析、优化、缓存、内置函数
引擎层
	数据的存储和提取
存储层
	数据存储,与引擎交互

引擎

MyIsam
	不支持事务
	表锁
		更新数据时会锁整张表,使查询阻塞
	不支持外键
	非聚簇索引
		只缓存索引,不缓存真实数据
	内部维护了一个计数器,保存整个表的行数,执行count(*)时只需要读出该变量即可
	索引结构叶子节点的数据域存放的不是实际的数据记录,而是数据记录的地址,索引文件与数据文件分离,称为“非聚簇索引”
InnoDB
	MySQL默认引擎
	支持事务
	行级锁
		操作时只锁一行,对其他行没有影响
	外键
		新增数据时需要扫描数据是否合格,插入数据慢
		两张表依赖性太强,迁移表不方便
	聚簇索引
		缓存索引和真实数据,对内存要求高
		聚簇索引文件存放在主键索引的叶子节点,InnoDB必须要有主键
		辅助索引需要两次查询,会有回表
	不保存具体行数,执行count(*)时需要全表扫描

索引

一种数据结构,帮助快速查找数据
hash索引
	底层是hash表,调用一次hash函数就可以获取到相应键值,之后再回表查询获取的实际数据
	等值查询快,无法进行范围查询,索引顺序与原顺序无法保持一致,B+树左节点小于右节点,右节点大于父节点,支持范围查询
	不支持排序、模糊查询、不能避免回表
	等值查询快,但不稳定,当键大量重复,发生hash碰撞,效率低
B+树
	多路平衡查找树,每次都是从根节点出发,找到叶子节点才能获取所查键值,根据查询判断是否需要回表
	表没有设置主键,会用一个默认的row_id作为主键,如果没有主键,其他索引回表查找不到相应数据行
推荐整型自增主键而不是UUID
	UUID是字符串,需要消耗更多的存储空间
	自增的整型索引在磁盘中会连续存储,在读取一页数据时也是连续的,UUID是随机产生的,读取上下两行数据存储是分散的
	在插入或删除数据时,自增主键会在叶子节点末尾建立新的节点,不会破坏左侧子树结构,UUID主键,B+树为维持自身特性,可能会进行结构重构,消耗更多时间

分库分表

原因
	库和表数据大,查询耗时长
	发生意外,需要修复所有数据,修复数据困难
垂直拆分
	表字段拆分
		不建议,成本高,后期数据量大,可能还是需要
水平拆分
水平拆分
	将数据分散多张表
sharding-jdbc

日志

redo
	保证事务的持久性
		为了保证数据可靠性,最终需要落盘,但为了保证数据写入速度,需要引入基于内存的缓冲池,数据先在缓冲池,再刷新到磁盘,可能宕机导致缓冲池数据丢失
		用户写数据时,先写redo log,再持久化到磁盘,变成redo log file,用户数据在buffer中,如果宕机,读取磁盘的redo log file进行数据恢复
undo
	实现事务回滚
		MVCC事务重要组成部分,对数据变更会产生undo记录,记录到undo表空间
慢查询日志
	记录所有执行超过long_query_time秒的查询

调优

先确定主键,有主键的表MySQL会创建聚族索引,主键和数据行是在一块,不会涉及回表
开启慢查询;

用explain定位是否走索引;
加索引
语句慢可以查看是否建立了相应索引,索引字段尽量选择where条件后面的或order by、group by、join连接的字段,作为索引列,排序符合最左匹配原则,选的时候根据索引选择器,非重复数据行和重复数据行中间的排列,大的放左,小的放右的形式,多列的索引列,尽量建立联合索引而非多个单个索引
SQL书写,不要将索引列放到表达式中,或者用反向判断,not null、!=、not in等,会让索引失效
数据查询频繁,可以考虑使用覆盖索引,不需要回表操作的
表记录少,经常增删改的表,以及频繁更新的字段不适合创建索引
like分两次查,避免回表
text长度限制,索引失效,新建表存储,id倒排索引,加逗号分割,实时更新表

事务

ACID
	原子性
		事务要么全部成功,要么全部失败
	一致性
		事务开始前和结束后,数据完整性必须一致
	隔离性
		一个事务的执行不能干扰其他事务
	持久性
		事务结束后,该事务对数据库所作的更改持久的保存在数据库中,不会回滚
带来的问题
	更新丢失
		事务A和事务B操作同一行,事务B操作覆盖事务A的更新
	脏读
		事务A读取了事务B更新的数据,事务B回滚操作,事务A读到的数据是脏数据
	不可重复读
		事务A多次读取同一数据,事务B在事务A多次读取过程中,对数据做了更改并提交,导致事务A多次读取同一数据,结果不一致
	幻读
		事务A读取了几行数据,事务B插入一些数据,事务A发现多了一些不存在的数据
事务隔离级别
	读未提交
		最低隔离级别,允许读尚未提交的数据变更,会导致脏读、幻读、不可重复读
	读已提交
		允许读取已经提交的事务,可以阻止脏读,会出现幻读、不可重复读
	可重复读
		对同一字段多次读取结果一致,可以阻止脏读和不可重复读,会出现幻读
		InnoDB默认隔离级别
	可串行化
		最高隔离级别,完全服从ACID,所有事务依次执行,事务之前互不干扰
解决
	加锁
		读取数据前,对其加锁,阻止其他事务对数据修改
	MVCC
		多版本并发控制,不加任何锁,开销低,保存数据在某个时间点的快照来实现的,不管需要执行多长时间,每个事务看到的数据是一致的
		在每行记录后面保存两个隐藏列来实现,一个保存行的创建时间,一个保存行的过期时间。存储的不是真实时间,而是系统版本号,每开始一个新事务,系统版本号都会自动递增
		可重复读
			只查找版本早于当前事务版本的数据行,可以确保事务读取的行
日志
	redo log
		事务开启时,事务中的操作会先写入存储引擎的日志缓冲中,事务提交前,
	undo log

锁机制
读锁(共享锁)
写锁(排他锁)
乐观锁
主从复制
slave从master读取binlog进行数据同步

Redis

优点

基于内存运行的高性能KV数据库,内存中速度快
数据结构简单

数据结构

	string
		不同长度编码不同
	list
		有序链表
	hash
		value是键值对
	set
		无序集合
	zset
		有序集合
多线程IO,命令执行还是单线程

缓存问题

缓存雪崩
	大规模key同一时间失效,导致大量请求打入数据库,数据库压力增大,可能导致数据库宕机
		设置不同的过期时间
		采用熔断机制,限流
缓存击穿
	某个热点key失效,大并发集中请求
		热点key不设置过期时间
缓存穿透
	用户请求的数据不在缓存中,也不在数据库中,每次请求不存在的数据都会将请求打在数据库,大规模不存在的key打到数据库,可能导致数据库宕机
		将无效key放入redis中
布隆过滤器
基于位图的数据结构,存储的是二进制0和1,占用空间小,在缓存前加一层布隆过滤器,只有数据在布隆过滤器才查缓存
应用初始化时将数据库表中所有数据主键查询出来,构建布隆过滤器,后续接口在查询redis前先通过布隆过滤器查一下ID
缺点
	存在误判,要查到的元素不在容器中
	删除困难

持久化机制

AOF
	文件追加,增量,默认关闭,以日志形式记录每个写操作,将redis执行过的所有写指令记录下来,只许追加文件不可以改写文件,文件会越来越大

redis在AOF文件体积过大时,自动在后台对AOF进行重写
优点
数据准确性高
缺点
AOF文件大于RDB,恢复速度慢
效率低

RDB
	快照,全量,在指定时间间隔内将内在中的数据集快照写入磁盘,恢复时将快照文件直接读到内存
	redis单独创建一个子线程来进行持久化,先将数据写入到一个临时文件,持久化结束后,再用临时文件替换上次持久化好的文件,主进程不进行任何IO操作
	优点
		高效,恢复大的数据集会快一些
	缺点
		最后一次持久化的数据可能丢失

过期键删除策略

定期删除
每隔100ms随机抽取一批设置了过期时间的key,过期了则删除
惰性删除
部分key依靠定期删除没有被删除,采用惰性删除策略,需要用到key时再去检查下是否过期,过期则删除

淘汰策略

  1. volatile-lru: 从已设置过期时间的集合中挑选最近最少使用的数据淘汰,计算key的空闲时间
  2. allkeys-lru: 从数据集中挑选最近最少使用
  3. volatile-lfu: 从已设置过期时间的集合中挑选使用频率最少的数据淘汰
  4. allkeys-lfu: 从数据集中挑选使用频率最低
  5. volatile-ttl: 已设置过期时间,将要过期的数据
  6. volatile-random:已设置过期时间,任意数据
  7. allkeys-random:数据集任意选择数据
  8. noeviction: 不进行删除,达到最大内存时,直接返回错误信息。

与MySQL数据不一致

同步机制

全同步
	slave启动时初始化同步
	同步过程
		slave启动时,会向master发送一条SYNC指令
		master收到指令,启动一个备份进程将所有数据写到rdb文件中
		更新master状态(备份是否成功、备份时间等),将rdb文件内容发送给等待中的slave
	为每个等待中的slave注册写事件,当slave对应的socket可以发送数据时,再将rdb内容发送给slave
部分同步
	redis运行时修改同步
	redis的master/slave服务启动后,先进行全同步,所有写操作在master,读操作在slave
	同步过程
		master收到一个操作,判断是否要同步给slave
		需要同步,将操作记录到aof文件
		遍历所有slave,将操作指令和参数写入到slave的回复缓存
		slave对应的socket发送缓存中有空间写入数据,将数据通过socket发出去

集群

主从模式
	数据单向,主到从,主从数据一样,数据冗杂
	主节点宕机,从节点作为主节点的备份,可以晋升为主节点
		需要修改应用方的主节点地址,命令从节点复制新的主节点,过程需人工干预
	拓展主节点读能力,分担主节点压力
哨兵模式
	自动化故障恢复,一个哨兵线程监控所有节点状态,哨兵定时给节点发心跳请求
	每个哨兵以每秒钟一次的频率,向所有主从服务器以及哨兵实例发送指令,实例
	主从自动切换,可用性更高
	较难支持在线扩容
集群模式
	高可用、可扩展、分布式、容错性
	三主三从,一个主节点挂了,采用选举机制,子节点广播其他主节点,主节点投票选举

分布式锁

setNx
	set时存入当前线程的唯一标识,释放锁,del key,删除前判断是不是自己设置的锁,如果不是就不删除

PostgreSQL

与MySQL共同点:开源免费,可运行多个操作系统
PG:可靠性更高,SQL更加规范,高事务性,数据一致性完整性高
SQL标准严谨规范
支持索引类型多,复杂查询能力强
PG:主备复制靠物理复制,MySQL基于binlog逻辑复制,PG数据一致性更加可靠,复制性能高,对主机性能影响小
PG适合严格的金融行业,MySQL适合业务逻辑相对简单,对数据可靠性要求相对低

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值