chengchengxu15 / CS-leaning

1 stars 1 forks source link

sql 面试准备 #75

Open chengchengxu15 opened 2 years ago

chengchengxu15 commented 2 years ago

ACID 以及实现的原理 primary key 和unique的区别,primary key为什么只有一个 索引的分类 数据库范式(normalization) 英语版:https://www.interviewbit.com/mysql-interview-questions/

chengchengxu15 commented 2 years ago

ACID 以及实现的原理

https://www.lixueduan.com/post/mysql/10-acid/

1 原子性(atomicity) 事务通常由多个语句组成,原子性保证每个事务都被视为一个单独的单元,要么完全成功,要么完全失败。即一个事务(transaction)中的所有操作,要么全部执行成功,要么全部不执行。

简单来说:原子性的结果就是没有中间状态,如果有中间状态则一致性就不会得到满足。

仔细想一想没有中间结果是不可能实现的,所以 MySQL 采用了曲线救国的方式:即执行失败后,可以回滚,保证不会出现部分成功的情况,通过 undolog 实现该特性。

事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

undo log 属于逻辑日志,它记录的是 sql 执行相关的信息。当发生回滚时,InnoDB 会根据 undo log 的内容做与之前相反的工作:对于每个 insert,回滚时会执行 delete;对于每个 delete,回滚时会执行insert;对于每个 update,回滚时会执行一个相反的 update,把数据改回去。

虽然从结果上看是保证原子性了,但是和真正的原子性还是有差距的,应为这样实现其实是有中间结果,在并发场景下其他事务可能会看到中间结果。

为了保证中间结果对外不可见,需要通过隔离性来保证并发场景下的正确性

通过隔离性保证其他事务不会看到本事务的执行结果; 当然 read uncommitted 级别则没有这个功能,所以一般不用该隔离级别。 MySQL 原子性实现原理

通过 undolog 在失败时回滚保证在结果上是原子性的, 即没有中间状态。

通过隔离性保证了在其他并发事务看来是原子性的,即中间状态对外不可见。

2 隔离性(isolation) 隔离性,指一个事务内部的操作及使用的数据对正在进行的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。

正是它保证了原子操作的过程中,中间状态对其它事务不可见。

隔离性有原子性的部分,但是更多的还是关注并发事务。

Mysql 隔离级别有以下四种(级别由低到高):

ReadUncommitted 读未提交 ReadCommitted 读已提交 RepeatableRead 可重复度 Serializable 串行化 隔离性追求的是并发情形下事务之间互不干扰。简单起见,我们主要考虑最简单的读操作和写操作(加锁读等特殊读操作会特殊说明),那么隔离性的探讨,主要可以分为两个方面:

(一个事务)写操作对(另一个事务)写操作的影响:锁机制保证隔离性 (一个事务)写操作对(另一个事务)读操作的影响:MVCC保证隔离性 锁机制

按照粒度,锁可以分为表锁、行锁以及其他位于二者之间的锁。

表锁在操作数据时会锁定整张表,并发性能较差; 行锁则只锁定需要操作的数据,并发性能好。 但是由于加锁本身需要消耗资源(获得锁、检查锁、释放锁等都需要消耗资源),因此在锁定数据较多情况下使用表锁可以节省大量资源。

3 持久性(durability) 持久性是指事务一旦提交,它对数据库的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

InnoDB 通过 redo log 重做日志保证了事务的持久性。

事务开始之后就产生 redo log,redo log 的落盘并不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入 redo log 文件中。

参数innodb_flush_log_at_trx_commit可设置在事务 commit 的时候必须要写入 redo log 文件。

redo log 具体原理:

当数据修改时,除了修改 Buffer Pool 中的数据,还会在 redo log 记录这次操作; 当事务提交时,会调用 fsync 接口对 redo log 进行刷盘。 redo log 采用的是 WAL(Write-ahead logging,预写式日志),所有修改先写入日志,再更新到 Buffer Pool 。 如果 MySQL 宕机,重启时可以读取 redo log 中的数据,对数据库进行恢复,保证了数据不会因 MySQL 宕机而丢失,从而满足了持久性要求。

4 一致性(consistency) 一致性是指事务执行结束后,数据库的完整性约束没有被破坏,事务执行的前后都是合法的数据状态。

数据库的完整性约束包括但不限于:实体完整性(如行的主键存在且唯一)、列完整性(如字段的类型、大小、长度要符合要求)、外键约束、用户自定义完整性(如转账前后,两个账户余额的和应该不变)。

可以说,一致性是事务追求的最终目标:前面提到的原子性、持久性和隔离性,都是为了保证数据库状态的一致性。此外,除了数据库层面的保障,一致性的实现也需要应用层面进行保障。

  1. 小结 下面总结一下ACID特性及其实现原理:

原子性:语句要么全执行,要么全不执行,即没有中间状态,是事务最核心的特性,事务本身就是以原子性来定义的;实现主要基于 undo log; 持久性:保证事务提交后不会因为宕机等原因导致数据丢失;实现主要基于 redo log; 隔离性:保证事务执行尽可能不受其他事务影响;InnoDB 默认的隔离级别是 RR,RR 的实现主要基于锁机制(包含 next-key lock)、MVCC(包括数据的隐藏列、基于 undo log 的版本链、ReadView); 一致性:事务追求的最终目标,一致性的实现既需要数据库层面的保障,也需要应用层面的保障。

chengchengxu15 commented 2 years ago

索引的分类

https://segmentfault.com/a/1190000037683781#:~:text=%E6%8C%89%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%88%86%E7%B1%BB%E5%8F%AF,%E5%A4%8D%E5%90%88%E7%B4%A2%E5%BC%95%E3%80%81%E7%BB%84%E5%90%88%E7%B4%A2%E5%BC%95%EF%BC%89%E3%80%82

〇、MySQL索引都有哪些分类? 按数据结构分类可分为:B+tree索引、Hash索引、Full-text索引。 按物理存储分类可分为:聚簇索引、二级索引(辅助索引)。 按字段特性分类可分为:主键索引、普通索引、前缀索引。 按字段个数分类可分为:单列索引、联合索引(复合索引、组合索引)。

chengchengxu15 commented 2 years ago

聚合索引(clustered index) https://zhuanlan.zhihu.com/p/135951750 InnoDB表要求必须有聚簇索引,默认在主键字段上建立聚簇索引,在没有主键字段的情况下,表的第一个非空的唯一索引将被建立为聚簇索引,在前两者都没有的情况下,InnoDB将自动生成一个隐式的自增id列,并在此列上建立聚簇索引。 https://acecodeinterview.com/mysql_keys_and_indexes/

chengchengxu15 commented 2 years ago

数据库范式(normalization)

https://blog.csdn.net/dreamrealised/article/details/10474391 https://www.zhihu.com/question/24696366