• 第8章 数据库考察点


    Mysql基础常考题

    • 事务的原理,特性,事务并发控制

    • 常用的字段, 含义和区别

    • 常用的数据库引擎之间区别

    什么是事务?

    Transaction:

    • 事务是数据库并发控制的基本单位

    • 事务可以看作是一系列SQL语句的集合

    • 事务必须要么全部执行成功,要么全部执行失败(回滚)

    • 转账操作是事务使用的一个常见场景

    #Transaction 示例
        session.begin()
        try:
            item1 = session.query(Item).get(1)
            item2 = session.query(Item).get(2)
            item1.foo = 'bar'
            item2.bar = 'foo'
            session.commit()
        except:
            session.rollback()
            raise
    

    事务的ACID特性

    ACID是事务的四个基本特性

    • 原子性(Atomicity): 一个事务中所有操作全部完成或失败

    • 一致性(Consistency): 事务开始和结束之后数据完整性没有被破坏

    • 隔离性(Isolation): 允许多个事务同时对数据库修改和读写

    • 持久性(Durability): 事务结束之后,修改是永久的不会丢失

    事务的并发控制可能产生哪些问题

    如果不对事务进行并发控制,可能会产生四种异常情况

    • 幻读(phantom read): 一个事务第二次查出现第一次没有出现的结果

    • 非重复读(nonrepeatable read): 一个事务重复读两次得到不同的结果

    • 脏读(dirty read): 一个事务读取到另一个事务没有提交的修改

    • 丢失修改(lost update): 并发写入造成其中一些修改丢失

    四种事务隔离级别

    为了解决并发控制异常,定义了4种事务隔离级别

    • 读未提交(read uncommitted) 别的事务可以读取到未提交改变

    • 读已提交(read committed): 只能读取已经提交的数据

    • 可重复读(repeatable read): 同一个事务先后查询结果一样

    ​ Mysql InnoDB 默认实现可重复读级别

    • 串行化(Serializable): 事务完全串行化的执行,隔离级别最高,执行效率最低

    如何解决高并发场景下的插入重复

    高并发场景下, 写入数据库会有数据重复问题

    • 使用数据库的唯一索引

    • 使用队列异步写入

    • 使用redis等实现分布式锁

    乐观锁和悲观锁

    什么是乐观锁,什么是悲观锁

    • 悲观锁是先获取锁再进行操作,一锁二查三更新 select for update

    • 乐观锁先修改,更新的时候发现数据已经变了就回滚(check and set)

    • 乐观锁一般通过版本号或者时间戳实现

    • 需要根据响应速度,冲突频率,重试代价来判断使用那一种

    Mysql常用数据类型-字符串(文本)

    CHAR(Length) length bytes A fixed-length field from 0 to 255 characters long
    VARCHAR(Length) **String length + 1 or 2 bytes ** A variable-length field from 0 to 65535 characters long
    tinytext String length + 1 bytes A string with a maximum length of 255 characters
    TEXT String length + 2 bytes A string with a maximum length of 65535 characters

    Mysql常用数据类型-数值

    TINYINT(Length) 1 byte Range of -128 to 127 or 0 to 255 unsigned
    SMALLINT(Length) 2 bytes Range of -32768 to 32767 or 0 to 65535 unsiged
    MEDIUMINT(Length) 3 bytes Range of -8388608 to 8388607 or 0 to 16777215 unsigned
    INT(Length) 4 bytes Range of -2147483648 to 2147483647 or 0 to 4294967295
    BIGINT(Length) 8 bytes Range of -9223372036854775808 to 9223372036854775807 or 0 to 18446744073709551615 unsigned
    FLOAT(Length, Decimals) 4 bytes A small number with a floating decimal point
    DOUBLE(Length, Decimals) 8 bytes A large number with a floating decimal point

    Mysql常用数据类型-日期和时间

    DATE 3 bytes ln the format of YYYY-MM-DD
    DATETIME 8 bytes ln the format of YYYY-MM-DD HH:MM:SS
    TIMESTAMP 4 bytes In the format of YYYYMMDDHHMMSS; acceptable range starts in 1970 and ends in the year 2018

    InnoDB vs MyISAM

    两种引擎常见的区别

    • InnoDB支持事务

    • InnoDB支持外键

    • InnoDB支持行锁和表锁 MyISAM只支持表锁

    Mysql索引原理及优化常见考题

    Mysql索引

    • 索引的原理,类型,结构

    • 创建索引的注意事项,使用原则

    • 如何排查和消除慢查询

    什么是索引?

    为什么需要索引?

    • 索引是数据表中一个或者多个列进行排序的数据结构

    • 索引能够大幅提升检索速度

    • 创建,更新索引本身也会耗费空间和时间

    什么是B-Tree?

    查找结构进化史

    • 1> 线性查找: 实现简单,太慢

    • 2> 二分查找: 有序,简单,要求是有序的,插入特别慢

    • 3> HASH: 查询快,占用空间,不太适合存储大规模数据

    • 4> 二叉查找树: 插入和查询快(log(n)), 无法存大规模数据,复杂度退化

    • 5> 平衡树: 解决bst退化的问题,树是平衡的,节点非常多的时候,依然树高很高

    • 6> 多路查找树: 一个父亲多个孩子节点(度) 节点过多 树高不会特别深

    • 7> 多路平衡查找树: B-Tree

    什么是B-Tree,为什么要使用B-Tree

    • 多路平衡查找树(每个节点最多m(m >= 2))个孩子,称为m阶或者度)

    • 叶节点具有相同的深度

    • 节点中的数据key从左到右是递增的

    B+Tree
    B+树是B-Tree的变形

    • Mysql实际使用的B+Tree作为索引的数据结构

    • 只在叶子节点带有指向记录的指针(为什么? 可以增加树的度)

    • 叶子节点通过指针相连,为什么?实现范围查询

    是不是树的度越多越好?

    Mysql索引的B+Tree类型

    Mysql创建索引类型

    • 普通索引(CREATE INDEX)

    • 唯一索引,索引列的值必须唯一(CREATE UNIQUE INDEX)

    • 多列索引

    • 主键索引(PRIMARY KEY) 一个表只能有一个

    • 全文索引(FULLTEXT INDEX), InnoDB不支持

    什么时候创建索引?

    建表的时候需要根据查询需求来创建索引

    • 经常用作查询条件的字段(WHERE条件)

    • 经常用作表连接的字段

    • 经常出现在order by, group by之后的字段

    创建索引有哪些需要注意的?

    最佳实践

    • 非空字段 NOT NULL, Mysql很难对空值作查询优化

    • 建表规范要求索引字段有默认值

    • 区分度高, 离散度大,作为索引的字段尽量不要有大量相同值

    • 索引的长度不要太长(比较耗费时间)

    索引什么时候失效?

    记忆口诀:模糊匹配,类型隐转,最左匹配

    • 以 % 开头的LIKE语句,模糊搜索

    • 出现隐式类型转换(在py这种动态语言查询中需要注意)

    • 没有满足最左前缀原则(为什么是左配)

    什么是聚集索引和非聚集索引?

    聚集索引和辅助索引

    聚焦索引

    非聚集和聚集索引的文件存储方式

    • 聚集还是非聚集指的是B+Tree叶节点存的是指针还是数据记录

    • MyISAM索引和数据分离,使用的是非聚集索引

    • InnoDB数据文件就是索引文件, 主键索引就是聚集索引

    • 辅助索引先找到主键以后再根据主键找到数据

    如何排查慢查询

    通常缺少索引,索引不合理或者业务代码实现导致

    • slow_query_log_file 开启并且查询慢查询日志

    • 通过explain排查索引问题

    • 调整数据修改索引,业务代码层限制不合理访问

    总结

    • 索引的原理

    • B + Tree的结构

    • 不同索引的区别

    SQL语句编写常考题

    考点聚焦

    SQL语句以考察各种常用连接为重点

    • 内连接(INNER JOIN): 两个表都存在匹配时,才会返回匹配行

    • 外连接(LEFT/RIGHT JOIN): 返回一个表的行,即使另一个没有匹配

    • 全连接(FULL JOIN): 只要某一表存在匹配就返回

    内连接

    INNER JOIN

    • 将左表和右表能够关联起来的数据连接后返回

    • 类似于求两个表的"交集"

      • select * from A inner join B on a.id = b.id

    示例表

    id value
    1 ab
    2 a
    id value
    1 ab
    3 b

    外连接

    外连接包含左连接和右连接

    • 左连接返回左表中所有记录,即使右表中没有匹配的记录

    • 右连接返回右表中所有记录,即使左表中没有匹配的记录

    • 没有匹配的字段会设置成NULL

    缓存及Redis常考面试题

    缓存的使用场景,Redis的使用,缓存使用的坑

    为什么使用缓存?使用场景?

    Redis的常用数据类型, 使用方式

    缓存使用问题,数据一致性问题,缓存穿透,击穿,雪崩问题

    主要讨论内存缓存(Redis/Memchached)

    • 解关系数据库(常见的是Mysql)并发访问的压力,热点数据

    • 减少响应时间:内存IO速度比磁盘快

    • 提升吞吐量:Redis等内存数据库单机就可以支撑很大并发

    操作时间对比

    操作 响应时间
    打开一个网站 几秒
    在数据库中查询一条记录(有索引) 十几毫秒
    机械磁盘一次寻址定位 4毫秒
    从机械磁盘顺序读取1MB数据 2毫秒
    从SSD磁盘顺序读取1MB数据 0.3毫秒
    从远程分布式缓存Redis读取一个数据 0.5毫秒
    从内存中读取1MB数据 十几微秒
    Java程序本地方法调用 几微秒
    网络传输2KB数据 1微秒

    Redis/Memcached主要区别?

    对比参数 Redis Memcached
    类型 1.支持内存 2.非关系型数据库 1.支持内存 2.key-value键值对形式 3.缓存系统
    数据存储类型 1.String 2.List 3. Set 4.Hash 5.Sort Set(ZSet) 1.文本型 2. 二进制类型[新版增加]
    查询[操作]类型 1.批量操作 2. 事务支持[假的事务] 3.每个类型不同的CRUD 1.CRUD 2.少量的其它命令
    附加功能 1. 发布/订阅模式 2. 主从分区 3. 序列化支持 4.脚本支持[Lua脚本] 1. 多线程服务支持
    网路IO模型 1. 单进程模式 1. 多线程,非阻塞IO模式
    事件库 自封装简易事件库AeEvent 贵族血统的LibEvent事件库
    持久化支持 1. RDB 2. AOF 不支持

    Mysql + Redis就能抗很多业务

    请简述Redis常用数据类型和使用场景?

    考察对Redis使用的掌握程度

    • String(字符串):用来实现简单的KV键值对存储,eg:计数器

    • List(链表): 实现双向链表,eg:用户的关注,粉丝列表

    • Hash(哈希表): 用来存储彼此相关的信息的键值对

      • HSET key field value
    • Set(集合): 存储不重复元素,比如用户的关注者

    • Sorted Set(有序集合): 实时信息排行榜

    延伸考点:Redis内置实现

    需要了解Redis各种类型的C底层实现方式

    • String: 整数或者sds(Simple Dynamic String)

    • List: ziplist or double linked list

    • ziplist: 通过一个连续的内存块实现list结构,

      ​ 其中的每个entry节点头部保存前后节点长度信息,实现双向链表功能

    • Hash: ziplist or hashtable

    • set: inset or hashtable

    • SortedSet: skiplist 跳跃表

    reference book

    ​ Redis 设计与实现

    这些数据结构操作的时间和空间复杂度?

    Redis实现的跳跃表示什么结构?

    • Sorted Set为了简化实现,使用skiplist而不是平衡树实现?

    Redis有哪些持久化方式?

    Redis支持两种方式实现持久化

    • 快照方式:把数据快照放在磁盘二进制文件中,dump.rdb

      ​ 快照的实现方式是指定时间间隔把Redis数据库状态保存到一个压缩的二进制文件中

      • AOF(Append Only File): 每一个写命令追加到appendonly.aof中 可以通过修改redis配置实现

    什么是Redis事务?

    和mysql的事务有什么不同?

    • 将多个请求打包,一次性,按序执行多个命令的机制

    • Redis通过MULTI, EXEC, WATCH等命令实现事务功能

    • Python redis-py pipeline=conn.pipeline(transaction=True)

    Redis如何实现分布式锁?

    • 使用setnx实现加锁,可以同时通过expire添加超时时间

    • 锁的value值可以使用一个随机的uuid或者特定的命名

    • 释放锁的时候,通过uuid判断是否是该锁,是则执行delete释放锁

    使用缓存的模式?

    • Cache Aside:同时更新缓存和数据库

    • Read/Write Through: 先更新缓存,缓存负责同步更新数据库

    • Write Behind Caching:先更新缓存,缓存定期异步更新数据库一致性问题

    如何解决缓存穿透问题?

    ​ 大量查询不到的数据的请求落到后端数据库,数据库压力增大

    ​ 由于大量缓存查不到就去数据库取,数据库也没有要查的数据

    • 解决:对于没查到返回为None的数据也缓存, 插入数据的时候删除相应缓存,或者设置较短的超时时间

    如何解决缓存击穿问题?

    ​ 某些非常热点的数据key过期,大量请求打到后端数据库

    ​ 热点数据key 失效导致大量请求打到数据库增加数据库压力

    • 分布式锁:获取锁的线程从数据库拉数据更新缓存,其它线程等待

    • 异步后台更新:后台任务对过期的key自动刷新

    如何解决缓存雪崩问题?

    缓存不可用或者大量缓存key同时失效,大量请求直接打到数据库

    • 多级缓存:不同级别的key设置不同的超时时间

    • 随机超时:key的超时时间随机设置,防止同时超时

    • 架构层: 提升系统可用性,监控,报警完善

    Mysql与Redis思考题?

    索引的理解

    为什么Mysql数据库的主键使用自增的整数比较好?

    使用uuid可以吗?为什么?

    如果是分布式系统下怎么生成数据库的自增id呢?

    Redis应用-分布式锁

    redis的应用之一:实现分布式锁

    思考题:

    ​ 请基于redis编写代码实现一个简单的分布式锁

    ​ 要求:支持超时时间参数

    ​ 扩展:如果redis单个节点宕机,如何处理?还有其它方案实现分布式锁?

  • 相关阅读:
    自定义Listview
    android ListView嵌套GridView显示不全问题
    Android-Universal-Image-Loader 图片异步加载类库的使用(超详细配置)
    android service被系统回收的解决方法
    android Activity基类通用方法
    用 FragmentManager 替换时使用 GoogleMaps 崩溃 app
    Gulp 从0开始
    面试题 之 全排列
    面试题之 query转为obj
    this .运算符 和 [] 运算符
  • 原文地址:https://www.cnblogs.com/xzpin/p/11619245.html
Copyright © 2020-2023  润新知