数据库知识点总结1

当年肥工的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语句实现一些用户定义的业务逻辑缓存

关系模型服务器

(略)网络

 

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

索引的优势

  • 大大减小了服务器须要扫描的数据行数。
  • 帮助服务器避免进行排序和分组,以及避免建立临时表(B+Tree 索引是有序的,能够用于 ORDER BY 和 GROUP BY 操做。临时表主要是在排序和分组过程当中建立,不须要排序和分组,也就不须要建立临时表)。
  • 将随机 I/O 变为顺序 I/O(B+Tree 索引是有序的,会将相邻的数据都存储在一块儿)。

索引的使用条件

  • 对于很是小的表、大部分状况下简单的全表扫描比创建索引更高效;
  • 对于中到大型的表,索引就很是有效;
  • 可是对于特大型的表,创建和维护索引的代价将会随之增加。这种状况下,须要用到一种技术能够直接区分出须要查询的一组数据,而不是一条记录一条记录地匹配,例如可使用分区技术。

 

事务

咱们在写Java程序,遇到并发问题时,会想到用锁来解决。数据库遇到并发问题怎么解决呢?答案就是事务,事务的本质就是锁和并发的结合体(能够理解成在数据库系统上执行的一个函数。好比在银行数据库中,把A的100元钱转给B)

事务指的是知足 ACID 特性的一组操做,能够经过 Commit 提交一个事务,也可使用 Rollback 进行回滚。一个事务包含了多个命令,服务器在执行事务期间,不会改去执行其它客户端的命令请求。事务是并发控制的基本单位

事务中的多个命令被一次性发送给服务器,而不是一条一条发送,这种方式被称为流水线,它能够减小客户端与服务器之间的网络通讯次数从而提高性能。

ACID特性

  • Atomicity    事务被视为不可分割的最小单元,事务的全部操做要么所有提交成功,要么所有失败回滚。回滚能够用回滚日志来实现,回滚日志记录着事务所执行的修改操做,在回滚时反向执行这些修改操做便可。
  • Consistency    数据库在事务执行先后都保持一致性状态。在一致性状态下,全部事务对一个数据的读取结果都是相同的。
  • Isolation    一个事务所作的修改在最终提交之前,对其它事务是不可见的。换句话说就是并发执行的事务不会相互影响,其对数据库的影响和它们串行执行时同样。
  • Durability    一旦事务提交,则其所作的修改将会永远保存到数据库中。即便系统发生崩溃,事务执行的结果也不能丢失。使用重作日志来保证持久性。
  • 只有知足一致性,事务的执行结果才是正确的。
  • 在无并发的状况下,事务串行执行,隔离性必定可以知足。此时只要能知足原子性,就必定能知足一致性。
  • 在并发的状况下,多个事务并行执行,事务不只要知足原子性,还须要知足隔离性,才能知足一致性。
  • 事务知足持久化是为了能应对数据库崩溃的状况。
  • 并发控制技术保证了事务的隔离性,使数据库的一致性状态不会由于并发执行的操做被破坏。
  • 日志恢复技术保证了事务的原子性,使一致性状态不会因事务或系统故障被破坏。同时使已提交的对数据库的修改不会因系统崩溃而丢失,保证了事务的持久性。

恢复

 

并发控制

事务是并发控制的基本单位。

并发一致性问题

在并发环境下,事务的隔离性很难保证,所以会出现不少并发一致性问题。解决方法是经过并发控制来保证隔离性。并发控制能够经过封锁来实现,可是封锁操做须要用户本身控制,至关复杂。数据库管理系统提供了事务的隔离级别,让用户以一种更轻松的方式处理并发一致性问题。

并发控制主要技术:封锁、时间戳、乐观控制法、多版本并发控制等。

封锁:至关于分布式中的加锁/解锁。基本封锁类型:排他锁(X 锁 / 写锁)、共享锁(S 锁 / 读锁)。

  • 写锁:对A加写锁以后,其余事务不可再读写A
  • 读锁:对A加读锁以后,其余事务只能读A

封锁协议:规定加锁解锁的规则

两段锁协议:全部事务必须分两个阶段对数据项加锁/解锁:

  • 准备阶段:在对任何数据进行读、写操做以前,首先要申请并得到对该数据的封锁(此时能够申请任何锁,但不能释放锁)
    • 具体实现中,在准备阶段会有一个协调者,向参与者申请资源并锁定资源,执行事务操做。可是并无commit或者rollback
  • 提交阶段:在释放一个封锁以后,事务再也不申请和得到任何其余封锁(此时能够释听任何锁,但不能再申请锁)
    • 这一步才真正commit或者rollback。若是协调者发现全部参与者都返回yes就commit,只要有一我的返回no就rollback

若并发执行的全部事务都遵循两段锁协议,则对这些事务的任何并发调度策略都是可串行化的。

可是对于分布式事务,2pc有可能出现数据不一致的问题。若是要完全解决这一问题就要用paxos或者Raft了。

封锁粒度:具体对哪一个对象加锁

MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
应该尽可能只锁定须要修改的那部分数据,而不是全部的资源。锁定的数据量越少,发生锁争用的可能就越小,系统的并发程度就越高。
可是加锁须要消耗资源,锁的各类操做(包括获取锁、释放锁、以及检查锁状态)都会增长系统开销。所以封锁粒度越小,系统开销就越大。
在选择封锁粒度时,须要在锁开销和并发程度之间作一个权衡。

活锁:某个事务等待时间太长,可经过先来先服务的策略避免。

死锁:事务永远没法完成,同OS中的死锁

  • 预防:一次封锁法(每一个事务必须一次将全部要使用的数据所有加锁)、顺序封锁法;
  • 诊断:超时法、等待图法;
  • 解除:撤销处理死锁代价最小的事务,并释放此事务的全部的锁,使其余事务得以继续运行下去。

可串行化调度:可串行性是并发事务正确调度的准则。表示并发调度的结果和彻底串行执行的结果是一致的。

隔离级别事务具备隔离性,理论上来讲事务之间的执行不该该相互产生影响,其对数据库的影响应该和它们串行执行时同样。然而彻底的隔离性会致使系统并发性能很低,下降对资源的利用率,于是实际上对隔离性的要求会有所放宽,这也会必定程度形成对数据库一致性要求下降。事务的隔离级别越低,可能出现的并发异常越多,可是一般而言系统能提供的并发能力越强。

  • 未提交读(READ UNCOMMITTED):事务中的修改,即便没有提交,对其它事务也是可见的。        最低级别,任何状况都没法保证。
  • 提交读(READ COMMITTED):一个事务只能读取已经提交的事务所作的修改。换句话说,一个事务所作的修改在提交以前对其它事务是不可见的。       可避免脏读的发生
  • 可重复读(REPEATABLE READ):保证在同一个事务中屡次读取一样数据的结果是同样的。       可避免脏读、不可重复读的发生。
  • 可串行化(SERIALIZABLE):强制事务串行执行。须要加锁实现,而其它隔离级别一般不须要。       可避免脏读、不可重复读、幻读的发生。

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 线程。

  • binlog 线程 :负责将主服务器上的数据更改写入二进制日志(Binary log)中。
  • I/O 线程 :负责从主服务器上读取二进制日志,并写入从服务器的中继日志(Relay log)。
  • SQL 线程 :负责读取中继日志,解析出主服务器已经执行的数据更改并在从服务器中重放(Replay)。

 

读写分离

主服务器处理写操做以及实时性要求比较高的读操做,而从服务器处理读操做。读写分离能提升性能的缘由在于:

  • 主从服务器负责各自的读和写,极大程度缓解了锁的争用;
  • 从服务器可使用 MyISAM,提高查询性能以及节约系统开销;
  • 增长冗余,提升可用性。

读写分离经常使用代理方式来实现,代理服务器接收应用层传来的读写请求,而后决定转发到哪一个服务器。

 

 

 

 

 


 

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

相关文章
相关标签/搜索