网站选择空间,东营网站制作方案,网站设计宁波,企业信息公示系统年报废话不多说#xff0c;上干货是兔老大的传统了#xff0c;收藏就完事了。 目录
数据库系统概论
四个基本概念
数据模型
数据库系统结构
数据库系统模式的概念
数据库系统的三级模式结构
数据库的二级映像功能与数据的独立性
数据库系统的组成
关系
关系模式
关系数… 废话不多说上干货是兔老大的传统了收藏就完事了。 目录
数据库系统概论
四个基本概念
数据模型
数据库系统结构
数据库系统模式的概念
数据库系统的三级模式结构
数据库的二级映像功能与数据的独立性
数据库系统的组成
关系
关系模式
关系数据库
基本的关系操作
关系的完整性
实体完整性即主属性非空
参照完整性
用户定义完整性
关系代数
传统的集合运算
专门的关系运算
选择
投影
连接
除
数据类型大总结
整数类型
实数类型
浮点数类型
BIT数据类型
字符串类型
CHAR VARCHAR
BINARY VARBINARY
BLOB TEXT
ENUM 使用枚举代替字符串类型
时间和日期类型
关系数据库标准语言SQL
基本概念
数据库的创建与基本概念
模式的创建与删除
表的定义、删除与修改
索引的建立与删除
sql查询
单表查询
连接查询
嵌套查询
集合查询
sql增删改
数据的插入
3.5.2 数据的修改
3.5.3 数据的删除 mysql常用函数总结
文本处理函数
日期和时间处理函数
数值处理函数
视图/存储过程/触发器
视图
为什么使用视图
视图的规则和限制
视图的创建
视图的更新
存储过程
为什么使用储存过程
执行存储过程
使用参数的存储过程
带有控制语句的存储过程
触发器
创建触发器
触发器类别
总结
数据库恢复
实现技术
数据转储
日志文件
1、什么是日志文件
2、日志文件的格式
3、日志文件的作用
4、登记日志文件
恢复策略
事务故障的恢复
系统故障的恢复
介质故障的恢复
检查点
镜像
小结
常用恢复技术
提高恢复效率的技术
并发控制
概述
封锁
封锁协议
饥饿
死锁
解决死锁的方法预防、诊断和解除
串行调度
可串行化调度
冲突可串行化调度
两段锁协议
封锁的粒度
意向锁
其他并发控制 数据库系统概论
四个基本概念
数据数据库中存储的基本对象描述一个事物的符号记录数据和其语义不可分开说
数据库DB是长期储存在计算机内、有组织的、可共享的大量数据的集合。
数据库管理系统一个管理数据的软件
主要功能
数据定义功能
1提供数据定义语言(DDL)创建表CREATE修改表ALTER删除表DROP
2定义数据库中的数据对象
操纵功能
提供数据操纵语言(DML即增删改查的操作)实现对数据库的基本操作 (查询、插入、删除和修改)
事务管理和运行管理
数据库由DBMS统一管理和控制保证数据的安全完整性、多用户对数据的并发使用、发生故障后的系统恢复
建立和维护功能1数据库初始数据装载转换2数据库转储3介质故障恢复4数据库的重组织5性能监视分析等
数据库系统由数据库、数据库管理系统应用程序和数据库管理员DBA等组成的存储、管理、处理和维护数据的系统。
数据模型
两类数据模型 概念模型第一次抽象用于数据库设计 逻辑模型和物理模型第二次抽象 1逻辑模型主要包括网状模型、层次模型、关系模型、面向对象模型等按计算机系统的观点对数据建模用于DBMS实现 2物理模型是对数据最底层的抽象描述数据在系统内部的表示方式和存取方法在磁盘或磁带上的存储方式和存取方法
数据模型的组成要素 数据结构 1描述数据库的组成对象以及对象之间的联系 2描述与数据之间联系有关的对象 3是对系统静态特性的描述 4分类1非关系型网状层次2关系型3面向对象型 数据操作 1对数据库中各种对象(型)的实例(值)允许执行的操作及有关的操作规则 2增删改查 3是对系统动态特性的描述 数据的完整性约束条件 1一组完整性规则的集合 2完整性规则给定的数据模型中数据及其联系所具有的制约和储存规则 3用以限定符合数据模型的数据库状态以及状态的变化以保证数据的正确、有效、相容 实体完整性具体的数据的属性信息是否完整 参照完整性该属性对应的值存在 用户定义完整性看心情
关系模型 基本概念 1关系Relation一个关系对应通常说的一张表 2元组Tuple表中的一行即为一个元组 3属性Attribute表中的一列即为一个属性给每一个属性起一个名称即属性名 4码Key 唯一确定一个元组的属性或属性组 5域Domain 是一组具有相同数据类型的值的集合 6分量元组中的一个属性值 7关系模式对关系的描述一般表示为 关系名属性1属性2……属性n 学生学号姓名年龄性别系年级 8注意规范不能出现大表套小表。 数据操作增删改查对若干元组操作的集合 数据的完整性约束条件 1实体完整性 2参照完整性 3用户定义完整性
数据库系统结构
数据库系统模式的概念
型对某一类数据的结构和属性的说明学号姓名性别系别年龄籍贯值是型的一个具体赋值201315130李明男计算机19江苏模式数据库逻辑结构和特征的描述是型的描述反映的是数据的结构及其联系模式是相对稳定的即属性名的集合实例模式的一个具体值反映数据库某一时刻的状态同一个模式可以有很多实例实例随数据库中的数据的更新而变动如果是一个成绩单那么科目那一行表示的是模式不仅仅只是这些还包括其他的信息每一个人的成绩一行表示的是一个实例
数据库系统的三级模式结构 模式数据库中全体数据的逻辑结构和特征的描述所有用户的公共数据视图综合了所有用户的需求一个数据库只有一个模式模式是相对稳定的但是实体是相对变动的 地位1是数据库系统模式结构的中间层2与数据的物理存储细节和硬件环境无关3与具体的应用程序、开发工具及高级程序设计语言无关 定义1数据的逻辑结构数据项的名字、类型、取值范围等2数据之间的联系3数据有关的安全性、完整性要求 外模式模式的子集一个数据库可以有多个是数据库中局部数据的逻辑结构和特征的描述 内模式1是数据物理结构和存储方式的描述2是数据在数据库内部的表示方式 一个数据库只有一个内模式。
数据库的二级映像功能与数据的独立性 外模式/模式映像保证了数据的逻辑独立性。不唯一 1当模式改变时数据库管理员修改有关的外模式模式映象使外模式保持不变 2应用程序是依据数据的外模式编写的从而应用程序不必修改保证了数据与程序的逻辑独立性简称数据的逻辑独立性。 模式/内模式映像保证了数据的物理独立性。唯一 1当数据库的存储结构改变了例如选用了另一种存储结构数据库管理员修改模式内模式映象使模式保持不变进而外模式也不发生改变 2应用程序不受影响。保证了数据与程序的物理独立性简称数据的物理独立性 数据的存取由DBMS管理的好处 1用户不必考虑存取路径等细节 2简化了应用程序的编制 3大大减少了应用程序的维护和修改 数据库系统的组成
硬件操作系统数据库设计人员数据库管理人员数据库管理系统用户等等。 关系 域一组具有相同数据类型的值的集合即取值范围 笛卡尔积域上的一种集合运算。结果为一个集合集合的每一个元素是一个元组元组的每一个分量来自不同的域。 基数一个域允许的不同取值个数。 笛卡尔积的基数每个域不同取值的个数的乘积或者说元组的个数 关系域的笛卡尔积的子集叫做在域上的关系域的个数叫做关系的目或度。即列数属性的数目注意广义上的笛卡尔积一般不能称为关系因为存在无效的数据。 关系表 列属性 行元组 候选码某一属性组的值能唯一地标示一个元组而其子集不能则称该属性组为候选码 主属性候选码中的属性都称为主属性注意主属性非空。 非主属性候选码之外的属性称为非主属性 全码关系模式的所有属性是这个关系模式的候选码 主码从候选码中选取一组能唯一确定一个元组的属性组作为主码。 三类关系 1基本关系实际存在的表是实际存储数据的逻辑表示 2查询表查询结果对应的表 3视图表由基本表或其他视图表导出的表是虚表不对应实际存储的数据。 注意关系数据模型中的关系必须是有限集合。 关系的每一个列必须附加一个属性名属性名不能重名这种方法取消了关系属性的有序性。 ① 列是同质的Homogeneous每一列中的分量来自同一个域是同一类型的数据 ② 不同的列可出自同一个域 其中的每一列称为一个属性 不同的属性要给予不同的属性名 ③ 列的顺序无所谓, 列的次序可以任意交换 ④ 任意两个元组的候选码不能相同相同就不是候选码了 ⑤ 行的顺序无所谓行的次序可以任意交换 ⑥ 分量必须取原子值不允许表中套表
关系模式 关系模式对关系的描述是静态的、稳定的 关系是关系模式在某一时刻的状态或内容是动态的、随时间不断变化的指后边的那个关系 关系模式的形式化表示
//关系模式
R(U, D, DOM, F)
R 关系名
U 组成该关系的属性名集合
D 属性组U中属性所来自的域
DOM 属性向域的映象集合
F 属性间的数据依赖关系集合//可以简记为
R (U) 或 R (A1A2…An)
R: 关系名
A1A2…An : 属性名
注域名及属性向域的映象常常直接说明为属性的类型、长度
关系数据库 在一个给定的应用领域中所有关系的集合构成一个关系数据库 关系数据库的型与值不是关系的型与值 1关系数据库的型也称关系数据库模式是对关系数据库的描述 2关系数据库的值是关系模式在某一时刻对应的关系的集合简称为关系数据库
基本的关系操作 常用的基本操作 **查询**选择、投影、连接、除、并、交、差 **数据更新**插入、删除、修改 **5种基本操作**选择、投影、并、差、笛卡尔积 注意不算交 关系操作的特点 集合操作方式操作的对象和结果都是集合一次一集合的方式操作对象是集合操作结果亦为集合。 关系的完整性
实体完整性即主属性非空
若属性A是基本关系R的主属性则属性A不能取空值
参照完整性 关系间的引用关系与关系之间存在着联系 外码设F是基本关系R的一个或一组属性但不是关系R的主码Ks是基本关系S的主码。如果F与Ks相对应则称F是基本关系R的外码外码所在的基本关系叫做参照关系Ks所在的关系叫做被参照关系。 注 1R、S不一定是不同的关系。 2目标关系S的主码Ks 和参照关系的外码F必须定义在同一个或一组域上 3外码并不一定要与相应的主码同名当外码与相应的主码属于不同关系时往往取相同的名字以便于识别 4外码的取值如果外码是参照关系的主属性则不能为空实体完整性只能为被参照关系中主码的取值。如果外码不是参照关系的主属性则可以取空或者被参照关系主码的取值 两个不变性指实体完整性和参照完整性
用户定义完整性 针对某一具体关系数据库的约束条件反映某一具体应用所涉及的数据必须满足的语义要求 关系模型应提供定义和检验这类完整性的机制以便用统一的系统的方法处理它们而不要由应用程序承担这一功能
关系代数
传统的集合运算 传统的关系运算 并、交、差、笛卡尔积 操作对象关系 操作方式同数学中的并、交、差、笛卡尔积。只不过操作对象的元素是元组。另外需要注意能进行运算所需要满足的条件。 对于并、交、差需要满足的关系1属性的数目相同2相应的属性取自同一个域
专门的关系运算
常见的关系运算有选择、投影、连接、除
选择
在关系R中选择满足给定条件的诸元组。
表达式$\sigma_F(R) {t | t \in R \and F(t) true}$
F为选择条件是一个逻辑表达式基本形式为$X_1 \theta Y_1$其中$\theta$为大于、小于、等于、不等于等。
举例 选择$\sigma_{Sdept IS}(Student)$ 投影
从R中选择出若干属性列组成新的关系
表达式$\prod_{A} (R) {t[A] | t\in R}$
A为属性列即从R中选择A中属性列的元组当然选择之后可能会删掉一些元组因为避免重复。
举例还是上方的关系经过投影$\prod_{Sname, Sdept}(Student)$结果如下 连接 1**一般连接**从两个关系的笛卡尔积中选取属性间满足一定条件的元组
1表达式$R\bowtie_ {A \theta B} S {t_r^ \frown t_s | t_r \in R \and t_s \in S \and t_r[A] \theta t_s[B] }$
2A和B分别为R和S上度数相等且可比的属性组
3$\theta$表示比较运算符
4连接运算从R和S的广义笛卡尔积R×S中选取R关系在A属性组上的值与S关系在B属性组上值满足比较关系θ的元组
2**等值连接**当上述的运算符为等于号的时候
1含义从关系R与S的广义笛卡尔积中选取A、B属性值相等的那些元组即等值连接为
2表达式$R\bowtie_ {A B} S {t_r^ \frown t_s | t_r \in R \and t_s \in S \and t_r[A] t_s[B] }$
3仍然是从行的角度进行运算而不涉及列
4属性组可以不同
3**自然连接**一种特殊的等值连接
1与等值连接的不同两个关系R和S必须具有相同的属性组
2将结果中相同的属性列去掉
3表达式$R\bowtie S {t_r^ \frown t_s | t_r \in R \and t_s \in S \and t_r[A] t_s[B] }$
4由自然连接所引发的一系列问题
1悬浮元组在做自然连接的时候被舍弃的元组
2外连接如果把舍弃的元组也保存在结果关系中而在其他属性上填空值(Null)这种连接就叫做外连接外连接 左外连接 右外连接
3左外连接如果只把左边关系R中要舍弃的元组保留就叫做左外连接
4右外连接如果只把右边关系S中要舍弃的元组保留就叫做右外连接
除
1除运算的意义
1假设关系RSRSR关系拥有的属性是姓名S关系拥有的属性是课程RS关系拥有的属性是姓名和课程的联系则RS/S表示选出所有至少选了表S中所列课程的学生的元组。
2如下图 注RS/S得到的关系张三和李四构成的表表示选修了全部课程的同学的集合。
举例
R
ABCa1b1c2a2b3c7a3b4c6a1b2c3a4b6c6a2b2c3a1b2c1
S:
BCDb1c2d1b2c1d1b2c3d2
R÷S
Aa1(1) 找S与R的共同属性即公式中的Y属性 (2)计算R中每个X属性的象集如果某个象集包含S在Y属性上的投影则该属为R/S结果中的一个值。 解答如下
在关系R中A可以取四个值{a1,a2,a3,a4}其中
a1的象集为{b1,c2b2,c3b2,c1}
a2的象集为{b3,c7b2,c3}
a3的象集为{b4,c6}
a4的象集为{b6,c6}
S在B,C上的投影为{(b1,c2),(b2,c3),(b2,c1)}。
显然只有R的象集a1包含S在B,C属性组上的投影所以R÷S{a1}。 数据类型大总结 整数类型 实数类型
定点数DECIMAL和NUMERIC类型在MySQL中视为相同的类型。它们用于保存必须为确切精度的值。
DECIMAL(M,D)其中M表示十进制数字总的个数D表示小数点后面数字的位数。
如果存储时整数部分超出了范围如上面的例子中添加数值为1000.01MySql就会报错不允许存这样的值。如果存储时小数点部分若超出范围就分以下情况若四舍五入后整数部分没有超出范围则只警告但能成功操作并四舍五入删除多余的小数位后保存。如999.994实际被保存为999.99。若四舍五入后整数部分超出范围则MySql报错并拒绝处理。如999.995和-999.995都会报错。
M的默认取值为10D默认取值为0。如果创建表时某字段定义为decimal类型不带任何参数等同于decimal(10,0)。带一个参数时D取默认值。
M的取值范围为1~65取0时会被设为默认值超出范围会报错。
D的取值范围为0~30而且必须M超出范围会报错。
所以很显然当M65D0时可以取得最大和最小值。 浮点数类型
floatdouble和real。他们定义方式为FLOAT(M,D) 、 REAL(M,D) 、 DOUBLE PRECISION(M,D)。 “(M,D)”表示该值一共显示M位整数其中D位位于小数点后面
FLOAT和DOUBLE中的M和D的取值默认都为0即除了最大最小值不限制位数。
M取值范围为0~255。FLOAT只保证6位有效数字的准确性所以FLOAT(M,D)中M6时数字通常是准确的。如果M和D都有明确定义其超出范围后的处理同decimal。
D取值范围为0~30同时必须M。double只保证16位有效数字的准确性所以DOUBLE(M,D)中M16时数字通常是准确的。如果M和D都有明确定义其超出范围后的处理同decimal。
内存中FLOAT占4-byte1位符号位 8位表示指数 23位表示尾数DOUBLE占8-byte1位符号位 11位表示指数 52位表示尾数。 浮点数比定点数类型存储空间少计算速度快但是不够精确。 因为需要计算额外的空间和计算开销所以应该尽量只在对小数进行精确计算时 才使用DECIMAL。但在数据量比较大的情况下可以考虑使用BIGINT代替DECIMAL将需要存储的货币单位根据小数的位数乘以相应的倍数即可。 BIT数据类型
可用来保存位字段值。BIT(M)类型允许存储M位值。M范围为1~64默认为1。
BIT其实就是存入二进制的值类似010110。
如果存入一个BIT类型的值位数少于M值则左补0.
如果存入一个BIT类型的值位数多于M值MySQL的操作取决于此时有效的SQL模式
如果模式未设置MySQL将值裁剪到范围的相应端点并保存裁减好的值。
如果模式设置为traditional(“严格模式”)超出范围的值将被拒绝并提示错误并且根据SQL标准插入会失败。
MySQL把BIT当做字符串类型而非数字类型。 字符串类型
字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。 CHAR VARCHAR CHAR和VARCHAR类型声明的长度表示你想要保存的最大字符数。例如CHAR(30)可以占用30个字符。默认长度都为255。
CHAR列的长度固定为创建表时声明的长度。长度可以为从0到255的任何值。当保存CHAR值时在它们的右边填充空格以达到指定的长度。当检索到CHAR值时尾部的空格被删除掉所以我们在存储时字符串右边不能有空格即使有查询出来后也会被删除。在存储或检索过程中不进行大小写转换。
所以当char类型的字段为唯一值时添加的值是否已经存在以不包含末尾空格可能有多个空格的值确定比较时会在末尾补满空格后与现已存在的值比较。
VARCHAR列中的值为可变长字符串。长度可以指定为0到65,535之间的值实际可指定的最大长度与编码和其他字段有关比如MySql使用utf-8编码格式大小为标准格式大小的2倍仅有一个varchar字段时实测最大值仅21844如果添加一个char(3)则最大取值减少3。整体最大长度是65,532字节。 同CHAR对比VARCHAR值保存时只保存需要的字符数另加一个字节来记录长度(如果列声明的长度超过255则使用两个字节)。 VARCHAR值保存时不进行填充。当值保存和检索时尾部的空格仍保留符合标准SQL。 如果分配给CHAR或VARCHAR列的值超过列的最大长度则对值进行裁剪以使其适合。如果被裁掉的字符不是空格则会产生一条警告。如果裁剪非空格字符则会造成错误(而不是警告)并通过使用严格SQL模式禁用值的插入。 BINARY VARBINARY BINARY和VARBINARY类型类似于CHAR和VARCHAR类型但是不同的是它们存储的不是字符串而是二进制串。所以它们没有编码格式并且排序和比较基于列值字节的数值值。
当保存BINARY值时在它们右边填充0x00(零字节)值以达到指定长度。取值时不删除尾部的字节。比较时所有字节很重要因为空格和0x00是不同的0x00空格包括ORDER BY和DISTINCT操作。比如插入a 会变成a \0。
对于VARBINARY插入时不填充字符选择时不裁剪字节。比较时所有字节很重要。 BLOB TEXT
BLOB是一个二进制大对象可以容纳可变数量的数据。有4种BLOB类型TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它们只是可容纳值的最大长度不同。
有4种TEXT类型TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。这些对应4种BLOB类型有相同的最大长度和存储需求。
BLOB列被视为二进制字符串。TEXT列被视为字符字符串类似BINARY和CHAR。
在TEXT或BLOB列的存储或检索过程中不存在大小写转换。
未运行在严格模式时如果你为BLOB或TEXT列分配一个超过该列类型的最大长度的值值被截取以保证适合。如果截掉的字符不是空格将会产生一条警告。使用严格SQL模式会产生错误并且值将被拒绝而不是截取并给出警告。 在大多数方面可以将BLOB列视为能够足够大的VARBINARY列。同样可以将TEXT列视为VARCHAR列。 BLOB和TEXT在以下几个方面不同于VARBINARY和VARCHAR
当保存或检索BLOB和TEXT列的值时不删除尾部空格。(这与VARBINARY和VARCHAR列相同。
比较时将用空格对TEXT进行扩充以适合比较的对象正如CHAR和VARCHAR。
对于BLOB和TEXT列的索引必须指定索引前缀的长度。对于CHAR和VARCHAR前缀长度是可选的。
BLOB和TEXT列不能有默认值。
BLOB或TEXT对象的最大大小由其类型确定但在客户端和服务器之间实际可以传递的最大值由可用内存数量和通信缓存区大小确定。你可以通过更改max_allowed_packet变量的值更改消息缓存区的大小但必须同时修改服务器和客户端程序。 每个BLOB或TEXT值分别由内部分配的对象表示。
它们TEXT和BLOB同的长度
Tiny最大长度255个字符(2^8-1)
BLOB或TEXT最大长度65535个字符(2^16-1)
Medium最大长度16777215个字符(2^24-1)
LongText 最大长度4294967295个字符(2^32-1)
实际长度与编码有关比如utf-8的会减半。 当BLOB和TEXT值太大时InnoDB会使用专门的外部存储区域来进行存储此时单个值在行内需要1~4个字节存储一个指针然后在外部存储区域存储实际的值。
MySQL会BLOB和TEXT进行排序与其他类型是不同的它只对每个类的最前max_sort_length字节而不是整个字符串进行排序。
MySQL不能将BLOB和TEXT列全部长度的字符串进行索引也不能使用这些索引消除排序。 ENUM 使用枚举代替字符串类型
MySQL在存储枚举时非常紧凑会根据列表值的数量压缩到一个或两个字节中。MySQL在内部将每个值在列表中的位置保存为整数并且在表的.frm文件中保存“数组——字符串”映射关系的查找表。
枚举字段是按照内部存储的整数而不是定义的字符串进行排序的
由于MySQL把每个枚举值都保存为整数并且必须通过查找才能转换为字符串所以枚举列有一定开销。在特定情况下把CHAR/VARCHAR列与枚举列进行JOIN可能会比直接关联CHAR/VARCHAR更慢。 时间和日期类型 DATE, DATETIME, 和TIMESTAMP类型 这三者其实是关联的都用来表示日期或时间。
当你需要同时包含日期和时间信息的值时则使用DATETIME类型。MySQL以YYYY-MM-DD HH:MM:SS格式检索和显示DATETIME值。支持的范围为1000-01-01 00:00:00到9999-12-31 23:59:59。
当你只需要日期值而不需要时间部分时应使用DATE类型。MySQL用YYYY-MM-DD格式检索和显示DATE值。支持的范围是1000-01-01到 9999-12-31。 TIMESTAMP类型同样包含日期和时间范围从1970-01-01 00:00:01 UTC 到2038-01-19 03:14:07 UTC。
TIME值的范围可以从-838:59:59到838:59:59。小时部分会因此大的原因是TIME类型不仅可以用于表示一天的时间(必须小于24小时)还可能为某个事件过去的时间或两个事件之间的时间间隔(可以大于24小时或者甚至为负) 两者的存储方式不一样
对于TIMESTAMP它把客户端插入的时间从当前时区转化为UTC世界标准时间进行存储。查询时将其又转化为客户端当前时区进行返回。
而对于DATETIME不做任何改变基本上是原样输入和输出。 YEAR类型是一个单字节类型用于表示年。
MySQL以YYYY格式检索和显示YEAR值。范围是1901到2155。 关系数据库标准语言SQL
基本概念 SQL语言是一个功能极强的关系数据库语言。同时也是一种介于关系代数与关系演算之间的结构化查询语言Structured Query Language其功能包括数据定义、数据查询、数据操纵和数据控制。 SQL的特点 1综合统一集数据定义、数据查询、数据操纵和数据控制等多种功能于一体。 2高度非过程化 面对象的设计 3面向集合的操作方式 操作对象是集合并且操作结果也是集合 4两种使用方式统一的语法结构 既是一种独立的语言又是一种嵌入式的语言嵌入式是指嵌入别的高级语言。 5简洁易学
数据库的创建与基本概念
一、创建数据库
代码
create database Student; --创建数据库
use Student; --使用数据库
drop database Student; --删除数据库
注意
1两种注释方式1两个减号--注释单行 2/* */注释多行
2不能再当前数据库删除当前数据库
数据类型 注意
1一个属性采用何种数据类型由两部分决定1该属性的取值范围2该属性做何种运算。
模式的创建与删除
模式一个独立于数据库用户的非重复命名空间在这个空间中可以定义该模式包含的数据库对象例如基本表、视图、索引等。
代码
/** 创建模式zhang下键表student*/
create schema zhangcreate table student(Sno char(9) primary key,Sname varchar(20) unique,Ssex char(4) not null,Sage smallint,Sdept varchar(5) );/** 删除模式中的表*/
drop table zhang.student;/** 删除模式*/
drop schema zhang; --注意前提该模式下无对象
注意
1删除模式的时候首先应当将模式下的所有对象删除才能删除该模式
2在删除某个非dbo模式下的表时需要加模式名
3该模式不是三级模式两级映像中的模式而是相当于一个命名空间主要可以解决重名的问题
4CASCADE(级联)删除模式的同时把该模式中所有的数据库对象全部删除SQL Server不支持
5RESTRICT(限制)只有当该模式中没有任何下属的对象时才能执行
表的定义、删除与修改
一、创建表三张1学生表Student2课程表Course3学生课程表SC
1学生表Student 代码
/** 未添加数据*/
create table student
(Sno char(9) primary key, --primary key 指示主码Sname varchar(20) unique, --unique 指示值唯一Ssex char(4) not null, --not null 该值非空Sage smallint,Sdept varchar(5)
);
2课程表Course 代码
/** 创建课程表*/
create table Course
(Cno char(2) primary key,Cname varchar(10) unique,Cpno char(2), --Cpno是外码参照的是自身的CnoCcredit smallint,foreign key (Cpno) references Course(Cno) --外码
);
3学生-课程表 代码
/** 创建学生-课程表*/
create table SC
(Sno char(9),Cno char(2),Grade int,primary key(Sno, Cno), --多个属性列构成主码写在最后foreign key(Sno) references student(Sno), --外码 每个外码写一行foreign key(Cno) references Course(Cno)
);
注意
1创建表的时候需要考虑三个完整性约束条件实体完整性参照完整性用户自定义完整性
2两种完整性约束条件的定义方式 列级完整性约束条件涉及相应属性列的完整性约束条件在属性列的后边定义。 表级完整性约束条件涉及一个或多个属性列的完整性约束条件 在将属性列完之后定义。
3外码要和所参照的主码类型相同。表级完整性约束的时候属性列需要加括号。
二、修改表
增加列
alter table student add graduation date;
/*
1. 指定要修改的表
2. add关键字
3. 新增列的属性名
4. 新增列的数据类型
*/
删除列
alter table student drop column graduation;
修改列的数据类型
alter table student alter column graduation varchar(20);
增加约束
/*这种增加约束的方法不容易从左边的框框键中看出来*/
alter table student add unique(graduation);/*给增加的约束自定义了一个别名容易区分*/
alter table student add constraint S_un unique(graduation);/*注意*/
--1. 不可以使用增加not null约束想要添加只可以在设计中将勾去掉
--虽然以下的方式看似添加了not null约束但是不起任何作用
alter table student add constraint cc check(sname is not null);--2. 给某一属性列添加主键需要保证该属性列不允许为空刚建的新表在未加约束的情况下默认属性列允许为空值
alter table student add primary key(sno,cno);--3. 添加外键需要保证外码和被参照表的主属性的数据类型保持一致
alter table student add foreign key (sno) references student(sno);
删除约束
/*通过指定的约束名字删除指定的约束*/
alter table student drop constraint S_un;/*在左边单机右键删除*/
三、删除表
/*删除表的时候必须先将参照表干掉再删除被参照表*/
drop table student
索引的建立与删除 建立索引的目的是加快数据查询的速度。DBA或者表的属主可以根据需要建立表的索引但是有些DBMS可以自动建立以下索引1PRIMARY KEY索引聚簇索引2UNIQUE索引唯一性索引 一、创建索引
/*创建唯一性索引*/
/** stu为索引名字创建索引必须要有一个索引名* 列名后面紧跟排序类型ASC为升序DESC为降序默认为ASC可以有多个列用逗号隔开。* 对于已经包含重复值的属性列不可以增加唯一性索引
*/
create unique index S_nn on student(graduation asc);/*创建聚簇索引聚集*/
Create clustered index stu on student(sage desc);
/** 聚簇索引的关键字为clustered,不是书上有误而是sqlserver是这样* 同样列名后面紧跟排序类型可以有多个列用逗号隔开。* 聚簇索引严格按照物理存储位置来排序。* 不可以在有主键的表中创建索引* 一个表只能创建一个聚簇索引
*/
二、删除索引
/*注意删除索引必须为表名索引名*/
drop index student.stu
sql查询 单表查询
简单的查询操作
--投影select后边指明所选的列from指明所访问的表
select sno, sname, sdept
from student;--选择指定的列可以加算术表达式并且为其添加新的属性名
select sno, 2019-sage as birthday
from student;--投影后修改属性名
select sno num, 2019-sage birthday
from student;--*代表选中所有列
select *
from student;--除了intsmallint其余的数据类型需要单引号
select sname,2017 year
from student;--字符串的拼接
--5)查询全体学生的姓名、联系电话并在前面加上字符串‘联系方式’
select sname, 联系方式tel
from student;--select后加函数
--count函数空值不计重复值重复计
--当count函数作用在全部列上时以元组计数
select COUNT(sno)
from student;--COUNT的含义是计数*表示所有列COUNT*表示元组数某个或部分属性列为空值不影响count统计结果
select COUNT(*)
from student;--去重distinct作用域是整个元组是所有指定列组成的元组的去重
select distinct sno, cno
from sc;--查询性别为女的学生的学号姓名
select sno, sname
from student
where ssex 女;--查询学分为4学分的课程的名字
select cname
from course
where ccredit 4;--查询成绩在85分以上的学生的学号学号不重
select distinct sno
from sc
where grade 85;--查询年龄在20~23岁包括20岁和23岁之间的学生的姓名、系别和年龄。
SELECT Sname,Sdept,Sage
FROM Student
WHERE Sage BETWEEN 20 AND 23;--不能写成sdeptCS,IS,MA
select sname,ssex
from student
where sdeptCS or sdeptIS or sdept MA;--IS NULL IS NOT NULL空值只能用“is”不能用“”
--WHERE NOT Sage 20not必须在 sage前边而不是前边select sname,ssex
from student
where sdept in (CS,IS,MA);--模糊查询
--%任意长度_单个字符__表示两个或两个以内
--转义字符\需要加escape \标注
select *
from student
where sname like 刘__;select * --如果字符中本身带有下划线用任意字符当转义字符
from Course
where Cname like DB\_%i_ _ escape \;
order by子句
--order by子句
--选择sno列从sc表中cno为3按成绩降序给出
--desc表示降序排列asc表示升序排列当缺省的时候表示asc
--在SqlServer中当排序的属性列中存在空值的时候升序排列默认空值在元组最先显示desc降序空值元组在最后显示
select sno
from sc
where cno 3
order by grade desc;--多属性列排序首先按ccredit进行升序排列当ccredit相等的时候按cpno进行降序排列
select *
from course
order by ccredit, cpno desc; 注意 首先将符合where子句的元组筛选出来然后根据order by子句进行排序。聚集函数
--count统计sc表中sno的数目空值不计重复值重复计
--distinct关键字在计算式取消重复列中的重复值
select count (distinct sno)
from sc;--统计元组的数目
select count(*)
from sc;--求该列值的总和
select sum (grade)
from sc;--求平均值结果向下取整
select AVG (grade)
from sc;--求最小
select min (grade)
from sc;--求最大
select max (grade)
from sc;
注意
聚集函数全部都忽略空值where子句中不能使用聚集函数作为条件表达式聚集函数只能用在select子句或者group by中的having子句。聚集函数作用的元组是满足where子句中的条件的元组
group by子句
--GROUP BY
--在有GROUP BY的语句中select子句后边只可以出现分组属性列或者聚集函数其他列名不可以
--平均值计算略过空值
--首先按cno进行分组分别统计每组中sno的数量和每组中的平均值最后给每一新列起别名
select cno, count(sno) cnt,AVG (grade) av
from sc
group by cno;--可以使用HAVING短语筛选最终输出结果,作用于组从中选择满足条件的组
--同上首先通过cno分组在通过having语句选出满足指定条件的组
select cno, count(sno) cnt, AVG (grade) av
from sc
group by cno
having COUNT(sno)2;--查询选修了3门以上课程的学生学号
--首先使用group by进行分组然后使用having选择满足条件的组
select sno,COUNT(cno)
from sc
group by sno
having COUNT(cno)3
注意
where子句作用于基表或视图从中选择满足条件的元组。having短语作用于组从中选择满足条件的元组使用group by子句后select子句的列名列表中只能出现分组属性和聚集函数
连接查询
基本概念 连接谓词中的列名称为连接字段 连接条件中的各连接字段类型必须是可比的但不必是相同的 SQL没有自动去掉重复列的功能
基本操作
--from涉及两个表不加连接条件得到的是广义的笛卡尔积select后跟的是最终显示的列
select student.*,sc.*
from student,sc;--加上连接条件得到的是从广义笛卡尔积中选择满足指定条件的元组
--select后跟的是最终所显示的列对于两个表公共的属性列需要使用表名进行区分不属于公共列的不需要
--SqlServer没有自动去掉重复列的功能
select student.*,cno,grade --去掉重复列
from student,sc
where student.snosc.sno; --连接条件不然是广义笛卡尔积--或者--
select sc.sno,sname,sage,ssex,sdept,cno,grade --去掉重复列
from student,sc
where student.snosc.sno; 一种可能的执行过程 1首先在表1中找到第一个元组然后从头开始扫描表2逐一查找满足连接条件的元组找到后就将表1中的第一个元组与该元组拼接起来形成结果表中一个元组 。 2表2全部查找完后再找表1中第二个元组然后再从头开始扫描表2逐一查找满足连接条件的元组找到后就将表1中的第二个元组与该元组拼接起来形成结果表中一个元组。 3重复上述操作直到表1中的全部元组都处理完毕。 自身连接
select first.cno, second.cpno
from course first, course second
where first.cpno second.cno;
注意
由于两张表的所有属性列的名字相同所以需要起别名进行加以区分。上述代码表示将第一张自己表和第二张自己表做广义笛卡尔积然后选择第一张自己表的cpno等于第二张自己的cno的元组对应的属性列。
外连接
--外连接
select sc.sno,sname,sage,ssex,sdept,cno,grade
from student full outer join sc
on student.sno sc.sno;--左外连接
select sc.sno,sname,sage,ssex,sdept,cno,grade
from student left outer join sc
on student.sno sc.sno;--右外连接
select sc.sno,sname,sage,ssex,sdept,cno,grade
from student right outer join sc
on student.sno sc.sno; 注意 原先的条件where变为on表名后的外连接操作符指明了主体表。嵌套查询
基本概念
查询块一个select-from-where语句
嵌套查询将一个查询块嵌套在另一个查询块的where子句或having短语的条件中的查询
子查询不能使用order by子句因为嵌套查询返回的是一个集合或者布尔值排序没有任何意义所以规定不能使用order by语句胡扯
一些嵌套查询可以使用连接查询代替但是一些不可以。
不相关子查询子查询的查询条件不依赖于父查询
相关子查询子查询的查询条件依赖于父查询
不相关子查询的可能执行过程由里向外逐层处理。即每个子查询在上一级查询处理之前求解子查询的结果用于建立其父查询的查找条件。
相关子查询可能的执行过程1首先取外层查询中表的第一个元组根据它与内层查询相关的属性值处理内层查询若where子句返回值为真则取此元组放入结果表2然后再取外层表的下一个元组3重复这一过程直至外层表全部检查完为止。
带有IN谓词的子查询
一个典型的例子 该查询为不相关子查询即查询过称为1在course表中查找出信息系统的课程号2根据查找出的课程号在sc表中查询出该学生的学号3根据查询到的学号在student表中查询出相应学生的姓名。
带有比较运算符的子查询
适用条件当能确切知道内层查询返回单值时可用比较运算符!或
例如
找出每个学生超过他选修课程平均成绩的课程号。 SELECT Sno, CnoFROM SC xWHERE Grade (SELECT AVG(Grade) FROM SC yWHERE y.Sno x.Sno);
查询过程 该例为一个相关子查询。
带有any或者all谓词的子查询
声明
any表示任意一个就行 any表示大于任意一个就可以
all表示所有 all表示需要大于所有的值
常见的谓词解释 带有EXISTS谓词的子查询
介绍
存在量词
exists
1不返回任何数据只返回true或者false。当内层的查询非空时返回true当内层的查询为空时返回false。
2由EXISTS引出的子查询其目标列表达式通常都用*因为带EXISTS的子查询只返回真值或假值给出列名无实际意义还是胡扯
not exists
1若内层查询结果非空则外层的WHERE子句返回假值
2若内层查询结果为空则外层的WHERE子句返回真值
例子
exists的例子 not exists的例子 难点1使用exists/not exists实现全称量词
1查询选修了全部课程的学生姓名
--说法转换即对于某个学生来说没有哪一门课程使自己没有选的
select sname
from student
where not exists(select *from coursewhere not exists(select s*from scwhere student.sno sno and cno course.cno));
解释
1对于第一个not exists里边查询的是当前student是否有未选修的课程如果当前学生有未选修的课程经过not exists返回false即该学生的信息不会被记录。
2对于第二个not exists里边查询的是当前学生对象对于当前的课程如果选了该门课程not exists里边为真经过not exists返回false该门课程不会被记录反之如果该学生未选该门课程该门课程将会被记录。
3有一点像双重for循环依次遍历所有的student中的元组在每一个student的情况下在遍历course最后在一个not exists中的where子句中进行判断。
难点2使用exists/not exists实现逻辑蕴涵
2查询至少选修了学生201215122选修的全部课程的学生号码。
SELECT DISTINCT Sno
FROM SC SCX
WHERE NOT EXISTS(SELECT *FROM SC SCYWHERE SCY.Sno 201215122 ANDNOT EXISTS(SELECT *FROM SC SCZWHERE SCZ.SnoSCX.Sno AND SCZ.CnoSCY.Cno));
解释
1基本同上
集合查询
并操作
查询计算机科学系的学生及年龄不大于19岁的学生。
/*使用UNION取并集*/
SELECT *
FROM Student
WHERE Sdept CS
UNION
SELECT *
FROM Student
WHERE Sage19
交操作
查询计算机科学系的学生与年龄不大于19岁的学生的交集(INTERSECT)。
/*使用INTERSECT实现交操作*/
SELECT *
FROM Student
WHERE SdeptCS
INTERSECT
SELECT *
FROM Student
WHERE Sage19
差操作
查询计算机科学系的学生与年龄不大于19岁的学生的差集。
/*使用EXCEPT实现差操作*/
SELECT *
FROM Student
WHERE SdeptCS
EXCEPT
SELECT *
FROM Student
WHERE Sage 19;
sql增删改
数据的插入
插入元祖
--1. 表名后没有指定属性列表示要插入的是一条完整的元组且属性列属性与表定义中的顺序一致
insert into student
values (201215128, 陈东, 18, 男, IS);--2. 在表明后指定要插入数据的表名及属性列属性列的顺序可与表定义中的顺序不一致
insert into student(sno, sname, sage, ssex, sdept)
values (201215138, 陈东栋, 18, 男, CS);--3. 插入部分列未显示给出的列按空值计算当然前提条件是那些列可以为空值
insert into student(sno, sname)
values (201215148, 陈栋);
2. 插入一个子查询的结果
--子查询的结果必须包含和insert的字段列表一样多的字段并且数据类型兼容
insert into depavgselect sdept,AVG(sage) avgagefrom studentgroup by sdept;
3.5.2 数据的修改
--1. 修改某些符合where子句中的条件的元组的值
update student
set sage 92
where sno 200215121;--2. where子句缺省默认修改所有元组的该属性的值
--注意在修改数据的时候应当先写where子句中的条件
update student
set sage 92;--3. 带子查询的修改
update sc
set grade 100
where CS in (select sdeptfrom studentwhere sc.sno student.sno
);--set子句中遇到null只能用等号where子句中只能用is null
update student
set sage null
where sno 201811012; 注意 DBMS在执行修改语句时会检查修改操作是否破坏表上已定义的完整性规则。 实体完整性保证主码不能被修改用户自定义完整性not null约束unique约束值域约束等。3.5.3 数据的删除
--1. 删除符合where子句中条件的某些行
delete
from student
where sno 201215148;--2. 带子查询的删除
delete
from sc
where CS in (select sdeptfrom studentwhere sc.sno student.sno
);--3. 删除所有行
delete
from student; 注意 同数据更新结果很危险操作需谨慎。 mysql常用函数总结
文本处理函数
Left(x,len) – 返回串左边的字符长度为len
Right(x,len)
Length(x) – 返回串的长度
Locate(x,sub_x) – 找出串的一个子串
SubString(x, from, to) – 返回字串的字符
Lower(x)
Upper(x)
LTrim(x)
RTrim(x)
Soundex(x) – 读音用于发音匹配
SELECT cust_name, cust_contact FROM customers WHERE Soundex(cust_contact) Soundex(‘Y Lie’);
日期和时间处理函数
日期和时间采用相应的数据类型和特殊的格式存储以便可以快速和有效的排序或过滤节省物理存储空间.
一般应用程序不使用用来存储日期和时间的格式因此日期和时间函数总是被用来读取、统计和处理这些函数.
常用日期和时间处理函数
AddDate() – 增加一个日期天周等
AddTime() – 增加一个时间时分等
CurDate() – 返回当前日期
CurTime() – 返回当前时间
Date() – 返回日期时间的日期部分
DateDiff() – 计算两个日期之差
Date_Add() – 日期运算函数
Date_Format() – 返回一个格式化的日期或时间串
Day() – 返回一个日期的天数部分
DayOfWeek() – 返回日期对应的星期几
Hour() – 返回一个时间的小时部分
Minute() – 返回一个时间的分钟部分
Second() – 返回一个时间的秒部分
Month() – 返回一个日期的月部分
Now() – 返回当前日期和时间
Time() – 返回一个日期时间的时间部分
Year() – 返回一个日期的年份部分
日期首选格式 yyyy-mm-dd; 如2005-09-01
检索某日期下的数据
SELECT cust_id, order_num FROM orders WHERE Date(order_date) ‘2005-09-01’;
检索某月或日期范围内的数据
SELECT cust_id, order_num FROM orders WHERE Year(order_date) 2005 AND Month(order_date) 9;
– or
SELECT cust_id, order_num FROM orders WHERE date(order_date) BETWEEN ‘2005-09-01’ AND ‘2005-09-30’;
数值处理函数
代数、三角函数、几何运算等
常用数值处理函数
abs(); cos(); exp(); mod()取余; Pi(); Rand(); Sin(); Sqrt(); Tan(); 视图/存储过程/触发器
视图
视图是虚拟的表与包含数据的表不同视图只包含使用时动态检索数据的查询,主要是用于查询。
为什么使用视图
重用sql语句简化复杂的sql操作在编写查询后可以方便地重用它而不必知道他的基本查询细节。使用表的组成部分而不是整个表。保护数据。可以给用户授予表的特定部分的访问权限而不是整个表的访问权限。更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据。
注意
在视图创建之后可以用与表基本相同的方式利用它们。可以对视图执行select操作过滤和排序数据将视图联结到其他视图或表甚至能添加和更新数据。重要的是知道视图仅仅是用来查看存储在别处的数据的一种设施。视图本身不包含数据因此它们返回的数据时从其他表中检索出来的。在添加和更改这些表中的数据时视图将返回改变过的数据。因为视图不包含数据所以每次使用视图时都必须处理查询执行时所需的任一检索。如果你使用多个联结和过滤创建了复杂的视图或者嵌套了视图可能会发现性能下降得很厉害。因此在部署使用了大量视图的应用前应该进行测试。
视图的规则和限制
与表一样视图必须唯一命名可以创建任意多的视图为了创建视图必须具有足够的访问权限。这些限制通常由数据库管理人员授予。视图可以嵌套可以利用从其他视图中检索数据的查询来构造一个视图。Order by 可以在视图中使用但如果从该视图检索数据select中也是含有order by那么该视图的order by 将被覆盖。视图不能索引也不能有关联的触发器或默认值视图可以和表一起使用
视图的创建
利用create view 语句来进行创建视图使用show create view viewname来查看创建视图的语句用drop view viewname 来删除视图更新视图可以先drop在create也可以使用create or replace view。
视图的更新
视图是否可以更新要视情况而定。
通常情况下视图是可以更新的可以对他们进行insertupdate和delete。更新视图就是更新其基表(视图本身没有数据)。如果你对视图进行增加或者删除行实际上就是对基表进行增加或者删除行。
但是如果MySQL不能正确的确定更新的基表数据则不允许更新(包括插入和删除)这就意味着视图中如果存在以下操作则不能对视图进行更新(1)分组(使用group by 和 having )(2)联结(3)子查询(4)并(5)聚集函数;(6)dictinct;(7)导出(计算)列。 存储过程
存储过程就是为了以后的使用而保存的一条或者多条MySQL语句的集合。可将视为批文件虽然他们的作用不仅限于批处理。
为什么使用储存过程
1.通过把处理封装在容易使用的单元中简化复杂的操作 2.由于不要求反复建立一系列处理步骤保证了数据的完整性。如果所有开发人员和应用程序都使用同一(实验和测试)存储过程则所使用的代码都是相同的。这一点的延伸就是防止错误。需要执行的步骤越多出错的可能性就越大防止错误保证了数据的一致性。 3.简化对变动的管理如果表名。列名或者业务逻辑等有变化只需要更改存储过程的代码。使用它的人员甚至不需要知道这些变化。这一点延伸就是安全性通过存储过程限制对基数据的访问减少了数据讹误的机会。 4.提高性能。因为使用存储过程比使用单独的sql语句更快。 5.存在一些只能用在单个请求的MySQL元素和特性存储过程可以使用他们来编写功能更强更灵活的代码 综上
三个主要的好处简单、安全、高性能。
两个缺陷
1、存储过程的编写更为复杂需要更高的技能更丰富的经验。
2、可能没有创建存储过程的安全访问权限。许多数据库管理员限制存储过程的 创建权限允许使用不允许创建。
执行存储过程
Call关键字Call接受存储过程的名字以及需要传递给他的任意参数。存储过程可以显示结果也可以不显示结果。
CREATE PROCEDURE productpricing() BEGIN SELECT AVG( prod_price) as priceaverage FROM products; END;
创建名为productpricing的储存过程。如果存储过程中需要传递参数则将他们在括号中列举出来即可。括号必须有。BEGIN和END关键字用来限制存储过程体。上述存储过程体本身是一个简单的select语句。注意这里只是创建存储过程并没有进行调用。 储存过程的使用 Call productpring() 使用参数的存储过程
一般存储过程并不显示结果而是把结果返回给你指定的变量上。
变量内存中一个特定的位置用来临时存储数据。
MySQL CREATE PROCEDURE prod(out pl decimal(8,2),out ph decimal(8,2),out pa decimal(8,2))
beginselect Min(prod_price) into pl from products;select MAx(prod_price) into ph from products;select avg(prod_price) into pa from products;end;call PROCEDURE(pricelow,pricehigh,priceaverage);select pricelow;select pricehigh;select pricelow,pricehigh,priceaverage; 解释
此存储过程接受3个参数pl存储产品最低价ph存储产品最高价pa存储产品平均价。每个参数必须指定类型使用的为十进制关键字OUT 指出相应的参数用来从存储过程传出一个值(返回给调用者)。 MySQL支持in(传递给存储过程)、out(从存储过程传出这里所用)和inout(对存储过程传入和传出)类型的参数。存储过程的代码位于begin和end语句内。他们是一系列select语句用来检索值。然后保存到相对应的变量(通过INTO关键字)。
存储过程的参数允许的数据类型与表中使用的类型相同。注意记录集是不被允许的类型因此不能通过一个参数返回多个行和列这也是上面为什么要使用3个参数和3条select语句的原因。 调用为调用此存储过程必须指定3个变量名。如上所示。3个参数是存储过程保存结果的3个变量的名字。调用时语句并不显示任何数据它返回以后可以显示的变量(或在其他处理中使用)。 注意所有的MySQL变量都是以开头。
CREATE PROCEDURE ordertotal(IN innumber int,OUT outtotal decimal(8,2))BEGINSELECT Sum(item_price * quantity) FROM orderitems WHERE order_num innumber INTO outtotal;end //CALL ordertotal(20005,total);select total; // 得到20005订单的合计CALL ordertotal(20009,total);select total; //得到20009订单的合计 带有控制语句的存储过程
CREATE PROCEDURE ordertotal(IN onumber INT,IN taxable BOOLEAN,OUT ototal DECIMAL(8,2))COMMENT Obtain order total, optionally adding taxBEGIN-- declear variable for totalDECLARE total DECIMAL(8,2);-- declear tax percentageDECLARE taxrate INT DEFAULT 6;-- get the order totalSELECT Sum(item_price * quantity) FROM orderitems WHERE order_num onumber INTO total;-- IS this taxable?IF taxable THEN-- yes ,so add taxrate to the totalSELECT total(total/100*taxrate)INTO total;END IF;-- finally ,save to out variableSELECT total INTO ototal;END;
在存储过程中我们使用了DECLARE语句他们表示定义两个局部变量DECLARE要求指定变量名和数据类型。它也支持可选的默认值(taxrate默认6%)因为后期我们还要判断要不要增加税所以我们把SELECT查询的结果存储到局部变量total中然后在IF 和THEN的配合下检查taxable是否为真然后在真的情况下我们利用另一条SELECT语句增加营业税到局部变量total中然后我们再利用SELECT语句将total(增加税或者不增加税的结果)保存到总的ototal中。
COMMENT关键字 上面的COMMENT是可以给出或者不给出如果给出将在SHOW PROCEDURE STATUS的结果中显示。 触发器
在某个表发生更改时自动处理某些语句这就是触发器。 触发器是MySQL响应delete 、update 、insert 、位于begin 和end语句之间的一组语句而自动执行的一条MySQL语句。其他的语句不支持触发器。
创建触发器
在创建触发器时需要给出4条语句规则
1. 唯一的触发器名
2. 触发器关联的表
3. 触发器应该响应的活动
4. 触发器何时执行(处理之前或者之后) Create trigger 语句创建 触发器
CREATE TRIGGER newproduct AFTER INSERT ON products FOR EACH ROW SELECT Product added INTO info;
CREATE TRIGGER用来创建名为newproduct的新触发器。触发器可以在一个操作发生前或者发生后执行这里AFTER INSERT 是指此触发器在INSERT语句成功执行后执行。这个触发器还指定FOR EACH ROW 因此代码对每个插入行都会执行。文本Product added 将对每个插入的行显示一次。 注意
1、触发器只有表才支持视图临时表都不支持触发器。
2、触发器是按照每个表每个事件每次地定义每个表每个事件每次只允许一个触发器因此每个表最多支持六个触发器(insertupdatedelete的before 和after)。
3、单一触发器不能与多个事件或多个表关联所以你需要一个对insert和update 操作执行的触发器则应该定义两个触发器。
4、触发器失败如果before 触发器失败则MySQL将不执行请求的操作此外如果before触发器或者语句本身失败MySQL则将不执行after触发器。
触发器类别
INSERT触发器
是在insert语句执行之前或者执行之后被执行的触发器。
1、在insert触发器代码中可引入一个名为new的虚拟表访问被插入的行
2、在before insert触发器中new中的值也可以被更新(允许更改被插入的值)
3、对于auto_increment列new在insert执行之前包含0在insert执行之后包含新的自动生成值
CREATE TRIGGER neworder AFTER INSERT ON orders FOR EACH ROW SELECT NEW.order_num;
创建一个名为neworder的触发器按照AFTER INSERT ON orders 执行。在插入一个新订单到orders表时MySQL生成一个新的订单号并保存到order_num中。触发器从NEW.order_num取得这个值并返回它。此触发器必须按照AFTER INSERT执行因为在BEFORE INSERT语句执行之前新order_num还没有生成。对于orders的每次插入使用这个触发器总是返回新的订单号。
DELETE触发器
Delete触发器在delete语句执行之前或者之后执行。
1、在delete触发器的代码内,可以引用一个名为OLD的虚拟表用来访问被删除的行。
2、OLD中的值全为只读不能更新。
CREATE TRIGGER deleteorder BEFORE DELETE ON orders FOR EACH ROWBEGININSERT INTO archive_orders(order_num,order_date,cust_id) values (OLD.order_num,OLD.order_date,OLD.cust_id);END;----------------------------------------------------------------CREATE TABLE archive_orders(order_num int(11) NOT NULL AUTO_INCREMENT,order_date datetime NOT NULL,cust_id int(11) NOT NULL,PRIMARY KEY (order_num),KEY fk_orders1_customers1 (cust_id),CONSTRAINT fk_orders1_customers1 FOREIGN KEY (cust_id) REFERENCES customers(cust_id)) ENGINEInnoDB AUTO_INCREMENT20011 DEFAULT CHARSETutf8
在任意订单被删除前将执行此触发器它使用一条INSERT 语句将OLD中的值(要被删除的订单) 保存到一个名为archive_orders的存档表中(为实际使用这个例子我们需要用与orders相同的列创建一个名为archive_orders的表) 使用BEFORE DELETE触发器的优点(相对于AFTER DELETE触发器来说)为如果由于某种原因订单不能存档delete本身将被放弃。 我们在这个触发器使用了BEGIN和END语句标记触发器体。这在此例子中并不是必须的只是为了说明使用BEGIN END 块的好处是触发器能够容纳多条SQL 语句(在BEGIN END块中一条挨着一条)。
UPDATE触发器
在update语句执行之前或者之后执行
1、在update触发器的代码内,可以引用一个名为OLD的虚拟表用来访问以前(UPDATE语句之前)的值引用一个名为NEW的虚拟表访问新更新的值。
2、在BEFORE UPDATE触发器中NEW中的值可能也被用于更新(允许更改将要用于UPDATE语句中的值)
3、OLD中的值全为只读不能更新。
CREATE TRIGGER updatevendor BEFORE UPDATE ON vendors FOR EACH ROW SET NEW.vend_state Upper(NEW.vemd_state);
保证州名缩写总是大写(不管UPFATE语句中是否给出了大写)每次更新一行时NEW.vend_state中的值(将用来更新表行的值)都用Upper(NEW.vend_state)替换。
总结
1、通常before用于数据的验证和净化(为了保证插入表中的数据确实是需要的数据) 也适用于update触发器。
2、与其他DBMS相比MySQL 5中支持的触发器相当初级未来的MySQL版本中估计会存在一些改进和增强触发器的支持。
3、创建触发器可能需要特殊的安全访问权限但是触发器的执行时自动的如果insertupdate或者delete语句能够执行则相关的触发器也能执行。
4、用触发器来保证数据的一致性(大小写格式等)。在触发器中执行这种类型的处理的优点就是它总是进行这种处理而且透明的进行与客户机应用无关。
5、触发器的一种非常有意义的使用就是创建审计跟踪。使用触发器把更改(如果需要甚至还有之前和之后的状态)记录到另外一个表是非常容易的。
6、MySQL触发器不支持call语句无法从触发器内调用存储过程。 数据库恢复
实现技术 恢复操作的基本原理冗余 恢复机制涉及的两个关键问题
如何建立冗余数据 数据转储backup登录日志文件logging 如何利用这些冗余数据实施数据库恢复数据转储 数据转储定义
转储是指DBA将整个数据库复制到其他存储介质上保存起来的过程备用的数据称为后备副本或后援副本
如何使用 数据库遭到破坏后可以将后备副本重新装入重装后备副本只能将数据库恢复到转储时的状态转储方法 静态转储与动态转储海量转储与增量转储
静态转储
1定义在系统中无事务运行时进行的转储操作。转储开始的时刻数据库处于一 致性状态而转储不允许对数据库的任何存取、修改活动。静态转储得到的一定是一个数据一致性的副本。
2优点实现简单
3缺点降低了数据库的可用性
转储必须等待正运行的用户事务结束才能进行新的事务必须等待转储结束才能执行
动态转储 1定义转储期间允许对数据库进行存取或修改。转储和用户事务可以并发执行。 2优点不用等待正在运行的用户事务结束不会影响新事务的运行。 3实现必须把转储期间各事务对数据库的修改活动登记下来建立日志文件后备副本加上日志文件就能把数据库恢复到某一时刻的正确状态。
海量转储 1定义每次转储全部数据库 2特点从恢复角度使用海量转储得到的后备副本进行恢复更方便一些。
增量转储 1定义每次只转储上一次转储后更新过的数据 2特点如果数据库很大事务处理又十分频繁则增量转储方式更实用更有效。 日志文件 1、什么是日志文件
日志文件(log)是用来记录事务对数据库的更新操作的文件
2、日志文件的格式
1以记录为单位
日志文件中需要登记的内容包括 各个事务的开始标记(BEGIN TRANSACTION)各个事务的结束标记(COMMIT或ROLLBACK)各个事务的所有更新操作以上均作为日志文件中的一个日志记录
每个日志记录的内容
事务标识标明是哪个事务 操作类型插入、删除或修改操作对象记录内部标识更新前数据的旧值对插入操作而言此项为空值更新后数据的新值对删除操作而言, 此项为空值2以数据块为单位
日志记录内容包括
事务标识标明是哪个事务 被更新的数据块
3、日志文件的作用
进行事务故障恢复进行系统故障恢复协助后备副本进行介质故障恢复
1事务故障恢复和系统故障恢复必须用日志文件
2在动态转储方式中必须建立日志文件后备副本和日志文件结合起来才能有效地恢复数据库
3静态转储方式中也可以建立日志文件重新装入后备副本然后利用日志文件把已完成的事务进行重做对未完成事务进行撤销 4、登记日志文件
基本原则 登记的次序严格按并行事务执行的时间次序必须先写日志文件后写数据库
为什么要先写日志文件
1写数据库和写日志文件是两个不同的操作在这两个操作之间可能发生故障
2如果先写了数据库修改而在日志文件中没有登记下这个修改则以后就无法恢复这个修改了
3如果先写日志但没有修改数据库按日志文件恢复时只不过是多执行一次不必要的UNDO操作并不会影响数据库的正确性 恢复策略 事务故障的恢复
事务故障事务在运行至正常终止点前被终止恢复方法 由恢复子系统应利用日志文件撤消UNDO此事务已对数据库进行的修改事务故障的恢复由系统自动完成对用户是透明的不需要用户干预事务故障的恢复步骤
1. 反向扫描文件日志查找该事务的更新操作。
2. 对该事务的更新操作执行逆操作。即将日志记录中“更新前的值” 写入数据库。 插入操作 “更新前的值”为空则相当于做删除操作 删除操作“更新后的值”为空则相当于做插入操作 若是修改操作则相当于用修改前值代替修改后值
3. 继续反向扫描日志文件查找该事务的其他更新操作并做同样处理。
4. 如此处理下去直至读到此事务的开始标记事务故障恢复就完成了。
系统故障的恢复
系统故障造成数据库不一致状态的原因 未完成事务对数据库的更新已写入数据库已提交事务对数据库的更新还留在缓冲区没来得及写入数据库恢复方法 Undo 故障发生时未完成的事务Redo 已完成的事务系统故障的恢复由系统在重新启动时自动完成不需要用户干预系统故障的恢复步骤
1. 正向扫描日志文件 重做(REDO) 队列: 在故障发生前已经提交的事务 这些事务既有BEGIN TRANSACTION记录也有COMMIT记录撤销 (Undo)队列: 故障发生时尚未完成的事务 这些事务只有BEGIN TRANSACTION记录无相应的COMMIT记录
2. 对撤销(Undo)队列事务进行撤销(UNDO)处理 反向扫描日志文件对每个UNDO事务的更新操作执行逆操作
3. 对重做(Redo)队列事务进行重做(REDO)处理 正向扫描日志文件对每个REDO事务重新执行登记的操作
介质故障的恢复
恢复步骤
重装数据库
装入最新的后备副本使数据库恢复到最近一次转储时的一致性状态。对于静态转储的数据库副本装入后数据库即处于一致性状态对于动态转储的数据库副本还须同时装入转储时刻的日志文件副本利用恢复系统故障的方法即REDOUNDO才能将数据库恢复到一致性状态。装入有关的日志文件副本重做已完成的事务。
首先扫描日志文件找出故障发生时已提交的事务的标识将其记入重做队列。然后正向扫描日志文件对重做队列中的所有事务进行重做处理。介质故障的恢复需要DBA介入DBA的工作 重装最近转储的数据库副本和有关的各日志文件副本执行系统提供的恢复命令具体的恢复操作仍由DBMS完成
检查点
利用日志技术进行数据库恢复存在两个问题 搜索整个日志将耗费大量的时间REDO处理事务实际上已经执行又重新执行浪费了大量时间具有检查点checkpoint的恢复技术 在日志文件中增加检查点记录checkpoint增加重新开始文件并让恢复子系统在登录日志文件期间动态地维护日志检查点记录的内容 建立检查点时刻所有正在执行的事务清单这些事务最近一个日志记录的地址重新开始文件的内容 记录各个检查点记录在日志文件中的地址动态维护日志文件的方法
周期性地执行如下操作建立检查点保存数据库状态。
具体步骤是
1.将当前日志缓冲区中的所有日志记录写入磁盘的日志文件上
2.在日志文件中写入一个检查点记录
3.将当前数据缓冲区的所有数据记录写入磁盘的数据库中
4.把检查点记录在日志文件中的地址写入一个重新开始文件 使用检查点方法可以改善恢复效率
当事务T在一个检查点之前提交
T对数据库所做的修改一定都已写入数据库写入时间是在这个检查点建立之前或在这个检查点建立之时在进行恢复处理时没有必要对事务T执行REDO操作
使用检查点的恢复步骤 1.从重新开始文件中找到最后一个检查点记录在日志文件中的地址由该地址在日志文件中找到最后一个检查点记录 2.由该检查点记录得到检查点建立时刻所有正在执行的事务清单ACTIVE-LIST
建立两个事务队列 UNDO-LISTREDO-LIST把ACTIVE-LIST暂时放入UNDO-LIST队列REDO队列暂为空3.从检查点开始正向扫描日志文件直到日志文件结束
如有新开始的事务Ti把Ti暂时放入UNDO-LIST队列如有提交的事务Tj把Tj从UNDO-LIST队列移到REDO-LIST队列
4.对UNDO-LIST中的每个事务执行UNDO操作 对REDO-LIST中的每个事务执行REDO操作 镜像 为避免硬盘介质出现故障影响数据库的可用性许多DBMS提供了数据库映像mirror功能用于数据库恢复。
将整个数据库或其中的关键数据复制到另一个磁盘上每当主数据库更新时DBMS自动把更新后的数据复制过去由DBMS自动保证镜像数据与主数据库的一致性。一旦出现介质故障可由镜像磁盘继续提供使用同时DBMS自动利用磁盘数据进行数据库的恢复不需要关闭系统和重装数据库副本。
在没有出现故障时数据库镜像还可以用于并发操作即当一个用户对数据库加排它锁修改数据时其他用户可以读镜像数据库上的数据而不必等待该用户释放锁。
由于数据库镜像是通过复制数据实现的频繁地赋值数据自然会降低系统运行效率。因此在实际应用中用户往往只选择对关键数据和日志文件进行镜像。 小结 如果数据库只包含成功事务提交的结果就说数据库处于一致性状态。保证数据一致性是对数据库的最基本的要求。事务是数据库的逻辑工作单位 DBMS保证系统中一切事务的原子性、一致性、隔离性和持续性DBMS必须对事务故障、系统故障和介质故障进行恢复恢复中最经常使用的技术数据库转储和登记日志文件恢复的基本原理利用存储在后备副本、日志文件和数据库镜像中的冗余数据来重建数据库
常用恢复技术 事务故障的恢复
UNDO
系统故障的恢复
UNDO REDO
介质故障的恢复
重装备份并恢复到一致性状态 REDO提高恢复效率的技术
检查点技术
可以提高系统故障的恢复效率 可以在一定程度上提高利用动态转储备份进行介质故障恢复的效率
镜像技术
镜像技术可以改善介质故障的恢复效率
并发控制
多用户数据库允许多个用户同时使用的数据库订票系统
不同的多事务执行方式 1.串行执行每个时刻只有一个事务运行其他事务必须等到这个事务结束后方能运行。 2.交叉并发方式
单处理机系统中事务的并发执行实际上是这些并行事务的并行操作轮流交叉运行不是真正的并发但是提高了系统效率
3.同时并发方式
多处理机系统中每个处理机可以运行一个事务多个处理机可以同时运行多个事务实现多个事务真正的并行运行
并发执行带来的问题 多个事务同时存取同一数据共享资源 存取不正确的数据破坏事务一致性和数据库一致性
概述
并发操作带来的数据不一致性包括 1丢失修改lost update 2不可重复读non-repeatable read 3读脏数据dirty read
记号:Wx写数据x Rx读数据x 并发控制机制的任务 1对并发操作进行正确的调度 2保证事务的隔离性 3保证数据库的一致性
并发控制的主要技术 1封锁locking主要使用的 2时间戳timestamp 3乐观控制法optimistic scheduler 4多版本并发控制multi-version concurrency control MVCC
封锁
封锁封锁就是事务T在对某个数据对象例如表、记录等操作之前先向系统发出请求对其加锁。加锁后事务T就对该数据对象有了一定的控制在事务T释放它的锁之前其它的事务不能更新此数据对象 确切的控制由封锁的类型决定
基本的封锁类型有两种排它锁X锁exclusive locks、共享锁S 锁share locks
排它锁又称写锁对A加了排它锁之后其他事务不能对A加 任何类型的锁排斥读和写
共享锁又称读锁对A加了共享锁之后其他事务只能对A加S锁不能加X锁只排斥写
很重要 封锁协议
在运用X锁和S锁对数据对象加锁时需要约定一些规则封锁协议Locking Protocol
何时申请X锁或S锁、持锁时间、何时释放
对封锁方式制定不同的规则就形成了各种不同的封锁协议。
常用的封锁协议三级封锁协议
三级封锁协议在不同程度上解决了并发问题为并发操作的正确调度提供一定的保证。 1、一级封锁协议
事务T在修改数据R之前必须先对其加X锁直到事务结束commit/rollback才释放。
一级封锁协议可以防止丢失修改
如果是读数据不需要加锁的所以它不能保证可重复读和不读“脏”数据。 2、 二级封锁协议 在一级封锁协议的基础写要加X锁事务结束释放上增加事务T在读入数据R之前必须先对其加S锁读完后即可释放S锁。读要加S锁读完即释放
二级封锁协议除了可以防止丢失修改还可以防止读脏数据
由于读完数据即释放S锁不能保证不可重复读 3、三级封锁协议 在一级封锁协议基础上增加事务T在读取数据R之前必须先对其加S锁直到事务结束后释放。
三级封锁协议除了可以防止丢失修改和读脏数据外还防止了不可重复读 三级封锁协议的主要区别是什么操作需要申请锁何时释放锁。封锁协议越高一致性程度越高。 饥饿 饥饿事务T1封锁了数据R事务T2又请求封锁R于是T2等待。T3也请求封锁R当T1释放了R上的封锁之后系统首先批准了T3的请求T2仍然等待。 T4又请求封锁R当T3释放了R上的封锁之后系统又批准了T4的请求……T2有可能永远等待这就是饥饿的情形 避免饥饿的方法先来先服务
当多个事务请求封锁同一数据对象时按请求封锁的先后次序对这些事务排队
该数据对象上的锁一旦释放首先批准申请队列中第一个事务获得锁。 死锁 死锁事务T1封锁了数据R1 T2封锁了数据R2。 T1又请求封锁R2因T2已封锁了R2于是T1等待T2释放R2上的锁。 接着T2又申请封锁R1因T1已封锁了R1T2也只能
等待T1释放R1上的锁。 这样T1在等待T2而T2又在等待T1T1和T2两个事务永远不能结束形成死锁。 解决死锁的方法预防、诊断和解除
1、死锁的预防
产生死锁的原因是两个或多个事务都已经封锁了一些数据对象然后又都请求对已被其他事务封锁的数据对象加锁从而出现死等待。
预防死锁发生就是破坏产生死锁的条件
方法
1一次封锁法 要求每个事务必须一次将所有要使用的数据全部加锁否则就不能继续执行。 存在的问题降低系统的并发度难以实现精确确定封锁对象
2顺序封锁法 预先对数据对象规定一个封锁顺序所有事务都按这个顺序实施封锁。 存在的问题
维护成本数据库系统中的封锁对象极多并且在不断地变化
难以实现很难实现确定每一个事务要封锁哪些对象
DBMS普通采用的诊断并解除死锁的方法
2、死锁的诊断和解除 方法超时法和事务等待图法 1超时法如果一个事务的等待时间超过了规定的时限就认为发生了死锁 优点实现简单 缺点误判死锁时限若设置太长死锁发生后不能及时发现。 2事务等待图法用事务等待图动态反映所有事务的等待情况事务
等待图是一个有向图G(TU)T为结点的集合每个结点表示正运行的事务 U为边的集合每条边表示事务等待的情况。若T1等待T2则T1、T2之间划一条有向边从T1指向T2。 并发控制子系统周期性地比如每隔数秒生成事务等待图检测事务。如果发现图中存在回路则表示系统中出现了死锁。
解除死锁并发控制子系统选择一个处理死锁代价最小的事务将其撤销。
释放该事务持有的所有的锁使其他事务能够继续运行下去。 串行调度
什么样的调度是正确的串行调度是正确的。
执行结果等价于串行调度的调度也是正确的这样的调度称为可串行化调度。
可串行化调度
定义多个事务的并发执行是正确的当且仅当其结果与按某一次序串行地执行这些事务时的结果相同称这种调度策略为可串行化调度serializable。
可串行性是并发事务正确调度的准则。按这个准则规定一个给定的并发调度当且仅当它是可串行化的才认为是正确调度。 冲突可串行化调度
判断可串行化调度的充分条件
冲突操作不同的事务对同一个数据的读写和写写操作。 不同事务的冲突操作和同一事务的两个操作是不能交换的。
Rix和Wjx不可交换Wix和Wjx不可交换
冲突可串行化调度
一个调度Sc在保证冲突操作的次序不变的情况下通过交换两个事务不冲突操作的次序得到另一个调度Sc’如果Sc’是串行的称调度Sc为冲突可串行化的调度。 两段锁协议
DBMS的并发控制机制必须提供一定的手段来保证调度是可串行化的。目前DBMS普遍采用两段锁协议TwoPhase Locking简称2PL的方法来显示并发调度的可串行性。 两段锁协议是指所有事务必须分两个阶段对数据对象进行加锁和解锁。 1在对任何数据进行读写操作以前首先要申请并获得对该数据的锁。 2在释放一个锁之后事务不再申请和获得其他任何的锁。
“两段”锁的含义事务分为两个阶段
第一阶段是获得封锁也称为扩展阶段
事务可以申请获得任何数据对象上的任何类型的锁但是不能释放任何锁
第二阶段是释放封锁也称为收缩阶段
事务可以释放任何数据对象上的任何类型的锁但是不能再申请任何锁 事务遵守两段锁协议是可串行化调度的充分条件而不是必要条件。
若并发事务都遵守两段锁协议则对这些事务的任何并发调度策略都是可串行化的
若并发事务的一个调度是可串行化的不一定所有事务都符合两段锁协议 两段锁协议与防止死锁的一次封锁法
一次封锁法要求每个事务必须一次将所有要使用的数据全部加锁否则就不能继续执行因此一次封锁法遵守两段锁协议
但是两段锁协议并不要求事务必须一次将所有要使用的数据全部加锁因此遵守两段锁协议的事务可能发生死锁 封锁的粒度
封锁对象的大小称为封锁粒度granularity。
封锁的对象可以是逻辑单元属性值、属性值集合、元组、关系、索引项、数据库也可以是物理单元页、物理记录。
选择封锁粒度原则 封锁粒度和系统的并发度和并发控制的开销密切相关 封锁的粒度越大数据库所能够封锁的数据单元就越少并发度就越低系统开销也
越小
封锁的粒度越小并发度较高但系统开销也就越大 意向锁
意向锁如果对一个节点加意向锁则可说明该节点的下层节点正在被加锁对任一节点加锁时必须先对它的上层节点加意向锁。
例如对任一元组加锁时必须先对它所在的数据库和关系加意向锁。
三种常用的意向锁意向共享锁Intent Share LockIS锁意向排它锁Intent Exclusive LockIX锁共享意向排它锁Share Intent Exclusive LockSIX锁。 1、IS锁
如果对一个数据对象加IS锁表示它的子节点拟加S锁。
例如事务T1要对R1中某个元组加S锁则要首先对关系R1和数据库加IS锁 2、IX锁
如果对一个数据对象加IX锁表示它的子节点拟加X锁。
例如事务T1要对R1中某个元组加X锁则要首先对关系R1和数据库加IX锁 3、SIX锁
如果对一个数据对象加SIX锁表示对它加S锁再加IX锁即SIX S IX。 例如对某个表加SIX锁则表示该事务要读整个表所以要对该表加S锁同
时会更新个别元组所以要对该表加IX锁 意向锁的强度 锁的强度是指它对其他锁的排斥程度。一个事务在申请封锁时以强锁代替弱锁是安全的反之则不然。
具有意向锁的多粒度封锁方法
申请封锁时应该按自上而下的次序进行
释放封锁时则应该按自下而上的次序进行
优点 1提高了系统并发度 2减少了加锁和解锁的开销
在实际的DBMS产品中得到广泛应用。 其他并发控制
并发控制的方法除了封锁技术外还有时间戳方法、乐观控制法和多版本并发控制。
时间戳方法给每一个事务盖上一个时标即事务开始的时间。每个事务具有唯一的时间戳并按照这个时间戳来解决事务的冲突操作。如果发生冲突操作就回滚到具有较早时间戳的事务以保证其他事务的正常执行被回滚的事务被赋予新的时间戳被从头开始执行。
乐观控制法认为事务执行时很少发生冲突所以不对事务进行特殊的管制而是让它自由执行事务提交前再进行正确性检查。如果检查后发现该事务执行中出现过冲突并影响了可串行性则拒绝提交并回滚该事务。又称为验证方法
多版本控制是指在数据库中通过维护数据对象的多个版本信息来实现高效并发的一种策略。