当年肥工的DB课讲的其实还挺好的...就用当时的笔记叭html
(因此当年为何不整理呢?仍是懒叭mysql
完整性:防止DB中存在不符合规定的数据(eg:性别只能是男或女)git
实体完整性:primary key中的属性取值必须惟一且不能为空github
参照完整性:若F是R的外码(foreign key),K是S的主码(primary key),F链接K。那么对于R中的每一个元祖,R.F必须是 在S.K中出现过的值 或者 NULL算法
用户定义的完整性:用户本身在具体的DB中指定的约束(定义:NOT NULL / UNIQUE / CHECK)sql
触发器:用于实现用户定义的完整性 CREATE TRIGGER ON ... AFTER ...数据库
存储过程:用SQL语句实现一些用户定义的业务逻辑缓存
关系模型服务器
(略)网络
(略)
B+Tree
B Tree 指的是 Balance Tree,也就是平衡树。平衡树是一颗查找树,而且全部叶子节点位于同一层。
B+ Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现,它具备 B Tree 的平衡性,而且经过顺序访问指针来提升区间查询的性能。
在 B+ Tree 中,一个节点中的 key 从左到右非递减排列,若是某个指针的左右相邻 key 分别是 keyi 和 keyi+1,且不为 null,则该指针指向节点的全部 key 大于等于 keyi 且小于等于 keyi+1。
进行查找操做时,首先在根节点进行二分查找,找到一个 key 所在的指针,而后递归地在指针所指向的节点进行查找。直到查找到叶子节点,而后在叶子节点上进行二分查找,找出 key 所对应的 data。
插入删除操做会破坏平衡树的平衡性,所以在插入删除操做以后,须要对树进行一个分裂、合并、旋转等操做来维护平衡性。
与红黑树的比较
红黑树等平衡树也能够用来实现索引,可是文件系统及数据库系统广泛采用 B+ Tree 做为索引结构,主要有如下两个缘由:
(一)更少的查找次数
平衡树查找操做的时间复杂度和树高 h 相关,O(h)=O(logdN),其中 d 为每一个节点的出度。
红黑树的出度为 2,而 B+ Tree 的出度通常都很是大,因此红黑树的树高 h 很明显比 B+ Tree 大很是多,查找的次数也就更多。
(二)利用磁盘预读特性
为了减小磁盘 I/O 操做,磁盘每每不是严格按需读取,而是每次都会预读。预读过程当中,磁盘进行顺序读取,顺序读取不须要进行磁盘寻道,而且只须要很短的磁盘旋转时间,速度会很是快。
操做系统通常将内存和磁盘分割成固定大小的块,每一块称为一页,内存与磁盘以页为单位交换数据。数据库系统将索引的一个节点的大小设置为页的大小,使得一次 I/O 就能彻底载入一个节点。而且能够利用预读特性,相邻的节点也可以被预先载入。
B+ Tree、LSM Tree:http://www.javashuo.com/article/p-dozobccc-kc.html
MYSQL:http://blog.codinglabs.org/articles/theory-of-mysql-index.html
Hash:http://www.javashuo.com/article/p-tmiclehe-cv.html
红黑树:https://www.jianshu.com/p/e136ec79235c
索引的优势
索引的使用条件
咱们在写Java程序,遇到并发问题时,会想到用锁来解决。数据库遇到并发问题怎么解决呢?答案就是事务,事务的本质就是锁和并发的结合体(能够理解成在数据库系统上执行的一个函数。好比在银行数据库中,把A的100元钱转给B)
事务指的是知足 ACID 特性的一组操做,能够经过 Commit 提交一个事务,也可使用 Rollback 进行回滚。一个事务包含了多个命令,服务器在执行事务期间,不会改去执行其它客户端的命令请求。事务是并发控制的基本单位。
事务中的多个命令被一次性发送给服务器,而不是一条一条发送,这种方式被称为流水线,它能够减小客户端与服务器之间的网络通讯次数从而提高性能。
ACID特性:
恢复:
事务是并发控制的基本单位。
并发一致性问题
在并发环境下,事务的隔离性很难保证,所以会出现不少并发一致性问题。解决方法是经过并发控制来保证隔离性。并发控制能够经过封锁来实现,可是封锁操做须要用户本身控制,至关复杂。数据库管理系统提供了事务的隔离级别,让用户以一种更轻松的方式处理并发一致性问题。
并发控制主要技术:封锁、时间戳、乐观控制法、多版本并发控制等。
封锁:至关于分布式中的加锁/解锁。基本封锁类型:排他锁(X 锁 / 写锁)、共享锁(S 锁 / 读锁)。
封锁协议:规定加锁解锁的规则
两段锁协议:全部事务必须分两个阶段对数据项加锁/解锁:
若并发执行的全部事务都遵循两段锁协议,则对这些事务的任何并发调度策略都是可串行化的。
可是对于分布式事务,2pc有可能出现数据不一致的问题。若是要完全解决这一问题就要用paxos或者Raft了。
封锁粒度:具体对哪一个对象加锁
MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
应该尽可能只锁定须要修改的那部分数据,而不是全部的资源。锁定的数据量越少,发生锁争用的可能就越小,系统的并发程度就越高。
可是加锁须要消耗资源,锁的各类操做(包括获取锁、释放锁、以及检查锁状态)都会增长系统开销。所以封锁粒度越小,系统开销就越大。
在选择封锁粒度时,须要在锁开销和并发程度之间作一个权衡。
活锁:某个事务等待时间太长,可经过先来先服务的策略避免。
死锁:事务永远没法完成,同OS中的死锁
可串行化调度:可串行性是并发事务正确调度的准则。表示并发调度的结果和彻底串行执行的结果是一致的。
隔离级别事务具备隔离性,理论上来讲事务之间的执行不该该相互产生影响,其对数据库的影响应该和它们串行执行时同样。然而彻底的隔离性会致使系统并发性能很低,下降对资源的利用率,于是实际上对隔离性的要求会有所放宽,这也会必定程度形成对数据库一致性要求下降。事务的隔离级别越低,可能出现的并发异常越多,可是一般而言系统能提供的并发能力越强。
MVCC
在分布式数据库中,为了提升事务执行的并行度,会使用MVCC进行并发控制。MYSQL中就用MVCC进行并发控制。
切分
水平切分:水平切分又称为 Sharding,它是将同一个表中的记录拆分到多个结构相同的表中。
当一个表的数据不断增多时,Sharding 是必然的选择,它能够将数据分布到集群的不一样节点上,从而缓存单个数据库的压力。
垂直切分:将一张表按列切分红多个表,一般是按照列的关系密集程度进行切分,也能够利用垂直切分将常常被使用的列和不常常被使用的列切分到不一样的表中。
在数据库的层面使用垂直切分将按数据库中表的密集程度部署到不一样的库中,例如将原来的电商数据库垂直切分红商品数据库、用户数据库等。
Sharding 策略
哈希取模:hash(key) % N;
范围:能够是 ID 范围也能够是时间范围;
映射表:使用单独的一个数据库来存储映射关系。
Sharding 存在的问题
1. 事务问题 使用分布式事务来解决,好比 XA 接口。
2. 链接 能够将原来的链接分解成多个单表查询,而后在用户程序中进行链接。
3. ID 惟一性 使用全局惟一 ID(GUID)、为每一个分片指定一个 ID 范围、分布式 ID 生成器 (如 Twitter 的 Snowflake 算法)
主从复制
主要涉及三个线程:binlog 线程、I/O 线程和 SQL 线程。
读写分离
主服务器处理写操做以及实时性要求比较高的读操做,而从服务器处理读操做。读写分离能提升性能的缘由在于:
读写分离经常使用代理方式来实现,代理服务器接收应用层传来的读写请求,而后决定转发到哪一个服务器。
https://github.com/CyC2018/CS-Notes/blob/master/notes/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%B3%BB%E7%BB%9F%E5%8E%9F%E7%90%86.md
https://github.com/huihut/interview#-%E6%95%B0%E6%8D%AE%E5%BA%93
https://github.com/CyC2018/CS-Notes/blob/master/notes/MySQL.md
https://github.com/CyC2018/CS-Notes/blob/master/notes/Redis.md