1. 数据库基础

1.1. 什么是事务

事务的英文为 Transaction,什么是事务?

  1. 事务的数据库并发控制的基本单位
  2. 事务可以看作是一系列SQL语句的结合
  3. 事务必须要么全部执行成功,要么全部执行失败

例如: 银行转账

银行转账(A给B转账)包含两步操作 : A-50 B+50

1.2. 事务的特性

事务具有四个特性(ACID):

  1. 原子性(Atomicity): 一个事务中所有操作全部完成或全部失败
  2. 一致性(Consistency): 事务开始和结束之后数据完整性没有被破坏
  3. 隔离线(Isolation): 允许多个事务同时对数据库修改和读写
  4. 持久性(Durability): 事务结束后,修改永不丢失

1.3. 事务的并发控制

1.3.1. 如何没有并发控制造成的问题

  1. 幻读(phantom read): 一个事务第二次查出现第一次没有的结果
  2. 非重复读(nonrepeatable read): 一个事务重复读两次得到不同的结果
  3. 脏读 (dirty read): 一个事务读取到另一个事务没有提交的修改
  4. 丢失修改 (lost update): 并发写入导致一部分修改丢失

1.3.2. 为了解决并发控制异常,四种事务的隔离级别

  1. 读未提交(read uncommitted): 别的事务可以读取到未提及的修改
  2. 读已提交 (read committed): 只能读取到已经提交的数据
  3. 可重复读 (repeatable read): 同一个事务先后查询结果一样
  4. 串行化 (Serializable): 事务完全串行化的执行,隔离级别最高,执行效率最低。
隔离级别 脏读 不可重复读 幻读
读未提交 可能 可能 可能
读已提交 不可能 可能 可能
可重复读 不可能 不可能 可能
可串行化 不可能 不可能 不可能

[warning] 特别注意:数据库常用的隔离级别是 读已提交实际上即便选择 读未提交,也会被强制为读已提交

1.4. 如何解决数据库的高并发

  1. 使用数据的唯一索引 (没有分表分库的情况下)
  2. 使用队列异步写入
  3. 使用redis等实现分布式锁

说的简单些,redis来实现分布式锁的原理就是将程序中一个唯一的key写入redis中,当有其他分布式应用要访问时候此key时,就去redis中读取,读取到了则说明此数据正在被处理,读取不到则说明可以进行处理;

在redis实现的分布式锁中,我们需要强调以下几点,只有保证了以下几点,才可说是确保了锁的实现: 互斥,在任何时刻,对于同一条数据,只有一台应用可以获取到分布式锁; 不能发生死锁,一台服务器挂了,程序没有执行完,但是redis中的锁却永久存在了,那么已加锁未执行完的数据,就永远得不到处理了,直到人工发现,或者监控发现; 高可用性,可以保证程序的正常加锁,正常解锁; 加锁解锁必须由同一台服务器进行,不能出现你加的锁,别人给你解锁了。

1.5. 悲观锁和乐观锁

悲观锁: 悲观锁是先获取锁再进行操作。一锁二查三更新。(慢)

乐观锁:乐观锁先修改,更新的时候发现数据已经变了就回滚 (理想状态下快)

1.6. 索引

1.6.1. 什么是索引

索引是数据表中一个或者多个列进行排序的数据结构, 数据库采用B+树作为索引的存储结构

1.6.2. 什么时候创建索引

  1. 经常用作查询条件的字段(where条件)
  2. 经常用作表连接的字段
  3. 经常出现在order by(排序), group by(分组)之后的字段

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

  1. 非空字段NOT NULL 对空值很难作查询优化
  2. 区分度高, 离散度大, 作为索引的字段值尽量不要有大量相同值
  3. 索引的长度不要太长

1.6.4. 索引失效

记忆口诀:

  1. 模糊匹配

    模糊匹配: 以 %开头的like语句, 模糊搜索

  2. 类型隐转

    类型隐转:出现隐式类型转化

  3. 最左匹配

    最左匹配:主要在多列索引(联合索引)中发生,例如:

    • [(a, b,c), (a,b), (a)] 可以索引来加快
    • [(a, b,c), (b, c)] 不能索引来加快

    联合索引时会遵循最左前缀匹配的原则,即最左优先,在检索数据时从联合索引的最左边开始匹配。

1.6.5. 聚集索引和非聚集索引

聚集索引还是非聚集指的是B+Tree 叶子节点存的是指针还是数据记录。

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

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

1.6.6. 如何排查慢查询

原因:

  1. 缺少索引
  2. 索引不合理
  3. 业务代码实现有问题

解决方法: slow_query_log_file 开启并且查询慢查询日志;通过 explain 排查索引问题;调整数据修改索引;业务代理不合理(一次获取过多数据)

1.7. 常用的SQL连接

  1. 内连接(inner join):两个表都存在匹配时,才会返回匹配行
  2. 外连接(left/right join ): 返回一个表的行,即使另一个没有匹配
  3. 全连接(full join): 只要某一个表存在匹配就返回

内连接select * from classroom as A inner join student as B on A.id = B.room_id;

外连接 select * from classroom as A right join student as B on B.name = '小粉';

全连接 select * from classroom as A full join student as B on B.room_id = A.id; 返回两个表的全部的数据,优先列出两个表都匹配的内容

1.8. 数据库设计三大范式

  1. 第一范式要求确保表中每列的原子性,也就是不可拆分;
  2. 第二范式要求确保表中每列与主键相关,而不能只与主键的某部分相关(主要针对联合主键),主键列与非主键列遵循完全函数依赖关系,也就是完全依赖;
  3. 第三范式确保主键列之间没有传递函数依赖关系,也就是消除传递依赖。

results matching ""

    No results matching ""

    results matching ""

      No results matching ""