数据库范式
1NF(第一范式)
属性(对应于表中的字段)不能再被分割,也就是这个字段只能是一个值,不能再分为多个其他的字段了。1NF 是所有关系型数据库的最基本要求 ,也就是说关系型数据库中创建的表一定满足第一范式。
2NF(第二范式)
2NF 在 1NF 的基础之上,消除了非主属性对于码的部分函数依赖。如下图所示,展示了第一范式到第二范式的过渡。第二范式在第一范式的基础上增加了一个列,这个列称为主键,非主属性都依赖于主键。
3NF(第三范式)
3NF 在 2NF 的基础之上,消除了非主属性对于码的传递函数依赖 。符合 3NF 要求的数据库设计,基本上解决了数据冗余过大,插入异常,修改异常,删除异常的问题。比如在关系 R(学号 , 姓名, 系名,系主任)中,学号 → 系名,系名 → 系主任,所以存在非主属性系主任对于学号的传递函数依赖,所以该表的设计,不符合 3NF 的要求。
总结
- 1NF:属性不可再分。
- 2NF:1NF 的基础之上,消除了非主属性对于码的部分函数依赖。
- 3NF:3NF 在 2NF 的基础之上,消除了非主属性对于码的传递函数依赖 。
/* 建表规范 */ ------------------
-- Normal Format, NF
- 每个表保存一个实体信息
- 每个具有一个ID字段作为主键
- ID主键 + 原子表
-- 1NF, 第一范式
字段不能再分,就满足第一范式。
-- 2NF, 第二范式
满足第一范式的前提下,不能出现部分依赖。
消除复合主键就可以避免部分依赖。增加单列关键字。
-- 3NF, 第三范式
满足第二范式的前提下,不能出现传递依赖。
某个字段依赖于主键,而有其他字段依赖于该字段。这就是传递依赖。
将一个实体信息的数据放在一个表内实现。
drop、delete 与 truncate 区别
drop(丢弃数据): drop table 表名
,直接将表都删除掉,在删除表的时候使用。
truncate (清空数据) : truncate table 表名
,只删除表中的数据,再插入数据的时候自增长 id 又从 1 开始,在清空表中数据的时候使用。
delete(删除数据) : delete from 表名 where 列名=值
,删除某一列的数据,如果不加 where 子句和truncate table 表名
作用类似。
truncate 和不带 where 子句的 delete、以及 drop 都会删除表内的数据,但是 truncate 和 delete 只删除数据不删除表的结构(定义),执行 drop 语句,此表的结构也会删除,也就是执行 drop 之后对应的表不复存在。
MySQL 自增主键一定是连续的吗?
自增值保存在哪?
MyISAM 引擎的自增值保存在数据文件中
InnoDB 引擎的自增值,其实是保存在了内存里,并没有持久化。第一次打开表的时候,都会去找自增值的最大值
max(id)
,然后将max(id)+1
作为这个表当前的自增值。
实际上,到了 MySQL 8.0 版本后,自增值的变更记录被放在了 redo log 中,提供了自增值持久化的能力,也就是实现了“如果发生重启,表的自增值可以根据 redo log 恢复为 MySQL 重启前的值”
自增值不连续的四个场景:
- 自增初始值和自增步长设置不为 1
- 唯一键冲突
- 事务回滚
- 批量插入(如
insert...select
语句)
MyISAM 和 InnoDB 的区别
1.是否支持行级锁
MyISAM 只有表级锁(table-level locking),而 InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。
2.是否支持事务
MyISAM 不提供事务支持。
InnoDB 提供事务支持,具有提交(commit)和回滚(rollback)事务的能力。
3.是否支持外键
MyISAM 不支持,而 InnoDB 支持。
4.是否支持数据库异常崩溃后的安全恢复
MyISAM 不支持,而 InnoDB 支持。
🌈 拓展一下:
- MySQL InnoDB 引擎使用 redo log(重做日志) 保证事务的持久性,使用 undo log(回滚日志) 来保证事务的原子性。
- MySQL InnoDB 引擎通过 锁机制、MVCC 等手段来保证事务的隔离性( 默认支持的隔离级别是
REPEATABLE-READ
)。 - 保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障。
对于咱们日常开发的业务系统来说,你几乎找不到什么理由再使用 MyISAM 作为自己的 MySQL 数据库的存储引擎。
InnoDB 存储引擎中的行锁的加锁规则
- Record Lock(记录锁) :锁住某一行记录
- Gap Lock(间隙锁) :锁住一段左开右开的区间
- Next-key Lock(临键锁) :锁住一段左开右闭的区间
隐式锁定
- 对于常见的 DML 语句(如
UPDATE
、DELETE
和INSERT
),InnoDB 会自动给相应的记录行加写锁 - 默认情况下对于普通
SELECT
语句,InnoDB 不会加任何锁,但是在 Serializable 隔离级别下会加行级读锁
显式锁定
SELECT * FROM table_name WHERE ... FOR UPDATE
,加行级写锁SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
,加行级读锁
sql执行顺序
-- 行过滤
1 FROM <left_table>
2 ON <join_condition>
3 <join_type> JOIN <right_table> -- 第二步和第三步会循环执行
4 WHERE <where_condition> -- 第四步会循环执行,多个条件的执行顺序是从左往右的
5 GROUP BY <group_by_list>
6 HAVING <having_condition>
-- 列过滤
7 SELECT -- 分组之后才会执行SELECT
8 DISTINCT <select_list>
-- 排序
9 ORDER BY <order_by_condition>
-- MySQL附加
10 LIMIT <limit_number> -- 前9步都是SQL92标准语法.limit是MySQL独有写法