面试八股文
脱坑转码 必背 八股文
什么是关系型数据库
将复杂的数据结构组织成一个个二维的表格,对数据的操作都建立在一个或多个表格上,通过对这些表格进行分类,合并,连接等运算来实现数据库的管理。
MySQL支持哪些存储引擎
支持 InnoDB,MyISAM,Memory,Archive。 其中,InnoDB 是 MySQL 的默认存储引擎。
MyISAM 和 InnoDB 的区别有哪些:
InnoDB 支持事务,MyISAM 不支持
InnoDB 支持外键,而 MyISAM 不支持
InnoDB 是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高;MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针,主键索引和辅助索引是独立的。
Innodb 不支持全文索引,而 MyISAM 支持全文索引,查询效率上 MyISAM 要高;
InnoDB 不保存表的具体行数,MyISAM 用一个变量保存了整个表的行数。
MyISAM 采用表级锁(table-level locking);InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。
SQL 数据类型有哪些?
数字, 字符 ,时间, JSON
数字
类型
大小
说明
TINYINT
1字节
整型
SAMLLINT
2字节
整型
MEDIUMINT
3字节
整型
INT
4字节
整型
BIGINT
8字节
整型
FLOAT
4字节
单精度浮点
DOUBLE
8字节
双精度浮点
DECIMAL
\
DECIMAL(X,Y) 总位数X, 小数Y位
字符
类型
大小
说明
CHAR(X)
1-255字符
X长度的字符
VARCHAR(X)
1-65535字符
最长为X长度的字符
TEXT
1-65535字符
不确定长度的字符串
MEDIUMTEXT
1-1千6百万字符
不确定长度的字符串
LONGTEXT
1-42亿字符
不确定长度的字符串
固定长度用 CHAR, 有限长度用 VARCHAR, 尽量不用 TEXT
日期
类型
大小
说明
DATE
3字节
日期
TIME
3字节
时间
YEAR
1字节
年份
DATETIME
8字节
日期时间
TIMESTAMP
4字节
时间戳
数据库设计3范式
确保表中每一列保持原子性, 不同列之间没有关系
确保表中的每列都只和主键相关,也就是一张表只记录一件事
确保表中的每一列都只和其中的主键有直接的关系,如果存在间接关系应该拆分成两张表
MySQL建表的约束条件有哪些?
主键约束(Primay Key Coustraint) 唯一性,非空性
唯一约束 (Unique Counstraint)唯一性,可以空,但只能有一个
外键约束 (Foreign Key Counstraint) 需要建立两表间的关系并且外键必须为另一个表的主键
检查约束 (Check Counstraint) 对该列数据的范围、格式的限制
默认约束 (Default Counstraint) 该数据的默认值
什么是 MySQL 事务机制 ?
用一句话说,事务机制就是 要么不做,要么做完的机制,MySQL 就支持这种机制
MySQL的事务机制运行如下图所示:
SQL 语句并不是直接对数据库进行操作, 而是将数据库里的数据先复制到 undo 日志当中, 在undo日志里面进行修改。随后若确定保存更改,则将undo日志里面的修改记录提交到redo日志当中,交由redo日志对数据库进行数据操作。若不确定不修改数据,则undo日志将原来的数据返回到数据库当中。
为什么要事务机制?
假设这么一个场景, 有多条SQL语句需要执行,执行到一半的时候,机房停电。随后恢复供电,问题来了?我们此时并不知道执行到了第几条SQL语句, 不知道数据库里面哪些数据被修改了,这是非常严重的后果。
事务机制就能规避这种风险,我们先把需要修改的记录保存到redo日志中,交由redo日志去处理,假设在提交过程停电也没有关系,因为所有的修改记录已经在redo日志中了,redo日志重新对数据进行同步即可。
事务机制的四个特性
原子性,要么做完,要么不做
一致性,不管有多么的高并发,执行结果一定正确
隔离性,事务不受其他事务的影响
持久性,事务一旦提交,结果就不可改变,即使遇到死机,停电,也可以通过日志完成对数据的修改
隔离
隔离性:可以防止多个事务并发同时操作数据产生冲突
脏读,不可重复读,幻读
脏读:事务A 读取了 事务B 更新未提交的数据
不可重复读:事务A 多次读取数据, 事务B 更新提交数据,事务A多次读取不一致
幻读: 事务A要 更改一份数据并且已经匹配成功,但在造作过程中,事务B新增了一条数据进来。事务A更改结束以后发现还存在未被更改的数据, 就像发生幻觉一样。
四种隔离级别
READ UNCOMMITED, 未提交读。一个事务 可以读取 另一个事务更改了但未提交的数据
READ COMMITED, 提交读。 一个事务只可以读取其他事务提交了以后的数据
REPEATABLE READ, 可重复读。 在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据都是一致的
SERIALIZABLE, 串行化。所有事物排队,一个个来读写操作。
什么是索引?
索引是帮助高效获取数据的数据结构。是对数据表中的一列或者多列的值进行排序的数据结构。对于索引,会保存在额外的文件中。
索引优点:
可以大大加快数据的检索速度
索引缺点:
时间方面:创建索引和维护索引要耗费时间,具体地,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,会降低增/改/删的执行效率;
空间方面:索引需要占物理空间
索引 种类有哪些?
从存储结构上来划分:BTree索引(MySQL 默认B+Tree索引),Hash索引
从应用层次来分:普通索引(一个索引包含单列的值),复合索引(多列值组成一个索引), 唯一索引(索引列的值必须唯一, 允许位NULL)
为什么 MySQL 的索引要使用 B+树而不是其它树形结构?比如 B 树?AVL? 红黑树?
B树: 叶子节点,非叶子节点上都保存数据,不利于范围查询
B+树: 只有叶子节点保存数据, 叶子节点使用双向链表连接,适合范围查询。
AVL, 红黑树更是如此,是二叉树,树的高度会更高. 即使是平衡二叉树, 也需要 log(N)次操作,而B 类树只需要logm(N)次操作,而且m很大,最终B类树的深度会低很多. 而且二叉树只适合做精确查询,不适合做范围查询。
而在外存中IO操作的时间代价是远远高于内存的, 硬盘分为一个个扇区, 读一次需要整个扇区都读出了.而B 类树通过降低树的高度, 能够大幅度降低访问时间
聚簇索引和非聚簇索引
聚簇索引:
将数据存储与索引放在以前,找到索引就找到了数据,默认情况下聚簇索引是主键。InnoDb 使用的是聚簇索引,将主键组织到一棵B+树中,而行数据存储道叶子节点中。其最终目的就是减少逻辑IO,提高查询速度。
不建议使用厂字符串(UUID) 作为主键索引,系数数据的列不适合建立聚簇索引,因为会占据大量空间,检索速度变慢。稀疏数据的列不适合建立聚簇索引,频繁更新的列不适合建立索引。
非聚簇索引:
将数据存储与索引分开存储,索引指向数据内存空间,也被称作 二级索引。MyISAM使用的是非聚簇索引
聚簇索引和非聚簇索引的B+树结构并没有太大区别,节点一致,只是存储的内容不一致。
联合索引(也叫 复合索引)
联合索引也就是由多个字段组成的一个索引。比如下面的 idx_y_z 就是由 f_y 和 f_z 两个字段组成的索引
如果数据表有100行,那么两个字段的联合索引的叶子节点就有 100*100 个节点, 每一个节点都有两个子树。 可以看出联合索引的叶子节点与字段的个数成指数关系。
联合索引适用于需要大量使用 WHERE 字句对多个字段进行比较操作 ,且数据规模有限的场景。
联合索引的作用时机
联合索引使用遵循最左匹配原则
联合索引的查找顺序与where条件顺序无关, 而与字段有关
MySQL 日志
undo 日志
作为待修改数据的备份,如果舍弃修改,需要数据回滚,则从 undo 日志中进行回滚
redo 日志
任何提交修改过后的数据会被记录在 redo 日志中,即使发生宕机,停电等中断数据更新的事件,等服务器恢复正常以后,依旧可以从redo 日志中提取待更新的数据,对原数据库进行更改
binlog 日志
记录数据库表结构(CREATE, ALTER TABLE) 以及 表数据修改(INSERT, UPDATE, DELETE)的二进制日志
锁
乐观锁和悲观锁
乐观锁:对于数据冲突保持一种乐观态度,操作数据时不会对操作的数据进行加锁,只有到数据提交的时候才通过一种机制来验证数据是否存在冲突。
悲观锁:对于数据冲突保持一种悲观态度,在修改数据之前把数据锁住,然后再对数据进行读写,在它释放锁之前任何人都不能对其数据进行操作,直到前面一个人把锁释放后下一个人数据加锁才可对数据进行加锁,然后才可以对数据进行操作,一般数据库本身锁的机制都是基于悲观锁的机制实现的。
共享锁和排他锁
共享锁也称为读锁,相互不阻塞,多个客户在同一时刻可以同时读取同一个资源而不相互干扰。排他锁也称为写锁,会阻塞其他的写锁和读锁,确保在给定时间内只有一个用户能执行写入并防止其他用户读取正在写入的同一资源。
按照锁的粒度分数据库锁有哪些?
行级锁
行级锁是MySQL中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁 和 排他锁。
开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
表级锁
表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。
开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。
页级锁
页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。BDB支持页级锁
开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
Last updated