数据库范式
属性:列
记录:行
超键:超码、在关系中能唯一标识记录的属性集(身份证、学号),唯一集合但不是最小唯一,三点定位思路
小范围内所有人,没有重名的。
候选键:不含有多余属性的超键
主键:从候选键中任选一个,叫主键。根据场景定
生产中:用户信息的身份证不能当主键(政策)
主属性:某一个属性,属于候选键,它为主属性。除了主键外的候选键
外键:属性是其他表的主键
表设计,需要将频繁修改的字段拆出去
标杆;
#第一范式:
属性不可拆分、
业务场景。例如姓名是否要拆开。要有前瞻性的拆分
#第二范式:
非主属性必须完全依赖于候选键
完全依赖
数据冗余、导致数据不一致、修改东西多影响性能
#第三范式:
非主属性不依赖于其他非主属性、消除传递依赖
例如:年龄、是否成年
#三范式修正
每个属性都不依赖非主属性
例如排序依赖于其他属性,需要抽出去。不然会先insert再update
插入:
先插入学生表、再插入班级序号表(异步写)
#第四范式:
禁止主键 和 非主键 有一对多关系
抽离多的。学号:电话s
实际中,一般用 逗号、分隔符存储
#第五范式:
要求:每个依赖关系、都有 候选键 推出
不能被无损的分解成几个更小的候选键
权限设计。
人 角色 角色— 功能
A 管理员 管理员—修改学生、修改老师
#反范式:
关联查询、连表查询、关联表过多—io过多—查询过慢
查询速度:为了提高效率,加冗余,反范式
业务要求:生产中:订单表、存储商品名称(快照)。如果完全按照范式,改商品名称后,找不到了。
#数据库设计:
读、写
读优化:
第一方法:索引、提升查询效率的绝佳手段
把某个键做hash、放在索引文件中、放到内存-速度更快
哈希碰撞
改的多、查的少。不需要索引。
主键、外键、常用检索键。用索引
写优化:
性能和一致性
锁
读随便并发
防止写并发
写细分:
单条写-—锁定一条记录,其他改其他记录、可并发
表写—锁整个表、排序出号
乐观锁—当前的操作对象大概率不产生并发。
1、读取被操作对象,记录某个特征信息
2、拿着对象进行业务逻辑处理,得到新的对象
3、向数据库写回新的对象
4、校验特征信息
5、如果一致,写,如果不一致、退/重试
特征信息策略:
1版本号:增加一个属性,时间戳,自增ID、、、判断没有被修改过
2如果属性值比较丰富的话,可以被更新的属性,写之前校验,还是读时候的值。
已经上线了的表,没有锁,出现了写冲突;
最快解决办法:全部属性当特征、、改改代码不动库
读:所有字段做hash
执行业务逻辑
写的时候校验hash
乐观锁、只是读写策略,没有加锁
读写失败、重复读写机制、牺牲了操作放的性能
应用场景:读取但是极少修改的对象上面。
事务
悲观锁
操作方对被操作对象加锁后,等释放锁后,其他操作方才能加锁
S锁、共享锁、读锁。可以获取到锁
Mysql例子:select * from xxx lock in share mode (读锁)
X锁、排他锁、写锁。其他对象拿不到锁
Mysql例子:select * from xxx for update (写锁)
默认的select语句有锁吗?
平时不直接做写读锁,根据数据库事物的隔离级别进行操作。
隔离级别就是通过这些锁实现的。
行锁、where id=
页锁、锁定行相邻的记录
表锁、无法判断操作的行时、没有指定行
事务
ACID
原子性、WAL:write ahead log。 恢复系统、先写日志
一致性、外键、唯一索引、
隔离性、锁
持久性、逻辑、物理日志。 恢复系统
事务对并发性能的影响
如何让并发数更高
隔离越细、并发越高、系统开销更低
不隔离:脏写脏读、不可重复读(多次读 读到的结果不同)—行、幻读(已经清理了,有人查入了数据,还读到了内容)—表
实际工作—隔离级别:
直接加x锁、串行—性能急剧下降
为了性能、允许有一些并发问题、隔离性和并发性此消彼长。
查询隔离级别 show
设置隔离级别 set
Mysql 默认隔离级别》RR 可重复读
I 隔离性。锁
S锁,x锁,
表锁,开销小、加锁快、并发低—系统升级、数据迁移
行锁,开销大、加锁慢、并发高
读未提交—脏读。一级
读、查询时不加锁,
写、时 加s锁。事务结束释放
读已提交—不可重复读、幻读。二级
读、加s锁,读完后立即释放—读时改不了,避免了脏读、读完之后可能被其他事务写。
写、加x锁、事务结束释放
可重复读—三级、mysql默认级别
读、加s锁,事务完成释放
写、加x锁,事务完成释放
前面都是行锁、避免不了 幻读
串行化,四级、最高隔离级别
读,锁整个表、到事务结束
写,锁整个表、到事务结束
自建事务
发请求、发邮件、无法封装成事务。微服务之间的调用,分布式事务解决。
数据库量大后的优化
数据量增多,sql语句效率下降。索引文件增大、sql语句变长
优化顺序:加索引、表分区、分库分表、读写分离
数据库存储有对应文件、一个表一个文件。.idb。分区:一个表对应多个文件。
分区:
不影响业务、方不同磁盘、可以备份恢复逐步进行
数目有限、跨分区业务查询、数据合并操作开销
分库:
把库的数据(表)移动到其他库、库数据减少、提升不大。
分库分表:
把表拆到另外的库中
分表:
表拆2个表,检索性能高、行锁、表锁的范围变小、性能提高
水平拆分:一部分数据拆开。数据结构一样
垂直拆分:某些记录被拆开、包含部分属性
原则:避免跨表操作
经常获取用户的全部信息——水平
经常获取用户的部分信息、另外一部分极少——垂直
路由操作:
拼接操作:
读写分离:
保证读不受写约束
适用于读多写少
主库—负责写,其他从库负责读
还可用于数据备份
路由操作:
select---指到读库
add update delete create 分到写库上
主从复制:
确保主从数据的一致性
主库数据同步到从库中,避免:对从库的写操作(不然出现x锁)
实现方式:binlog
1、主库开启日志记录功能,写操作写入binlog
2、binlog 被发到从库中,写入从库的relaylog
3、从库解析relaylog,重现数据
日志记录方式:
statement :Binlog记录的操作语句。。如果涉及一些时间的函数,now() 数据就不一致了
Row:存储操作记录。
mixed 混合模式
主从复制的延迟问题:
日志记录传输解析—到从库。非实时
异步复制:降低写的时间,可能导致数据丢失
半同步复 制:
全同步复制