[toc]
软件设计师笔记09_数据库技术基础
下面的内容参考自《软件设计师教程(第5版)》 这本书的第9章 数据库技术基础。
基本概念
数据库与数据库系统
数据是描述事物的符号记录,它具有多种表现形式,可以是文字、图形、图像、声音和语言等。
数据库系统(DBS)的定义
数据库系统是一个采用了数据库技术,有组织地、动态地存储大量相关数据,方便多用户访问的计算机系统。广义上讲,数据库系统是由数据库、硬件、软件和人员组成的。
- 数据库(DB):是指长期存储在计算机内的、有组织的、可共享的数据集合,即数据本身。
- 硬件:是指构成计算机系统的各种物理设备,包括存储数据所需的外部设备。
- 软件:包括操作系统、数据库管理系统及应用程序。
- 人员:系统分析员和数据库设计人员、应用程序员、最终用户、数据库管理员(DBA)等。
数据库管理系统(DataBaseManagementSystem,DBMS)的分类
- 关系型数据库系统(RDBS):是指采用关系模型作为数据组织的数据库系统,如MySQL、Oracle、SQL Server等。
- 面向对象的数据库系统(OOBS):是指采用面向对象模型作为数据组织的数据库系统,如ObjectDBMS、VisualFoxPro等。
- 对象关系数据库系统(ORDBS):是指采用对象关系模型作为数据组织的数据库系统,如PostgreSQL、Oracle等。
数据库系统的体系结构
从用户的角度看,数据库系统体系结构分为集中式、分布式、C/S(客户端/服务器)和并行结构;
集中式数据库系统
在集中式数据库系统中,不仅数据是集中的,数据的管理也是集中的,数据库系统的所有功能都集中在 数据库管理系统 所在的计算机上。大多数关系 数据库管理系统 的产品也是从这种系统结构开始发展的,目前这种系统还在使用。
如图所示 
C/S(客户端/服务器) 数据库系统
在C/S结构中,客户端的请求会被发送到服务器上执行。其主要特点是客户端与服务器 CPU之间的职责明确,客户端主要负责数据表示服务,服务器主要负责数据库服务。
采用客户端/服务器结构后,数据库系统功能分为前端和后端。前端主要包括图形用户界面、表格生成和报表处理等工具;后端负责存取结构、查询计算和优化、并发控制以及故障恢复等。
前端与后端通过SOL或应用程序来接口。ODBC(开放式数据库互连)和JDBC(Java 程序数据库连接)等标准定义了应用程序和数据库服务器通信的方法,即定义了应用程序接口,应用程序用它来打开与数据库的连接、发送查询和更新以及获取返回结果等。
如图所示 
并行数据库系统
并行体系结构的数据库系统是多个物理上连在一起的 CPU。并行体系结构的数据库类型分为共享内存式多处理器和无共享式并行体系结构。
共享内存式多处理器 共享内存式多处理器是指一台计算机上同时有多个活动的 CPU,它们共享单个内存和一个公共磁盘接口。这种并行体系结构最接近于传统的单 CPU 处理器结构,其设计的主要挑战是用 N个 CPU 来得到 N倍单 CPU 的性能。但是,由于不同的 CPU 对公共内存的访问是平等的,这样可能会导致一个 CPU 访问的数据被另一个 CPU 修改,所以必须要有特殊的处理。然而,由于内存访问采用的是一种高速机制,这种机制很难保证进行内存划分时不损失效率,所以这些共享内存访问问题会随着CPU个数的增加变得难以解决。
无共享式并行体系结构 无共享式并行体系结构是指一台计算机上同时有多个活动的CPU,并且它们都有自己的内存和磁盘,图中粗线表示高速网络。在不产生混淆的情况下,该结构的数据库系统也称为并行数据库系统。各个承担数据库服务责任的 CPU划分它们自身的数据,通过划分的任务以及通过每秒兆位级的高速网络通信完成事务查询。

分布式数据库系统
分布式 DBMS 包括物理上分布、逻辑上集中的分布式数据库结构和物理上分布、逻辑上分布的分布式数据库结构两种。
前者的指导思想是把单位的数据模式(称为全局数据模式)按数据来源和用途合理地分布在系统的多个结点上,使大部分数据可以就地或就近存取。数据在物理上分布后,由系统统一管理,使用户不感到数据的分布。
后者一般由两部分组成:一是本结点的数据模式,二是本结点共享的其他结点上有关的数据模式。结点间的数据共享由双方协商确定。这种数据库结构有利于数据库的集成、扩展和重新配置。
分布式数据库的体系结构如图所示。 
数据库的"三级模式和两级映像"结构
数据库体系结构大多采用"三级模式和两级映像"。
如图所示 
数据库的三级模式结构
- 概念模式(也称模式)。它是数据库中全体数据的逻辑结构和特征的描述,它由若干个概念记录类型组成,只涉及类型的描述,不涉及具体的值。概念模式反映的是数据库的结构和特征。
- 外模式(也称用户模式或子模式)。它是用户与数据库系统的接口,是用户用到的那部分数据的描述,由若干个外部记录类型组成。用户使用数据操作语言对数据进行操作,实际上是对外模式的外部记录进行操作。
- 内模式(也称存储模式),它是数据物理结构和存储方式的描述,是数据在数据库内部的表示方式,定义所有的内部记录类型、索引和文件的组织方式以及数据控制方面的细节。
简而言之,外模式是对接用户的,内模式是对接数据库系统的,而概念模式连接这两者的中间层,它是是用户和数据库系统之间的桥梁。

数据库的两级映像
数据库系统在三级模式之间提供了两级映像:模式/内模式映像、外模式/模式映像。正因为这两级映像保证了数据库中的数据具有较高的逻辑独立性和物理独立性。
- 模式/内模式映像。该映像存在于概念级和内部级之间,实现了概念模式到内模式之间的相互转换。(物理独立性)
- 外模式/模式映像。该映像存在于外部级和概念级之间,实现了外模式到概念模式之间的相互转换。(逻辑独立性)
数据的独立性是指数据与程序独立,将数据的定义从程序中分离出去,由 DBMS 负责数据的存储,从而简化应用程序,大大减少应用程序编制的工作量。数据的独立性是由 DBMS 的级映像功能来保证的。
数据的独立性包括数据的物理独立性和数据的逻辑独立性。
- 数据的物理独立性。是指当数据库的内模式发生改变时,数据的逻辑结构不变。由于应用程序处理的只是数据的逻辑结构,这样物理独立性可以保证,当数据的物理结构改变时,应用程序不用改变。但是,为了保证应用程序能够正确执行,需要修改概念模式和内模式之间的映像。
- 数据的逻辑独立性。是指用户的应用程序与数据库的逻辑结构是相互独立的。数据的逻辑结构发生变化后,用户程序也可以不修改。但是,为了保证应用程序能够正确执行,需要修改外模式和概念模式之间的映像。
数据模型
基本概念
模型就是对现实世界特征的模拟和抽象,数据模型是对现实世界数据特征的抽象。对于具体的模型人们并不陌生,如航模飞机、地图和建筑设计沙盘等都是具体的模型。
最常用的数据模型分为概念数据模型和基本数据模型。
概念数据模型:也称信息模型,是按用户的观点对数据和信息建模,是现实世界到信息世界的第一层抽象,强调其语义表达功能,易于用户理解,是用户和数据库设计人员交流的语言,主要用于数据库设计。这类模型中最著名的是实体联系模型,简称E-R模型。
基本数据模型:是按计算机系统的观点对数据建模,是现实世界数据特征的抽象,用于DBMS的实现。基本数据模型主要有层次模型、网状模型、关系模型和面向对象模型。
数据模型三要素
数据库结构的基础是数据模型,而数据模型是用来描述数据的一组概念和定义。数据模型的三要素是数据结构、数据操作、数据的约束条件。
- 数据结构:是所研究的对象类型的集合,是对系统静态特性的描述。
- 数据操作:是对数据库中各种对象(型)的实例(值)允许执行的操作集合,包括操作及操作规则。例如操作有检索、插入、删除和修改,操作规则有优先级别等。
- 数据的约束条件:是一组完整性规则的集合。也就是说,对于具体的应用数据必须遵循特定的语义约束条件,以保证数据的正确、有效、相容。
E-R 模型
实体-联系模型简称E-R模型,是软件工程设计中的一个重要方法,因为它接近于人的思维方式,容易理解并且与计算机无关,所以用户容易接受,是用户和数据库设计人员交流的语言。但是,E-R模型只能说明实体之间的语义联系,还不能进一步地详细说明数据结构。
因此一般遇到实际问题,应先设计一个E-R模型,然后再把它转换成计算机能接受的数据模型。
E-R模型的3个主要概念
E-R模型,所采用的3个主要概念是实体、联系和属性。
- 实体:是现实世界中可以区别于其他对象的“事件”或“物体”。每个实体由一组特性(属性)来表示,其中的某一部分属性可以唯一表示实体。实体集是具有相同属性的实体集合。例如教师是一个实体,而学校的所有教师是一个实体集。
- 联系:实体集之间的对应关系称为联系。实体的联系分为实体内部的联系和实体与实体之间的联系。
- 属性:是实体某方面的特性。例如,职工实体具有职工号、姓名、年龄、参加工作时间和通信地址等属性。每个属性都有其取值范围。在同一个实体集中,每个实体的属性是相同的,但可能取不同的值。
E-R模型中的属性有以下几个分类
- 简单属性和复合属性:
- 简单属性:是原子的、不可再分的。
- 复合属性:可以细分为更小的部分(即划分为别的属性)。
- 单值属性和多值属性:
- 若定义的属性对于一个特定的实体只有一个值,这样的属性叫做单值属性。
- 若定义的属性对应一组值,则称为多值属性。
- NULL属性:当实体在某个属性上没有值或属性值未知时,使用NULL值,表示无意义或不知道。
- 派生属性:可以从其他属性得来。
两个不同实体集之间的3种联系类型
- 一对一联系(1∶1):如果对于实体集A中的每一个实体,实体集B中至多有一个实体与之联系;反之亦然,则称实体集A与实体集B具有一对一联系。记为1∶1。
- 一对多联系(1∶n):如果对于实体集A中的每一个实体,实体集B中有n个实体(n≥0)与之联系;反之,对于实体集B中的每一个实体,实体集A中至多只有一个实体与之联系,则称实体集A与实体集B有一对多联系。记为1∶n。
- 多对多联系(m:n):如果对于实体集A中的每一个实体,实体集B中有n个实体(n≥0)与之联系;反之,对于实体集B中的每一个实体,实体集A中也有m个实体(m≥0)与之联系,则称实体集A与实体集B具有多对多联系。记为m:n。
如图所示 
两个以上不同实体集之间的联系类型
两个以上不同实体集之间存在 1:1:1、1:1:n、1:m:n 和 r:m:n 的联系。
如图表示了3个不同实体集之间的联系。例如图(b)表示病房、病人和医生之间一对多对多(1∶n:m)的联系,联系名为PD。表示了一个病房有多个病人和多个医生,一个医生只负责一个病房,一个病人只属于一个病房的语义 
E-R 模型图
E-R 图中的主要构件如图所示。
- 实体:用矩形表示,每个实体由一组属性表示,包括主键、候选键、外键。
- 联系:用菱形表示,分为一对一(1:1)、一对多(1:n)、多对多(m:n)。
- 属性:用椭圆表示,是实体某方面的特性。E-R 模型中的属性分为:①简单和复合属性;②单值和多值属性;③null 属性;④派生属性

例题: 假设学校有若干个系,每个系有若干名教师和学生;每个教师可以担任若干门课程,并参加多个项目;每个学生可以同时选修多门课程。请设计该学校教学管理系统的E-R模型,要求给出每个实体、联系的属性。
解题:该学校教学管理系统的E-R模型应该有5个实体,即系、教师、学生、项目和课程。
- (1)设计各实体属性如下:
- 系(系号,系名,主任名)
- 教师(教师号,教师名,职称)
- 学生(学号,姓名,年龄,性别)
- 项目(项目号,名称,负责人)
- 课程(课程号,课程名,学分)
- (2)各实体之间的联系如下:
- 教师担任课程的 1∶n“任课”联系;
- 教师参加项目的 n:m“参加”联系;
- 学生选修课程的n:m“选修”联系;
- 教师、学生与系之间所属关系的1:n:m“领导”联系。其中“参加”联系有一个排名属性,“选修”联系有一个成绩属性。
则对应的E-R模型图如下所示。 
关系模型
关系模型是最常用的数据模型之一。关系数据库系统就是使用关系模型作为数据的组织方式。
在关系模型中用表格结构表达实体集以及实体集之间的联系,其最大特色是描述的一致性。
关系数据库的基本概念
属性和域
- 属性: 在现实世界中,要描述一个事物,常常取其若干特征来表示。这些特征称为属性。
- 域: 每个属性的取值范围的集合,称为该属性的域。
关系的三种类型
- 基本关系(又称基本表、基表):这是实际存在的表,它是实际存储数据的逻辑表示。
- 查询表:它是查询结果对应的表。
- 视图表:它是由基本表或其他视图表导出的表。由于它本身不独立存储在数据库中,数据库中只存放它的定义,所以常称为虚表。
关系代数
5种基本的关系代数运算
5种基本的关系代数运算分别为 并,差,笛卡尔积,投影,选择。其他运算包括可以通过基本的关系运算导出。
关系代数运算符如图所示

关系数据库SQL语言
SQL是在1974年由Boyce和Chamberlim提出的,它是关系数据库中最普遍使用的语言,包括数据査询、数据操纵、数据定义和数据控制功能,是一种通用的、功能强大的关系数据库的标准语言。
SQL的基本概念
SQL的特点
- 综合统一。SOL集数据定义、数据操纵和数据控制功能于一体,语言风格统一,可独立完成数据库生命周期的所有活动。
- 高度非过程化。 SOL语言是高度非过程化语言,当进行数据操作时,只要指出“做什么”
- 面向集合的操作方式。SOL语言采用面向集合的操作方式,其操作对象、查找结果可以是元组的集合。
- 两种使用方式:
- a、用户可以在终端键盘上输入SQL命令,对数据库进行操作,故称之为自含式语言;
- b、将SQL嵌入到高级语言程序中,所以又是嵌入式语言。
- 语言简洁,易学易用。SQL语言功能极强,完成核心功能只用了9个动词,包括以下4类。
- 数据查询:SELECT。
- 数据定义:CREATE、DROP、ALTER。
- 数据操纵:INSERT、UPDATE、DELETE。
- 数据控制:GRANT、REVORK。
SQL支持三级模式结构:视图对应外模式、基本表对应模式、存储文件对应内模式。
SQL的基本构成
SQL语言由以下几个部分构成:
- 数据定义语言(DDL):它提供定义关系模式和视图、删除关系和视图、修改关系模式的命令。
- 交互式数据操纵语言(DML):它提供查询、插入、删除和修改的命令。
- 事务控制:它提供的定义事务开始和结束的命令。
- 嵌入式SQL和动态SQL:它用于嵌入到高级语言(C、C++、Java等)中混合编程。其中SQL负责操纵数据库,高级语言负责控制程序流程。
- 完整性:它包括定义数据库中的数据必须满足的完整性约束条件的命令,对于破坏完整性约束条件的更新将被禁止。
- 权限管理:它包括说明对关系和视图的访问权限的命令。
SQL数据定义
SQL 的数据定义包括对表、视图、索引的创建和删除。
创建表

修改表

删除表

建立索引

删除索引

SQL数据查询
SOL的数据操纵功能包括 SELECT(查询)、INSERT(插入)、DELETE(删除)和 UPDATE(修改)这4条语句。
SELECT 查询表


简单查询与连接查询
- 简单查询:简单查询只需要使用3个保留字,即SELECT、FROM 和 WHERE。
- 连接查询:若查询涉及两个以上的表,则称为连接查询。
子查询与聚集查询
- 子查询:子查询也称为嵌套查询,是指在一个SELECT-FROM-WHERE查询块中可以嵌入另一个查询块之中。在SQL中允许多重嵌套。
- 聚集函数:聚集函数是以一个值的集合为输入,返回单个值的函数。SQL提供了5个预定义集合函数,即平均值AVG、最小值MIN、最大值MAX、求和SUM及计数COUNT。

分组查询
- GROUPBY子句:在WHERE子句后面加上GROUPBY子句可以对元组进行分组,保留字GROUPBY后面跟着一个分组属性列表。最简单的情况是,FROM子句后面只有一个关系,根据分组属性对其元组进行分组。SELECT子句中使用的聚集操作符仅用在每个分组上。
- HAVING子句:假如元组在分组前按照某种方式加上限制,使得不需要的分组为空,则在GROUPBY子句后面跟一个HAVING子句即可。
当元组含有空值时,应注意以下两点:
- a、空值在任何聚集操作中都被忽略。它对求和、求平均值和计数都没有影响,也不能是某列的最大值或最小值
- b、NULL值可以在分组属性中看作一个一般的值。
字符串操作
对于字符串进行的最通常的操作是使用LIKE操作符的模式匹配。使用两个特殊的字符来描述模式,即“%”匹配任意字符串、“-”匹配任意一个字符。
SQL数据更新
插入数据

删除数据

更新数据

SQL访问控制(授权与收回权限)
SQL访问控制是指控制用户对数据访问的权限。应具有以下功能:
- 通过 GRANT 和 REVOKE 将授权通知系统,并存入数据词典。
- 当用户提出请求时,根据授权情况检查是否执行操作请求。
GRANT 授权语句

REVOKE 收回权限语句

关系数据库的范式化
范式是一系列规则,用于指导数据库的结构设计,以确保数据的一致性和减少冗余。
范式有1NF、2NF、3NF等,其中1NF 的级别最低。
第一范式(1NF):原子性
第一范式要求表中的所有字段值都是不可分解的原子值,即每个字段都是最小的数据单位,不可再分。
例如,如果一个字段包含了地址信息,而系统需要频繁地单独访问其中的城市部分,则应该将地址拆分为省份、城市、详细地址等多个字段。这样,当需要对地址的某个部分进行操作时,将更加方便,同时也提高了数据库的性能。
第二范式(2NF):唯一性
在满足第一范式的基础上,第二范式进一步要求表中的每个字段都必须与主键完全相关,而不能仅与主键的一部分相关。这主要针对联合主键的情况,即一个表中只能保存一种数据类型,不可以将多种数据类型保存在同一张表中。
例如,订单信息表中可能包含多种商品,因此需要将订单编号和商品编号作为联合主键。如果表中的某些字段只与主键的一部分相关,则违反了第二范式。
第三范式(3NF):独立性
第三范式要求表中的每个字段都必须直接与主键相关,而不能间接相关。也就是说,非主键字段之间不能存在依赖关系,它们必须直接依赖于主键。
例如,如果设计一个订单表,可以将客户编号作为外键与订单表建立关系,而不应在订单表中添加关于客户其他信息的字段。这样,在查询订单信息时,可以使用客户编号引用客户信息表中的记录,避免在订单信息表中重复输入客户信息,从而减少数据冗余。
事务管理
事务是一个操作序列,这些操作“要么都做,要么都不做”,是数据库环境中不可分割的逻辑工作单位。事务和程序是两个不同的概念,一般一个程序可包含多个事务。
在 SOL语言中,事务定义的语句有以下三条。
- BEGINTRANSACTION:事务开始。
- COMMIT:事务提交。该操作表示事务成功地结束,它将通知事务管理器该事务的所有更新操作现在可以被提交或永久地保留。
- ROLLBACK:事务回滚。该操作表示事务非成功地结束,它将通知事务管理器出故障了,数据库可能处于不一致状态,该事务的所有更新操作必须回滚或撤销。
事务具有原子性、一致性、隔离性和持久性。这4个特性也称事务的 ACID 性质。
- 原子性(Atomicity):一个事务中的所有操作在数据库中要么全做,要么全都不做
- 一致性(Consistency):一个事务执行的结果必须保证数据库从一个一致性状态变到另一个一致性状态。
- 隔离性(Isolation):事务与事务之间相互隔离。当多个事务并发执行时,任一事务的更新操作直到其成功提交的整个过程,对其他事务都是不可见的。
- 持久性(Durability):一旦事务成功提交,即使数据库崩溃,其对数据库的更新操作也将永久有效。
数据库的备份和恢复
在数据库的运行过程中,难免会出现计算机系统的软、硬件故障,这些故障会影响数据库中数据的正确性,甚至破坏数据库,使数据库中的全部或部分数据丢失。
因此,数据库的关键技术在于建立冗余数据,即备份数据。如何在系统出现故障后能够及时地使数据库恢复到故障前的正确状态,就是数据库恢复技术。
数据库一般遭遇的故障类型如下
- 事务内部故障:事务内部的故障有的可以通过事务程序本身发现。例如运算故障,事务发生死锁等。
- 系统故障:通常称为软故障,是指造成系统停止运行的任何事件,使得系统要重新启动。例如系统崩溃、操作系统死机等。
- 介质故障:通常称为硬故障,如磁盘损坏、磁头碰撞和瞬时强磁干扰。此类故障发生的几率小,但破坏性最大
- 计算机病毒:是一种人为的故障和破坏,是在计算机程序中插入的破坏,计算机功能或者数据可以繁殖和传播的一组计算机指令或程序代码。
数据库的备份方法
恢复的基本原理是“建立冗余数据”(重复存储)。建立冗余数据的方法是进行数据转储和登记日志文件。
数据的转储分为静态转储和动态转储、海转储和增量转储、日志文件。
- 静态转储和动态转储:
- 静态转储是指在转储期间不允许对数据库进行任何存取、修改操作
- 动态转储是指在转储期间允许对数据库进行存取、修改操作
- 海量转储和增量转储:
- 海量转储是指每次转储全部数据
- 增量转储是指每次只转储上次转储后更新过的数据
- 日志文件。在事务处理的过程中,把对数据库的插入,删除和修改的每一次操作写入日志文件。一旦发生故障,利用日志文件回退到事务的初始状态。
事务恢复的3个步骤
- 反向扫描文件日志,查找该事务的更新操作
- 对事务的更新操作执行逆操作
- 继续反向扫描日志文件,查找该事务的其他更新操作,并做同样的处理,直到事务的开始标志
数据库的并发控制
并发操作是指在多用户共享的系统中许多用户可能同时对同一数据进行操作。
并发操作带来的问题是数据的不一致性,主要有三类:丢失更新、不可重复读和读脏数据。其主要原因是事务的并发操作破坏了事务的隔离性。
并发操作带来的问题
并发操作带来的数据不一致性有三类:丢失修改、不可重复读和读脏数据。如图 9-30 所示。

丢失修改
如图 9-30(a)所示,事务T1、T2都是对数据 A 做减1操作。事务 T1 在时刻t5 把 A 修改后的值 15 写入数据库,但事务T2 在时刻t7再把它对 A 减1后的值 15 写入。两个事务都是对A的值进行减1操作并且都执行成功,但 A 中的值却只减了 1。
例如火车售票系统,T1与T2各售出了一张票,但数据库里的存票却只减了一张,造成数据的不一致。原因在于T1事务对数据库的修改被T2事务覆盖而丢失了,破坏了事务的隔离性。
不可重复读
如图 9-30(b)所示,事务T1 读取 A、B 的值后进行运算,事务T2在 t6 时刻对 B的值做了修改以后,事务T1又重新读取 A、B的值再运算,同一事务内对同一组数据的相同运算结果不同,显然与事实不相符。同样是事务T2干扰了事务T1的独立性。
读脏数据。
如图 9-30(c)所示,事务T1 对数据C 修改之后,在t3时刻事务T2读取修改后的 C 值做处理,之后事务 T1 回滚,数据C恢复了原来的值,事务T2对C所做的处理是无效的,它读的是被丢掉的垃圾值。
在上面的例子中,在事务并行处理的过程中对相同数据进行访问会导致了数据的不一致性,解决该问题可以从保证事务的隔离性入手。并发控制技术
有多种技术用来解决并发操作带来的数据不一致性问题,主要有封锁等。
并发控制的主要技术是封锁。封锁的类型有排它锁(简称X锁或写锁)和共享锁(简称S锁或读锁)。
封锁的类型
- 排他锁(X/写锁)。若事务T对数据对象 A加上X锁,则只允许事务T读取和修改 A,其他事务都不能再对 A 加任何类型的锁,直到事务T释放 A上的锁。
- 共享锁(S/读锁)。若事务T对数据对象 A 加上S锁,则只允许事务T读取 A,但不能修改 A,其他事务只能再对A加S锁,直到事务T释放A 上的S锁。这就保证了其他事务可以读 A,但在事务 T 释放A上的S锁之前不能对A进行任何修改。
三级封锁协议
- 一级封锁协议。:修改数据前先加 X 锁,事务结束后释放,可解决丢失修改问题。
- 二级封锁协议。在一级基础上,读数据之前加 S 锁,读完后释放即可。二级封锁协议可以解决读脏数据的问题。但是由于二级封锁协议读完了数据后即可释放S锁,所以不能保证可重复读。
- 三级封锁协议。在一级基础上,读数据之前加 S 锁,直到事务结束后释放 S 锁,即可解决丢失修改、读脏数据、不可重复读三个数据不一致的问题。
