【数据库】基础知识要点

来源:互联网 发布:suse11 yum安装包 编辑:程序博客网 时间:2024/06/02 14:32

不论做机器学习,还是后台开发,都需要了解数据库的基本知识,这一篇blog主要是总结数据库的一些基本概念。并不是为了讲解,重点就是总结梳理。

数据库主要是面向业务逻辑的,所以为了满足前端业务对数据的需求,数据库管理系统负责完成数据的定义、阻止、存储、管理、操作、事务管理等功能。所以数据库的学习内容里,最核心的就是数据库管理系统DBMS

一、数据库的数据组织模型与模式层级划分

数据库对数据的组织主要分为层次模型、网状模型、关系模型。
层次模型从数据结构的角度看就是树状结构,而网状模型则是图结构。当然,网状模型更好地描述世界中事物之间的关系,而层次模型受限,但是容易导致数据结构的爆炸式增长。现在最常用的数据模型就是关系模型,即关系数据库。

不论是哪一种数据结构组织成的数据库,都可以分为逻辑结构和具体数值两部分,具体存储的数据数值必须按照这种逻辑结构来存储,否则就会报错。而针对某一个应用将逻辑结构确定下来,就成了一个具体的模式。模式就是数据库中全体数据的逻辑结构和特征的描述。

一般来说,流行的数据库都提供了三级模式结构,即外模式、模式、内模式

  • 模式:是数据库中全体数据的中间层,描述了数据的逻辑结构和特征,是所有用户的公共数据视图。DDL语言可用来描述模式中的逻辑,针对一个DB,只存在一个模式
  • 外模式:是指数据库对外界的应用程序、外界用户呈现出来的一种视图,它并不代表真正的逻辑结构,仅仅是一种映像。如果应用程序不同、用户不同,则外模式就不同。
  • 内模式:又称存储模式,一个数据库只有一个存储模式。由于DBMS管理员在建立数据库模式的时候,并不关心底层细节,只关心逻辑通顺与否,所以这里需要构建一个内模式用来将逻辑模式和物理存储方式对应起来。当然,内模式也不仅仅是逻辑和存储的对应,还包括索引、压缩、加密等等。这里就有数据结构里提到的数据库的索引方法,B+树,用来加速数据库查询速度,当然也有hash索引,这种速度更快,但是对内存的消耗还是很大的。
二、关系数据库

关系数据库的数据组织形式就是关系模型,从实际应用角度,举一个学生选课数据库比较好理解,但是从理论角度来讲,关系数据模型主要包括(相同数据类型的值的集合),笛卡尔积(域的集合运算,每一个分量都是一个元组),关系(笛卡尔积的子集叫做在域上的关系,具体到实例里面,一个关系就可以抽出来作为一张数据库的表)。

在一个关系(或一张表)里,主码、候选码、主属性、非主属性(非码属性)等等概念就不赘述了,有时候码又称为键。全码意味着表里的所有属性都是候选码,即缺一不可,缺一则无法定义其中一个元组。需要注意的是,一张表中,候选码才是决定元组唯一的因素,而主码只是候选码其中的一个,主码是从经验角度对候选码的简化。在实际应用过程中,我们可以说整个表中的属性组合就是一个超码,因为每一个元组自身都可以描述自己的唯一性,但是存在一个最小超码,这个最小超码就是候选码,候选码可以有很多个,但是主码只有一个,那就是最方便数据库表操作的一个或一组属性。

关系数据库的基本操作主要有关系演算(查询、插入、删除);查询操作又包括关系代数(选择、投影、连接、除、并、差、交、笛卡尔积)

三、关系数据库的完整性

关系数据库的完整性是指数据库中的数据一些语义,只有保证这些语义正确,才能保证对数据库的操作不会出现错误。

  • 实体完整性
    表中的每一个元祖都必须主属性完整,也就是候选码中的各个属性必须存在。如果违反了实体完整性,就会拒绝插入或修改,比如插入的主码和表中一个元组一样,或者插入的元组的主码其中一项为空。
  • 参照完整性:如果一个属性并非表中(或关系中)的码,但是它又和其他表中的主码,则称该属性为外码。外码可以有两种取值,一种是空值,另一种是对应的其它表中的主码的值。
    如果违反了参照完整性,有若干种解决方案:一是拒绝执行这个操作;二是级联修改,即外码与对应的表中的主码不一致时,就级联删除或者级联修改,强制它们一致;三就是设置该处为空,这样也可以保证参照完整。具体选择哪种方法视情况而定。
  • 用户定义完整性:即具体问题具体分析的完整性定义。SQL提供了CHECK关键字来帮助检查用户定义完整性,即对域的取值设置范围规定。

如果对于一个表、或一个模式的完整性条件非常多,每次建立SQL语句都有很多的用户定义完整性需要操作,那么可以采用CONSTRAINT语句将CHECK和SQL语句独立出来,方便每次的修改。

四、SQL

关系数据库里常用的语言就是SQL了,这也是数据库里的重点内容,相当的篇幅都在讲SQL如何使用,SQL的特性等等。SQL集DDL(数据定义语言,主要是定义数据模式)、DML(数据操纵语言,包括查询、删除、插入等等)、DCL(数据控制语言,数据加密、完整性检验等等)于一体的,高度面向非过程的,而其他的关系代数和演算语言就可以忽略不计了。随后另写一篇blog总结一下SQL的语法和动词,使用SQL的DBMS同样支持关系数据库的三种模式层级关系,模式就是管理员定义的数据逻辑模式结构,外模式称为视图,内模式就是在硬盘上存储的文件。很多DBMS比如MySQL都支持SQL语言,Oracle也支持,但是其间多少有一些细微的差别,但是这并不影响我们的使用。

我们在创建数据库的时候,首先要定义一个模式,然后再在这个框架上定义表,模式和表的关系是一对多,如果没有的话,DBMS会默认为我们创建一个模式,尽管我们没有手动输入模式,但是默认的模式名就是用户名。

在数据库的各种操作中,经常会碰到两个参数 CASCADE 和 RESTRICTED,这两个含义分别是指,对于操作的数据,与其关联的数据是否要一起删除,还是保留其他的关联数据

视图:外模式的一种实现形式。

它可以在模式基础上向用户提供更加丰富的操作更加丰富的看待数据库的角度,也能将应用程序和数据库的逻辑模式在一定程度上独立出来,而且由于应用程序只能看到视图,不能看到真正的逻辑模式,也提供了一定的数据安全性

尽管SQL高度非过程,但是仍然有一些具有过程性的语句,比如触发器 TRIGGER,它是指在数据库的操作中,一旦满足了某些条件,即可触发触发器中的代码进行执行。

五、数据库的安全性

1、 在进入数据库时有用户名和密码登录,这个是用户身份鉴定
2、 定义用户权限,其中一种是满足计算机安全性等级C2的自助存取控制DAC:它是指不同的用户对数据库中的对象有不同的权限,且同一用户对不同的数据库对象有不同的权限,权限分为查看、更改和删除等等。另一种满足更高的安全等级B1,即对整个数据库中的对象都进行密级划分,只有满足一定级别权限的用户才能访问这些对象,否则不可以
用户权限的定义里最典型的就是应用程序可以访问的视图,以及DBMS管理员可以访问的模式。也就是说,外界用户只能查看外模式,只有管理员才可以访问修改逻辑模式。
在SQL语言中,集成了DCL,所以安排了GRANT和REVOKE两个动词语句来实现对数据库对象的授权和撤回。
3、 审计,这是一种监测手段,类似于摄像头,DBMS提供监视操作,将所有的用户和应用程序对数据库的修改、查看等信息全部记录在审计log中,这样就可以对审计日志进行分析,找出哪些非法用户在何时操作了哪些数据。SQL里提供了AUDIT动词法语。
4、 再有一个方法就是数据加密,加密技术应用广泛,尤其是在通信中,使用了对称非对称的加密算法,一般对于机密性非常高的数据,以及要在网路上传输的数据才会使用加密技术,因为加密的代价比较大,时间和空间的压力都比较大。

六、关系数据库的理论

单看理论是比较抽象的,一旦结合例子就显得清晰多了。
关系模型可以用五元组来表示:关系名、一组属性、属性对应的域、属性到域的映射、属性上的一组数据依赖。前四个都比较好理解,数据依赖是指属性之间的约束关系,主要包括函数依赖和多值依赖。

  • 函数依赖是指其中的一些属性能够唯一确定其他属性,比如一个学生的学号确定下来之后,其姓名、学分等等都确定下来了。将函数依赖这一概念推广到关系数据库中的码,候选码即决定项,非候选码即依赖项。若候选码多于一个,则选择一个是主码,也就是说,关系数据库的模式都满足关系模型。
  • 多值依赖是指在一张表中,其中的某一些属性受到其他若干属性的影响进而产生依赖,这样非常容易造成数据冗余,难以处理。

范式理论属于逻辑学的内容。

  • 第一范式:一个关系(或一张表)满足了每一个分量都必须是不可分的数据项,也就是说表中不能含有表,就可以称该关系数据库满足了第一范式。
  • 第二范式:在第一范式的基础上,每一个非主属性完全依赖于码,即称满足了第二范式,也就是说,表可以构成一个整体了,数据的属性相互之间有关联。
  • 第三范式:在第二范式基础上,数据表中如果不存在码传递决定非主属性,则称该关系模型满足第三范式。这一条有点抽象,解释一下,其含义是主属性都是直接决定非主属性,不存在中间的传递关系。
  • BCNF范式:又称扩展第三范式,指每一个决定因素都包含码在内
  • 第四范式:第四范式比BCNF更加严格,由于函数依赖是多值依赖的一种特殊情况,第四范式的本质含义就是限制关系模型不允许多值依赖出现,只许有函数依赖。消除多值依赖需要SQL投影操作完成

七、数据库编程

  1. 嵌入式SQL编程
    其主要方式就是采用高级语言进行流程控制,SQL语言进行数据库操作。主流语言都提供了SQL语言编程接口,将要处理的SQL语句组织成字符串传递给高级语言的接口,高级语言自己调用SQL来传递给DBMS进行处理。
    但是这其间有一个问题,就是嵌入式SQL语句和主语言之间的通信方式:一种是DBMS向主语言编译器、解释器等等传递SQL语句执行的控制状态信息,这样主语言即可根据这些信息来决定如何进行下一步操作,这种方法就是SQL通信区。另一种方法就是主语言向SQL语句提供参数,使用主变量来实现

    在嵌入式SQL中,为了弥合SQL面向集合,每次语句产生或多条记录,而主变量则每次只能存放一条记录这种矛盾,诞生了CURSOR这种东西,使用游标可以方便地操作数据库。游标的本质就是用户自己开设的一个数据缓冲区,将所有的SQL语句的执行结果存放在里面,用户利用该缓冲区将记录逐个附在变量里,告知主语言
    当然,如果查询结果就是单条记录,自然不需要游标。

  2. 动态SQL编程
    其目的是使SQL查询语句能够根据运行状态的不同而变化,因为在数据库执行SQL语句的过程中,很可能主语言的需求就变化了,需要更改操作,这时候就需要更改SQL语句,执行新的操作,这个变量的更改就放在主变量里,以适应随时更改。
    除此之外,SQL语句本身提供了动态参数功能,即 ?符号,供开发者使用。

  3. 存储过程
    在数据库编程中,除了嵌入式SQL,还有PL/SQL,这是SQL语言的过程化扩展,让其实现过程处理。PL/SQL语言中包含了赋值语句、控制结构、循环结构等等,和程序设计语言类似。PL/SQL语言编写的程序的基本结构就是块,块与块之间可以相互嵌套,每一个块完成一个独立的逻辑操作。这有点类似于高级程序语言中的函数概念。

    PL/SQL的块主要有两种类型,命名块和匿名块。匿名块每次执行都需要编译,也不可以保存在数据库中。而命名块就可以在编译之后保存在数据库中,被反复调用,命名块包括存储过程和函数

    将若干PL/SQL语句构成的操作过程编译和优化后存放在数据库中,就被称为存储过程,每次执行的时候就调用一次。由于是预先编译过的,所以执行起来不需要语法检查,运行效率很高,所以经常在服务器端使用。另外,存储过程降低了客户机和服务器之间的通信量。如果访问服务器,只要告知服务器若干参数,让服务器调用存储过程,这样执行的效率就很高。在SQL语言中,采用 Procedure 关键词进行存储过程的创建、执行、删除。同样的,也有游标可以用来对其操作。

  4. ODBC编程
    ODBC编程克服了各种不同类型的DBMS的异构性,提供了一个统一的操作接口,方便了程序的移植。使用ODBC开发应用程序,数据库的接口是ODBC api,ODBC程序的另一头是各种异构的数据库比如SQL Server、Oracle等等。我没有使用过ODBC,但是我感觉分布式开发的系统、或者更新换代的系统才会用到ODBC吧。

八、查询优化

查询处理是数据库的核心操作,主要分为查询分析、查询检查、查询优化、查询执行几个阶段。
查询分析:对语句进行词法、语法分析
查询检查:是指对语句中的数据对象进行检查,比如说要查询的表存在与否,属性是否存在,查询条件是否符合要求。检查通过后,就把SQL语句转换为等价的关系代数表达式(一般都是查询树、语法分析树),DBMS会处理这个关系代数表达式。
查询优化:即代数优化(优化关系代数表达式,即等价变换)和物理优化(基于存取路径的优化)。

在数据库优化中,主要是指选择SELECT的优化 和连接优化

  • 数据库选择SELECT方法主要有以下几种:
    1、全表扫描查询:耗时,简单粗暴。当然如果数量比较小还是比较有效的。
    2、索引、散列查询:建立在B+数和哈希表基础上,时间复杂度大大降低,数据量越大越有效。但是索引并不是一定就能够优化,在数据量比较小的时候,构建一颗索引树的时间和空间代价也是比较大的,尤其是当数据库更新频繁的时候,索引树需要经过旋转、增添删改等平衡化操作,而且如果树保存在外存上,读取外存的时间和空间都是很大的开销,散列更是如此。所以,在数据量超级庞大的情况下,再考虑建树,当然了,这些问题DBMS都已经做过优化了。
  • 连接操作的方法,也就是将两个以上的表连接在一起:
    1、 嵌套循环:简单粗暴耗时。
    2、 排序-合并方法:依然是采用有序的表来进行表的连接,效率也是大大增加。
九、事务

事务:指用户定义的一个数据库操作,操作可能只包含一条SQL语句,也可能包含多条,比如,一个存储过程就是一个事务,因为它已经编译过了,不可再细分。事务的特性就包含原子性,即一个事务要么都做,要么都不做。另外、事务还要确保一致性,即事务处理前后的结果一定保证数据库的状态满足事务处理的预期要求。事务必须确保隔离性,即事务的执行不能被其他事务干扰造成无法处理。事物的持续性即事务处理完成后,不会根据某种原因造成数据的改变或者丢失。

数据库中的事务有点类似于操作系统中的进程和线程,当然数据库的事务处理比进程和线程的处理略简单一些,毕竟处理的仅仅是数据库中的数据,而进程和线程涉及到的上下文很复杂。且事务的操作和并发控制紧紧联系在一起。

十、数据库故障恢复

系统故障(DBMS运行的OS出现故障)、物理故障(磁盘掉磁)、病毒木马(恶意篡改数据)是非事务故障,也就是说,单个DBMS自己无法解决的,DBMS可以克服的、机制最复杂的就是事务故障。

故障解决办法有:

  1. 数据转储:即备份。静态转储即转储其间不允许别的事务插手进来,比如网站团队半夜维护网站;而动态转储允许转储过程中事务进来操作,此时就需要建立事务日志log,记录到底哪些数据动过了。另外,如果数据量太大,还需要增量转储,也就是只转储改变的那一部分。转储技术不仅仅是克服故障的好办法,同样也是实现分布式的手段,分布式不仅仅可以克服故障,还能在存取效率上有很大的提升。现在已经可以实现DBMS自动把刚刚接收到的数据修改记录立即传送到数据转储的镜像上的功能,即数据库镜像。
  2. 登记日志文件:这是数据库故障恢复的核心,比如说磁盘掉磁了,登记日志文件都没了,那就没什么好说的了,损失已经形成,时光不能倒流。具有检查点的恢复技术其根本也是登记日志文件,只不过需要在检查点附近讨论到底哪些事务需要恢复,哪些事务不需要。
十一、事务并发

数据库中建立了封锁技术,和OS中的线程锁类似,确保事务的一致性。
排他锁:写锁,在增删数据库数据的时候不允许其它事务进来。
共享锁:读锁,如果一个事务在读取数据,那么其它事务也可以进来读数据,但是不能写数据。

尽管有了锁技术,但是还是会出现各种各样的错误和问题,比如锁,解决活锁的方法是设置排队队列。而死锁则可以采用预防、诊断、检测等方法来处理,和OS处理死锁的方法一样。
同样地,加锁技术还会出现惊群现象,这个也是靠排队队列来解决。

在处理并发的过程中,为确保事务的一致性和隔离性,还需要采用可串行化调度保证数据的正确性。基于此需求,诞生了两段锁协议在事务读写之前,首先要申请锁;在事务处理完成释放封锁之后,不允许再申请锁。这是一个很强的条件,充分条件。

为了提高事务处理效率,需要进行多粒度封锁,其含义就是把所有的数据库的对象分为不同的粒度,库级别最高,模式次之,表再次之,最后是一个个的元组。如果一个事务想要申请锁,那么就需要从多粒度树的头结点开始询问,数据库有没有被加锁?表有没有被加锁?如果都没有被加锁,则可以对自己想要操作的数据加锁。意向锁则是对多粒度加锁协议的一种改进,避免访问过多的对象,提高加锁效率

上述技术DBMS都已经广泛实现,也就是说,我们如果非必须只需要使用,而不需要知道其内涵到底是什么。

现阶段DBMS对应用程序的并行支持最高效的形式就是构建DBMS进程池,这样可以提高应用程序和DBMS之间的协调性

十二、面向对象的数据库技术

SQL支持面向对象技术,现在的DBMS都提供面向对象功能。也就是说,在数据角度上看,面向对象的RDBMS提供了LOB、MOB、BOOLEAN、ARRAY、DISTINCT等数据类型。也就是说,属性的类型可以自定义了,也可以完成继承,参照也有独立的类型,即引用类型。讲真这些东西我都没有用过,等到用的时候再接触吧。

十三、XML数据库

SQL支持XML,我记得在做文本处理的时候需要将文本转化成结构化的数据,看来这就是了,XML比SQL更加灵活,就是一个层级模型。

十四、数据仓库

这两年大数据这么火,等随后有时间再学习一下数据仓库吧。这里只是列一下基本的概念。
数据仓库的目的并非面向业务,数据库才是。所以数据库更追求对数据处理的实时性、便捷性、操作细碎、杂乱、更新速度快。而数据仓库则是面向分析的,目的不在于处理应用程序前端接收的业务,而是为了分析数据。所以数据不进行更新操作,数据量也较数据库大很多,一个事务采集的数据量非常大,主要目的是数据挖掘,供管理分析决策。

还有两块内容我空下来了。DBMS的系统组成,以及分布式数据库。随后再看再补吧。

原创粉丝点击