赞
踩
不论做机器学习,还是后台开发,都需要了解数据库的基本知识,这一篇blog主要是总结数据库的一些基本概念。并不是为了讲解,重点就是总结梳理。
数据库主要是面向业务逻辑的,所以为了满足前端业务对数据的需求,数据库管理系统负责完成数据的定义、阻止、存储、管理、操作、事务管理等功能。所以数据库的学习内容里,最核心的就是数据库管理系统DBMS。
数据库对数据的组织主要分为层次模型、网状模型、关系模型。
层次模型从数据结构的角度看就是树状结构,而网状模型则是图结构。当然,网状模型更好地描述世界中事物之间的关系,而层次模型受限,但是容易导致数据结构的爆炸式增长。现在最常用的数据模型就是关系模型,即关系数据库。
不论是哪一种数据结构组织成的数据库,都可以分为逻辑结构和具体数值两部分,具体存储的数据数值必须按照这种逻辑结构来存储,否则就会报错。而针对某一个应用将逻辑结构确定下来,就成了一个具体的模式。模式就是数据库中全体数据的逻辑结构和特征的描述。
一般来说,流行的数据库都提供了三级模式结构,即外模式、模式、内模式。
关系数据库的数据组织形式就是关系模型,从实际应用角度,举一个学生选课数据库比较好理解,但是从理论角度来讲,关系数据模型主要包括域(相同数据类型的值的集合),笛卡尔积(域的集合运算,每一个分量都是一个元组),关系(笛卡尔积的子集叫做在域上的关系,具体到实例里面,一个关系就可以抽出来作为一张数据库的表)。
在一个关系(或一张表)里,主码、候选码、主属性、非主属性(非码属性)等等概念就不赘述了,有时候码又称为键。全码意味着表里的所有属性都是候选码,即缺一不可,缺一则无法定义其中一个元组。需要注意的是,一张表中,候选码才是决定元组唯一的因素,而主码只是候选码其中的一个,主码是从经验角度对候选码的简化。在实际应用过程中,我们可以说整个表中的属性组合就是一个超码,因为每一个元组自身都可以描述自己的唯一性,但是存在一个最小超码,这个最小超码就是候选码,候选码可以有很多个,但是主码只有一个,那就是最方便数据库表操作的一个或一组属性。
关系数据库的基本操作主要有关系演算(查询、插入、删除);查询操作又包括关系代数(选择、投影、连接、除、并、差、交、笛卡尔积)。
关系数据库的完整性是指数据库中的数据一些语义,只有保证这些语义正确,才能保证对数据库的操作不会出现错误。
如果对于一个表、或一个模式的完整性条件非常多,每次建立SQL语句都有很多的用户定义完整性需要操作,那么可以采用CONSTRAINT语句将CHECK和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、 再有一个方法就是数据加密,加密技术应用广泛,尤其是在通信中,使用了对称非对称的加密算法,一般对于机密性非常高的数据,以及要在网路上传输的数据才会使用加密技术,因为加密的代价比较大,时间和空间的压力都比较大。
单看理论是比较抽象的,一旦结合例子就显得清晰多了。
关系模型可以用五元组来表示:关系名、一组属性、属性对应的域、属性到域的映射、属性上的一组数据依赖。前四个都比较好理解,数据依赖是指属性之间的约束关系,主要包括函数依赖和多值依赖。
范式理论属于逻辑学的内容。
七、数据库编程:
嵌入式SQL编程:
其主要方式就是采用高级语言进行流程控制,SQL语言进行数据库操作。主流语言都提供了SQL语言编程接口,将要处理的SQL语句组织成字符串传递给高级语言的接口,高级语言自己调用SQL来传递给DBMS进行处理。
但是这其间有一个问题,就是嵌入式SQL语句和主语言之间的通信方式:一种是DBMS向主语言编译器、解释器等等传递SQL语句执行的控制状态信息,这样主语言即可根据这些信息来决定如何进行下一步操作,这种方法就是SQL通信区。另一种方法就是主语言向SQL语句提供参数,使用主变量来实现。
在嵌入式SQL中,为了弥合SQL面向集合,每次语句产生或多条记录,而主变量则每次只能存放一条记录这种矛盾,诞生了CURSOR这种东西,使用游标可以方便地操作数据库。游标的本质就是用户自己开设的一个数据缓冲区,将所有的SQL语句的执行结果存放在里面,用户利用该缓冲区将记录逐个附在变量里,告知主语言。
当然,如果查询结果就是单条记录,自然不需要游标。
动态SQL编程
其目的是使SQL查询语句能够根据运行状态的不同而变化,因为在数据库执行SQL语句的过程中,很可能主语言的需求就变化了,需要更改操作,这时候就需要更改SQL语句,执行新的操作,这个变量的更改就放在主变量里,以适应随时更改。
除此之外,SQL语句本身提供了动态参数功能,即 ?符号,供开发者使用。
存储过程
在数据库编程中,除了嵌入式SQL,还有PL/SQL,这是SQL语言的过程化扩展,让其实现过程处理。PL/SQL语言中包含了赋值语句、控制结构、循环结构等等,和程序设计语言类似。PL/SQL语言编写的程序的基本结构就是块,块与块之间可以相互嵌套,每一个块完成一个独立的逻辑操作。这有点类似于高级程序语言中的函数概念。
PL/SQL的块主要有两种类型,命名块和匿名块。匿名块每次执行都需要编译,也不可以保存在数据库中。而命名块就可以在编译之后保存在数据库中,被反复调用,命名块包括存储过程和函数。
将若干PL/SQL语句构成的操作过程编译和优化后存放在数据库中,就被称为存储过程,每次执行的时候就调用一次。由于是预先编译过的,所以执行起来不需要语法检查,运行效率很高,所以经常在服务器端使用。另外,存储过程降低了客户机和服务器之间的通信量。如果访问服务器,只要告知服务器若干参数,让服务器调用存储过程,这样执行的效率就很高。在SQL语言中,采用 Procedure 关键词进行存储过程的创建、执行、删除。同样的,也有游标可以用来对其操作。
ODBC编程:
ODBC编程克服了各种不同类型的DBMS的异构性,提供了一个统一的操作接口,方便了程序的移植。使用ODBC开发应用程序,数据库的接口是ODBC api,ODBC程序的另一头是各种异构的数据库比如SQL Server、Oracle等等。我没有使用过ODBC,但是我感觉分布式开发的系统、或者更新换代的系统才会用到ODBC吧。
查询处理是数据库的核心操作,主要分为查询分析、查询检查、查询优化、查询执行几个阶段。
查询分析:对语句进行词法、语法分析
查询检查:是指对语句中的数据对象进行检查,比如说要查询的表存在与否,属性是否存在,查询条件是否符合要求。检查通过后,就把SQL语句转换为等价的关系代数表达式(一般都是查询树、语法分析树),DBMS会处理这个关系代数表达式。
查询优化:即代数优化(优化关系代数表达式,即等价变换)和物理优化(基于存取路径的优化)。
在数据库优化中,主要是指选择SELECT的优化 和连接优化
事务:指用户定义的一个数据库操作,操作可能只包含一条SQL语句,也可能包含多条,比如,一个存储过程就是一个事务,因为它已经编译过了,不可再细分。事务的特性就包含原子性,即一个事务要么都做,要么都不做。另外、事务还要确保一致性,即事务处理前后的结果一定保证数据库的状态满足事务处理的预期要求。事务必须确保隔离性,即事务的执行不能被其他事务干扰造成无法处理。事物的持续性即事务处理完成后,不会根据某种原因造成数据的改变或者丢失。
数据库中的事务有点类似于操作系统中的进程和线程,当然数据库的事务处理比进程和线程的处理略简单一些,毕竟处理的仅仅是数据库中的数据,而进程和线程涉及到的上下文很复杂。且事务的操作和并发控制紧紧联系在一起。
系统故障(DBMS运行的OS出现故障)、物理故障(磁盘掉磁)、病毒木马(恶意篡改数据)是非事务故障,也就是说,单个DBMS自己无法解决的,DBMS可以克服的、机制最复杂的就是事务故障。
故障解决办法有:
数据库中建立了封锁技术,和OS中的线程锁类似,确保事务的一致性。
排他锁:写锁,在增删数据库数据的时候不允许其它事务进来。
共享锁:读锁,如果一个事务在读取数据,那么其它事务也可以进来读数据,但是不能写数据。
尽管有了锁技术,但是还是会出现各种各样的错误和问题,比如活锁,解决活锁的方法是设置排队队列。而死锁则可以采用预防、诊断、检测等方法来处理,和OS处理死锁的方法一样。
同样地,加锁技术还会出现惊群现象,这个也是靠排队队列来解决。
在处理并发的过程中,为确保事务的一致性和隔离性,还需要采用可串行化调度保证数据的正确性。基于此需求,诞生了两段锁协议:在事务读写之前,首先要申请锁;在事务处理完成释放封锁之后,不允许再申请锁。这是一个很强的条件,充分条件。
为了提高事务处理效率,需要进行多粒度封锁,其含义就是把所有的数据库的对象分为不同的粒度,库级别最高,模式次之,表再次之,最后是一个个的元组。如果一个事务想要申请锁,那么就需要从多粒度树的头结点开始询问,数据库有没有被加锁?表有没有被加锁?如果都没有被加锁,则可以对自己想要操作的数据加锁。意向锁则是对多粒度加锁协议的一种改进,避免访问过多的对象,提高加锁效率。
上述技术DBMS都已经广泛实现,也就是说,我们如果非必须只需要使用,而不需要知道其内涵到底是什么。
现阶段DBMS对应用程序的并行支持最高效的形式就是构建DBMS进程池,这样可以提高应用程序和DBMS之间的协调性。
SQL支持面向对象技术,现在的DBMS都提供面向对象功能。也就是说,在数据角度上看,面向对象的RDBMS提供了LOB、MOB、BOOLEAN、ARRAY、DISTINCT等数据类型。也就是说,属性的类型可以自定义了,也可以完成继承,参照也有独立的类型,即引用类型。讲真这些东西我都没有用过,等到用的时候再接触吧。
SQL支持XML,我记得在做文本处理的时候需要将文本转化成结构化的数据,看来这就是了,XML比SQL更加灵活,就是一个层级模型。
这两年大数据这么火,等随后有时间再学习一下数据仓库吧。这里只是列一下基本的概念。
数据仓库的目的并非面向业务,数据库才是。所以数据库更追求对数据处理的实时性、便捷性、操作细碎、杂乱、更新速度快。而数据仓库则是面向分析的,目的不在于处理应用程序前端接收的业务,而是为了分析数据。所以数据不进行更新操作,数据量也较数据库大很多,一个事务采集的数据量非常大,主要目的是数据挖掘,供管理分析决策。
还有两块内容我空下来了。DBMS的系统组成,以及分布式数据库。随后再看再补吧。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。