数据库范式

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 自增主键一定是连续的吗?

自增值保存在哪?

  1. MyISAM 引擎的自增值保存在数据文件中

  2. InnoDB 引擎的自增值,其实是保存在了内存里,并没有持久化。第一次打开表的时候,都会去找自增值的最大值 max(id),然后将 max(id)+1 作为这个表当前的自增值。

实际上,到了 MySQL 8.0 版本后,自增值的变更记录被放在了 redo log 中,提供了自增值持久化的能力,也就是实现了“如果发生重启,表的自增值可以根据 redo log 恢复为 MySQL 重启前的值”

自增值不连续的四个场景

  1. 自增初始值和自增步长设置不为 1
  2. 唯一键冲突
  3. 事务回滚
  4. 批量插入(如 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(临键锁) :锁住一段左开右闭的区间

隐式锁定

  1. 对于常见的 DML 语句(如 UPDATEDELETEINSERT ),InnoDB 会自动给相应的记录行加写锁
  2. 默认情况下对于普通 SELECT 语句,InnoDB 不会加任何锁,但是在 Serializable 隔离级别下会加行级读锁

显式锁定

  1. SELECT * FROM table_name WHERE ... FOR UPDATE,加行级写锁
  2. 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独有写法