本篇主要是简略记录数据库相关的知识。
定义
存储数据、管理数据的仓库,简称数据库。
分类
可以分为关系型数据库和非关系型数据库,常见的关系型数据库有MySQL,Oracle,非关系型数据库有Redis,Elasticsearch,MongoDB和HBase等。
关系型数据库的数据建立在紧密的关系基础上,以数据表为数据的组织形式,优点是易于维护,使用方便和通过SQL可以实现复杂的操作;缺点是读写性能较差,数据组织形式灵活性不够,再就是高并发读写存在瓶颈。
非关系型数据库指的是一种数据结构化存储方法的集合,像是文档和键值对,优点有格式灵活,速度快(可选的载体多),高扩展性和成本低。缺点是没有sql支持,没有事务处理,复杂查询不太胜任。
扩展性上关系型依靠提高性能来实现,这样总会有上限。而非关系型通过分布式来扩展自己的性能。
数据类型
二进制数据,blob,目前使用存储访问路径,将实际的内容放在磁盘上来实现。
主键
唯一且不能为空。
事务
类似于原子性操作的一组操作,要么完全执行,要么完全不执行。执行失败会回滚。
事务的特性,原子性,一致性(数据的完整性没有被破坏),隔离性(多个并发事务同时读写修改),持久性(永久性修改数据,系统故障不丢失)。
MySQL中使用InnoDB的才支持事务。
事务隔离级别分为读未提交,读提交,可重复读和串行化。MySQL达到了第三层。
约束
非空约束,主键约束,唯一约束,外键约束,默认约束
脏读:事务1更新记录但没提交,事务2读取了更新后的行,事务1回滚了,则2读到的数据不存在了。
不可重复读:事务1读取记录时,事务2更新了记录并提交,事务1再读取时可以看到事务2修改后的记录。
幻读:事务1读取记录时事务2新增了记录并提交,事务1再次读取记录时会发现事务2修改后的记录。(行级锁)
优化sql的点
使用具体字段查找,避免在where中使用or,会使索引有失效的可能。使用varchar而不是char。索引不要太多,不要用在有大量重复的字段上,避免在where中使用表达式。where使用default代替null,distinct使用的字段要少。批量插入与删除,删除用ID批量删,分批,避免删除太多锁表。复合索引的使用(最左特性),先过滤,再分组。连接优先使用inner join,左连接左表要小。
MySQL优化使用合适的字段,避免使用空字段,使用连接来代替子查询,使用联合(UNION)来代替手动创建的临时表,使用事务和锁定表,使用外键,使用索引,优化相关的查询语句。自动类型转换也会使得索引不起作用。
DML(CRUD),DDL(create),DCL(grant,deny,revoke),DQL(select)
InnoDB
特点
支持行级锁,支持MVCC,支持外键,提供一致性非锁定读,利用CPU和内存的效率好。
结构
内存块组成的内存池,和后台线程,后台线程用来刷新内存池的数据,把已修改的数据刷新到磁盘。
后台线程
主线程:负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性。
IO线程:处理IO请求的回调处理。
Purge Thread:用来回收已经使用并分配的undo页。
Page Cleaner Thread:将脏页刷新操作放到单独线程中来完成
内存
读取磁盘数据加了缓冲池做过渡,类似于缓存的作用。以页作为读取单位。控制块对应缓存页。空闲页组成链表,节点对应控制块,控制块对应缓存块,用的时候,取节点,用,添加控制块信息,移除节点。使用LRU来淘汰算法,midpoint,FLUSH链表。空闲链表和LRU链表的关系是相互转化的,脏页链表(FLUSH)是在LRU链表中包含的。
checkpoint
解决的问题:缩短数据库恢复时间,缓冲池不够用时将脏页刷新到磁盘,重做日志不可用时刷新脏页。每次恢复只要从回复点之后进行就可以了,大大缩短了回复时间。缓冲池不够用时溢出最近最久未使用的页,页为脏页的情况强制执行checkpoint将脏页刷新回磁盘。重做日志循环使用,当恢复时不需要这部分日志可以被覆盖,需要的话,必须执行checkpoint将缓冲池的页至少刷新到当前重做日志的位置。
checkpoint类型,sharp,全部刷,关机时用;fuzzy,只刷新一部分脏页。
InnoDB 特性
插入缓冲:物理页的组成部分
两次写:提高可靠性,先写到两次写缓冲区,再分两次从缓冲区写入磁盘上共享表空间(副本),每次1MB,完成后再将两次写缓冲区写入数据文件
自适应哈希索引
异步IO,IO Merge
刷新邻接页,邻接脏页一起更新
InnoDB和MyISAM 区别
I:支持事务,支持行级锁和外键约束,不存储总行数。
M:不支持事务,支持表级锁,存储表的总行数,每个表有三个文件,索引文件,表结构文件,数据文件。使用非聚集索引,索引文件的数据域存储指向数据文件的指针。