【数据库】原理、MySQL、Redis

参考

  1. 《高性能MySQL(第三版)》
  2. CyC2018/CS-Notes
  3. Snailclimb/JavaGuide

数据库系统原理

【数据库】(1)数据库系统原理

  1. 什么是事务?
    事务是满足原子性、一致性、隔离性、持久性的一组操作,可以通过Commit提交一个事务,也可以使用Rollback回滚。
  2. 解释一下事务的四大特性。
    – 原子性:事务不可分割,要么全部执行, 要么失败回滚
    – 一致性:多个事务对同一个数据的读取结果是相同的,不能存在事务读取到旧数据
    – 隔离性:一个事务所做的修改对其他事务是不可见的
    – 持久性:事务提交之后,能够持久保存在数据库中,不丢失。
  3. 四大特性之间的关系是怎样的?
    数据库需要满足一致性和持久性,一致性需要靠原子性和隔离性来保证。
  4. 数据库在并发情况下,会产生哪些问题?
    在并发条件下如果没有保证隔离性会出现这些问题:
    – 修改丢失:另一个事务的修改覆盖了当前的修改。
    – 脏读:一个事务读取到了另一个事务的中间数据
    – 不可重复读:由于另一个事务的修改导致当前事务对数据的多次读取结果不同。
    – 幻影读:当前事务统计数据时,另一个事务插入或删除数据,导致多次统计结果不同。
  5. 事务有哪些隔离级别?
    – 未提交读:没有隔离,会造成脏读、不可重复读、幻影读
    – 提交读:其他事务提交后再读取,解决脏读问题
    – 可重复读:对同一数据多次读取结果一致,解决不可重复读问题
    – 可串行化:事务串行执行,不会存在并发一致性问题。
  6. InnoDB的隔离级别怎样,如何解决并发一致性问题?
    InnoDB的隔离级别是可重复读,使用多版本并发控制解决可重复读问题,使用Next-Key lock解决幻影读问题。
  7. 介绍一下3种范式。
    高一级的范式包括所有低级范式的规则
    – 第一范式:属性不可分。表中每个字段不可以继续分解。
    – 第二范式:非主属性完全依赖于键码。字段必须依赖于所有主键
    – 第三范式:非主属性禁止传递函数依赖。可以继续分解。

MySQL

1. 基础内容

  1. 一条SQL命令的执行流程是怎样的?
    客户端发送携带sql命令的请求,服务器进行语法解析和查询优化后,条用存储引擎的接口,存储引擎执行具体的查询操作,读取数据后返回。
  2. MyISAM与InnoDB引擎有什么区别?
    MyISAM是MySQL5.5之前的默认引擎,提供了数据压缩,执行速度快,但不支持事务,只有表级锁,且崩溃后无法安全恢复。
    InnoDB是MySQL5.5之后的默认引擎,支持事务、行级锁、外键,支持热备份。
  3. MySQL的数据类型有哪些?
    整数:tinyint,smallint,mediumint,int,bigint
    浮点数:float,double,decimal
    字符串:char,varchar(变长)
    时间日期:DateTime,TimeStamp
    整数和浮点数按照需要进行选择,字符串一般选择varchar,日期时间一般选择TimeStamp

2. 索引

  1. 谈一下B+Tree的原理。
    b+树图文详解
    – 数据保存在叶子节点,非叶子节点只保存每个子节点的最大值,这样每次查询都需要达到叶子节点,性能稳定
    – 叶子节点是有序的,并且在叶子节点使用指针连接形成链表,适合范围查询。
  2. MySQL的索引结构为什么使用B+树,而不是其他树形结构?
    https://www.bilibili.com/read/cv5985933/
    – 二叉查找树:不平衡,可能退化为链表
    – 平衡二叉树:需要维护平衡状态,需要旋转操作,在删除数据时的旋转需要O(logn)的时间。
    – 红黑树:不要求严格平衡,引入了颜色,在插入和删除数据时只需要O(1)的时间进行旋转即可;然而树太高,IO次数多,查询效率有所下降
    – B树:将二叉树改为多路平衡查找树,解决了树过高的问题
    – B+树:在B树的基础上,将非叶子节点改造为不存储数据的纯索引节点,进一步降低高度,同时将叶子节点用链表连起来,范围查询更加高效。
  3. MySQL有哪些索引类型?
    – B+Tree索引:是InnoDB的默认索引类型。InnoDB的B+Tree索引分为主索引和辅助索引,主索引的叶子节点记录了完整的数据,称为聚簇索引,表中的记录就是通过聚簇索引组织的,辅助索引的叶子节点记录了主键的值,因此使用辅助索引时,先查到主键的值,然后通过主索引查到具体的数据。支持全值查找、范围查找和最左前缀查找
    – 哈希索引:主要用于全值的精确查找
    – 全文索引:查找文本中的关键词
  4. 使用索引与表的大小的关系?
    对于比较小的表,可以直接使用全表扫描;
    对于中到大型的表,使用索引就很有效;
    对于特大型的表,可以使用分区技术。
  5. 什么时候使用索引?
    – 在where子句中出现的列,可以考虑使用索引
    – 数据唯一性差的字段不要使用索引,因为这样构造出来的B+树,很多很多关键字相等,在非叶子节点需要进行很多次的比较
  6. 应该怎样正确设置使用索引?
    – 索引列是独立的,不能带函数或者是表达式的一部分
    – 如果查询条件是多个列,那么可以使用多列的复合索引,其中区分度更高的列应该放在前面
    – 索引覆盖查询,如果索引包含了需要查询的值,那么就不需要再从主索引中读取记录。
  7. 什么时候索引会失效?
    – where子句中对索引列使用函数或表达式;
    – 查询条件中有or,那么需要or左右的列都需要索引,否则不会使用索引;
    – 存在隐式类型转换的,不会使用索引;
    – 范围查询中以%开头;
    – 复合索引中,如果不使用最左列,那么后续列也无法使用索引;
    – mysql可能会对语句进行优化,优化后的语句可能不使用索引更快。

3. 优化

  1. 如何优化查询?
    – 使用explain:查看select语句的查询类型,使用的索引,扫描的行数等
    – 减少请求的数据量:只获取需要的列,使用limit获取需要的行
    – 切分大查询,大的查询可能一次锁住很多数据,消耗资源
    – 分解多表关联查询:将多表关联查询分解为单表查询,然后在应用层连接。这样可以让缓存更容易命中,减少数据库压力

  2. 如何进行大表优化?
    可以对表进行切分,包括水平切分和垂直切分
    – 水平切分:又称为Sharding,将记录拆分到多个结构相同的表中
    – 垂直切分:可以将经常使用的列和不经常使用的列切分到不同的表中

  3. 如何进行水平切分?
    哈希取模hash(key)%N;按照Id范围划分;自定义切分然后把记录和分表的映射关系储存到一张映射表中。

  4. 水平切分产生什么问题,怎么解决?
    – 事务问题:InnoDB支持分布式事务
    – 多表关联:拆分成单表查询,然后在应用程序层关联
    – ID唯一性:全局ID,为每个分表指定一个ID范围,分布式id生成器

  5. 如何排查慢查询?
    – 在config中开启慢查询日志
    – 使用mysqldumpslow工具查看慢sql
    – 使用show processlist查看线程运行状态
    – 使用explain查看select语句的执行

Redis

  1. Redis为什么速度快?
    – 大部分操作是基于内存的
    – 使用单线程,避免了多线程竞争和上下文切换开销。
    – 使用非阻塞IO
  2. 介绍一下Redis单线程的工作模型。
    redis 单线程的理解
    首先多个Redis客户端是通过多个线程与Redis服务端建立socket连接,然后Redis对这些连接进行探测,查找出已经接收完客户端请求的连接,然后采用单线程的方式对请求数据进行处理,最后返回数据。
  3. Redis有哪些数据类型?
    String、Hash、List、Set、SortedSet
  4. SortedSet的底层实现?
    少量数据使用ziplist,大量数据使用skiplist。skiplist是跳跃表,方便有序链表的搜索,相比于红黑树,实现简单,插入迅速。每个节点不仅有指向当前层下一个节点的指针,还有指向下一层元素的指针,查找时先从上层开始查找,这样可以跳过很多元素。
  5. Redis清除过期的key有哪些方式?
    – 定期删除:默认每100ms,随机抽取一些设置了过期时间的key,检验其是否过期
    – 惰性删除:查询时,如果key过期,则触发删除
  6. Redis有哪些key淘汰策略?
    如果redis内存耗尽时,需要触发key的淘汰策略。
    两个范围所有key,设置了过期时间的key。3种策略:LRU、LFU、RANDOM。组合得到6种,另外还有不淘汰,淘汰最快要过期的。一共8种。
  7. 谈一下Redis的持久化机制。
    Redis有RDB快照和AOF文件两种持久化方案。RDB快照是每隔一段时间进行一次快照,文件较小。AOF记录每个写操作到AOF文件,类似于mysql的binlog。
  8. 什么是缓存雪崩、缓存穿透、缓存击穿,解决方案是什么?
    – 缓存雪崩:同一时刻大量缓存失效,导致请求全部进入数据库,导致数据库大量负载而崩掉。正确设置数据过期时间,如随机过期时间,热点数据永不过期等。
    – 缓存穿透:服务器接收到无效请求,缓存和数据库都没有数据,导致请求不断进入数据库,从而引起数据库压力过大。可以做参数校验拦截,也可以在缓存中放入值为空的键值对。
    – 缓存击穿:如果一个热点数据过期,那么会有很多并发请求进入数据库,引起数据库压力瞬间增大。可以设置热点数据永不过期。
db服务器连接mysql+redis高可用高性能框架干货 1、使用c++语言,vs2019开发垮平台[windows和linux]连接MySqlredis框架。 2、使用MySql持久化玩家数据,redis做玩家数据缓存层,redis不做数据持久化。 mysql搭配redis工作效率非常高效,就好比男女搭配干活不累,没有redismysql也能独立 很好的完成用户读写请求。有了redis,用户访问数据的效率更高,时间更短,快速的完成请求。 3、讲解如何保持mysqlredis数据强一致性策略,并在代码里实现。每次启动redis,使用管道技术,从mysql 批量导入活跃用户数据到redis中,并设置过期时间. 4、教程使用线程池技术,每个线程拥有自己独立的数据,线程绑定类。每一个实例就包含一个线程 每个线程数据里包含:mysql连接器、redis连接器、内存回收池、安全的串行队列、条件变量、互斥量 保证线程内的数据安全。 5、工作原理: 没有请求时,各个工作线程处于休眠状态。 有读写请求时,从线程池获取一个线程,添加读写请求,把数据推送到线程工作队列中。 然后工作线程获取队列的数据,进行串行工作任务安排,进行mysql数据库读写操作,以及redis读写数据操作, 当完成工作任务时,执行下一个工作任务,同时把处理结果推送到逻辑线程,把数据给用户。 6、用户读数据策略:用户获取数据首先是先从redis查找数据,redis命中, 返回数据给玩家,redis命中失败,mysql中查找数据,然后写入数据到redis中,返回数据给用户。 7、用户写数据策略:用户先从redis中删除数据,然后写数据到mysql中,最后再把数据写入到redis中,保持数据一致性。 8、教程是一个干货教程,不是新手教程,mysql基础语法讲解的少,redis有讲解基础系列。 教程讲解的是如何搭建一个支持高并发,高性能的读写数据库框架,使用mysql+redis搭配的高可用、高性能框架。 该套框架在多个项目使用过,也在棋牌类项目里面使用过。
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页