数据库基础知识
数据库:DataBase,信息的集合或者说是由数据库管理系统管理的数据的集合
数据库管理系统:操作和管理数据的软件
数据库系统:数据库 + 数据库管理系统 + 数据库管理员
数据库管理员:管理和控制数据库系统
元组:关系是一张表,表中的每行(即数据库中的每条记录)就是一个元组,每列就是一个属性。元组也称为行
码:码是能唯一标识实体的属性,对应表中的列
候选码:关系中的某一属性或属性组能唯一标识一个元组,而其任何、子集都不能再标识,则称属性组为候选码。例如:在学生实体中,“学号”是能唯一的区分学生实体的,同时又假设“姓名”、“班级”的属性组合足以区分学生实体,那么{学号}和{姓名,班级}都是候选码。
主码:主码也叫主键,主码是从候选码中选出来的。一个实体机中只有一个主码,但可以有多个候选码
外码:外键,如果一个关系中的一个属性是另外一个关系中的主码则这个属性为外码
主属性:候选码中出现过的属性称为主属性。比如关系 工人(工号,身份证号,姓名,性别,部门).显然工号和身份证号都能够唯一标示这个关系,所以都是候选码。工号、身份证号这两个属性就是主属性。如果主码是一个属性组,那么属性组中的属性都是主属性。
非主属性:不包含在任何一个候选码中的属性
主键:主码,用于唯一标识一个元组,不能有重复,不允许为空,一个表只能有一个主键。
外键:外码。用来和其他表建立联系,外键是另外一个表的主键,外键可以重复,可以是空值。一个表可以有多个外键
ER图
E-R图 也称 实体-联系图,提供了表示实体类型、属性和联系的方法
M:N 多对多 ; 1:1 1对1 ; 1:N 1对多
数据库范式
1NF(第一范式)
属性不能再分割,一个字段只能是一个值,不能再分为多个其他字段。1NF是所有关系型数据库的最基本要求
2NF(第二范式)
2NF在1NF基础上,消除了非主属性对于码的部分函数依赖。第二范式在第一范式的基础上增加了一个列,称为主键,非主属性都依赖于主键。
3NF(第三范式)
3NF 在 2NF 的基础之上,消除了非主属性对于码的传递函数依赖 。符合 3NF 要求的数据库设计,基本上解决了数据冗余过大,插入异常,修改异常,删除异常的问题。比如在关系 R(学号 ,姓名, 系名,系主任)中,学号 → 系名,系名 → 系主任,所以存在非主属性系主任对于学号的传递函数依赖,所以该表的设计,不符合 3NF 的要求。
- 1NF:属性不可再分
- 2NF:1NF基础上,消除非主属性对码的部分函数依赖
- 3NF:3NF在2NF基础上,消除非主属性对码的传递函数依赖
存储过程
阿里巴巴Java开发手册禁止使用存储过程,存储过程难以调式和扩展,没有移植性
存储过程看成是一些 SQL 语句的集合,中间加了点逻辑控制语句。存储过程在业务比较复杂的时候是非常实用的,比如很多时候我们完成一个操作可能需要写一大串 SQL 语句,这时候我们就可以写有一个存储过程,这样也方便了我们下一次的调用。存储过程一旦调试完成通过后就能稳定运行,另外,使用存储过程比单纯 SQL 语句执行要快,因为存储过程是预编译过的。
drop、delete、truncate区别
- drop(丢弃数据):
drop table 表名
,直接将表删除,在删除表时使用 - truncate(清空数据):
truncate table 表名
,只删除表中的数据,再插入数据的时候自增长id从1开始,在清空表中数据时使用 - delete(删除数据):
delete from 表名 where 列名 = 值
,删除某一列数据,如果不加where子句,就和truncate作用类似
truncate 和不带 where 子句的 delete、以及 drop 都会删除表内的数据,但是 truncate 和 delete 只删除数据不删除表的结构(定义),执行 drop 语句,此表的结构也会删除,也就是执行 drop 之后对应的表不复存在。
truncate 和 drop 属于 DDL(数据定义语言)语句,操作立即生效,原数据不放到 rollback segment 中,不能回滚,操作不触发 trigger。
delete 语句是 DML (数据库操作语言)语句,这个操作会放到 rollback segement 中,事务提交之后才生效。
DML 是数据库操作语言(Data Manipulation Language)的缩写,是指对数据库中表记录的操作,主要包括表记录的插入(insert)、更新(update)、删除(delete)和查询(select),是开发人员日常使用最频繁的操作。
是数据定义语言的缩写,简单来说,就是对数据库内部的对象进行创建、删除、修改的操作语言。它和 DML 语言的最大区别是 DML 只是对表内部数据的操作,而不涉及到表的定义、结构的修改,更不会涉及到其他对象。DDL 语句更多的被数据库管理员(DBA)所使用,一般的开发人员很少使用
执行速度:drop>truncate>delete
数据库设计
- 需求分析 : 分析用户的需求,包括数据、功能和性能需求。
- 概念结构设计 : 主要采用 E-R 模型进行设计,包括画 E-R 图。
- 逻辑结构设计 : 通过将 E-R 图转换成表,实现从 E-R 模型到关系模型的转换。
- 物理结构设计 : 主要是为所设计的数据库选择合适的存储结构和存取路径。
- 数据库实施 : 包括编程、测试和试运行
- 数据库的运行和维护 : 系统的运行与数据库的日常维护。
关系型数据库
建立在关系模型的基础上的数据库,(一对一、一对多、多对多)
存储引擎
MySQL默认存储引擎是InnoDB,因为InnoDB支持事务,为事务性存储引擎
MyISAM:只有表级锁,锁表;不提供事务支持;不支持外键,不支持数据库异常崩溃后安全恢复,不支持MVCC
InnoDB:行级锁,锁行记录,提供事务,支持外键,支持崩溃后安全恢复,支持MVCC:行级锁的一个升级,有效减少加锁操作,提供性能
- Mysql InnoDB:使用redo log(重做日志)保证事务的持久性,undo log保证事务的原子性
- 通过锁机制、MVCC等手段保证事务的隔离性
- 保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障
锁机制与InnoDB锁算法
- MyISAM:使用表级锁
- InnoDB:使用行级锁和表级锁。默认行级锁
InnoDB存储引擎的锁的算法有三种:
- Record Lock:记录锁,单个行记录上的锁
- Gap Lock:间隙锁,锁定一个范围,不包括记录本身
- Next key Lock:临建锁,锁定一个范围,包含记录本身
查询缓存
不实用 (略)
事务
事务是逻辑上的一组操作,要么都执行,要么都不执行;要么全部执行成功,要么全部不执行
# 开启事务
start transaction;
# sql
sql1,sql2,...
# 提交事务
commit;
ACID特性
关系型数据库事务都有ACID特性
- A:原子性,事务是最小的执行单位,不可分割,事务的原子性确保动作要么全部完成,要么完全不起作用
- C:一致性,执行事务前后,数据保持一致。
- I:隔离性,并发访问数据库时,事务与事务之间互不干扰,相互独立
- D:持久性,一个事务被提交后,它对数据库中数据的改变是持久的。
并发事务带来的问题
- 脏读:一个事务访问数据并对数据修改,还没提交到数据库,另外一个事务也访问这个数据,并使用这个数据。这个数据就是脏数据。
- 丢失修改:一个事务读取数据时,另外一个事务也访问该数据,第一个事务修改数据,第二个事务也修改数据,这样第一个事务内的修改结果就被丢失,因此称为丢失修改
- 不可重复读:一个事务内多次读同一数据。在这个事务还没结束时,另外一个事务也访问该数据。在第一个事务两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。
- 幻读:幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次读取一条记录发现记录增多或减少了。
事务隔离级别
- 读取未提交:最低隔离级别,允许读取尚未提交的数据变更。可能导致脏读、不可重复读、幻读
- 读取已提交:允许读取并发事务已经提交的数据。可以阻止脏读,可能导致不可重复读、幻读
- 可重复读:对同一字段的多次读取结果是一致的,除非数据是被本身事务修改。可以阻止脏读、不可重复读,但幻读仍有可能
- 可串行化:最高隔离级别,完全服从ACID隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
MySQL默认隔离级别是:可重复读。MySQL InnoDB 的 REPEATABLE-READ(可重读)并不保证避免幻读,需要应用使用加锁读来保证。而这个加锁度使用到的机制就是 Next-Key Locks。
因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是 READ-COMMITTED(读取提交内容) ,但是你要知道的是 InnoDB 存储引擎默认使用 REPEATABLE-READ(可重读) 并不会有任何性能损失。
InnoDB 存储引擎在 分布式事务 的情况下一般会用到 SERIALIZABLE(可串行化) 隔离级别。
阿里巴巴Java开发手册数据库部分总结
模糊查询
页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。
说明:索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。
外键和级联
不得使用外键与级联,一切外键概念必须在应用层解决。
说明:以学生和成绩的关系为例,学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风 险;外键影响数据库的插入速度
为什么不要用外键?
- 增加复杂性:删或更新都必须考虑外键约束。
- 增加额外工作
- 外键还会因为需要请求对其他表内部加锁而容易出现死锁情况
- 对分库分表不友好:因为分库分表下外键是无法生效的
好处:
- 保证了数据库的一致性和完整性
- 级联操作方便,减轻代码量
@Transaction注解
【参考】@Transactional事务不要滥用。事务会影响数据库的QPS,另外使用事务的地方需要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等。
参考
- 本文链接:https://wentianhao.github.io/2021/09/01/MySQL/
- 版权声明:本博客所有文章除特别声明外,均默认采用 许可协议。
若没有本文 Issue,您可以使用 Comment 模版新建。