目录
一、绪论
1.数据库的定义
数据库就是长期存储在计算机内有组织的、可共享的大量数据的集合。
它可以供各种用户共享,具有最小的冗余度和较强的数据独立性。数据库管理系统建立、运维时对数据库进行统一控制,以保证数据的完整性和安全性,并在多用户同时使用数据库时进行并发控制,在发生故障给后对数据库进行恢复。
2.数据模型的三要素
(1) 数据结构,数据结构描述数据库的组成对象以及对象之间的联系。
(2) 数据操纵,数据操纵是指对数据库中的各种对象(型)的实例(值)允许执行的操作的集合,包括操作及有关的操作规则。数据库主要有查询和更新(包括插入、删除、修改)两大类操作。
(3) 完整性约束,完整性约束是一组完整性的规则。完整性规则是给定数据模型中的数据及其联系所具有的制约和依存规则,用以限定符合数据模型的数据库状态以及状态的变化,以保证数据的正确、有效和相容。
3.三种模型的区别
层次模型:(1) 有且只有一个结点没有双亲结点,这个结点称为根结点。(2) 跟以外的其他结点有且只有一个双亲结点。
网状模型:(1) 允许一个以上的结点无双亲结点。(2) 一个结点可以有多于一个的双亲结点。
关系模型:关系模型是采用二维表格结构表达实体类型及实体间联系的数据模型,关系模型中无论是实体还是实体间的联系均由单一的结构类型——关系来表示。在实际的关系数据库中的关系也称表。一个关系数据库就是由若干个表组成。
4.关系模型的数据结构中术语
(1)关系:一个关系对应一张二维表。
(2)元组:表中一行即为一个元组。(关于元组和记录的关系《数据库系统概论(第6版)》书中描述在描述层次模型和网状模型时出现记录,在描述关系模型时出现元组,在层次模型和网状模型所描述的表中行为记录,列为字段,在关系模型描述的表中行为元组,列为属性。请见关系模型_百度百科、记录(数据库、EXCEL使用名词)_百度百科、数据库中的实体、元组、字段、属性、码、分量、依赖关系、完全部份传递依赖、范式等你了解吗?【笔记自用】_数据实体-优快云博客)
(3)属性:表中一列即为一个属性,每列列名即为属性名。
(4)码(键):表中的某一个属性或一组属性,其值可以唯一确定一个元组。
对于三张表S、C、SC,S表中一个属性 Sno 作 S表 的主键(码);SC 中的一组属性 Cno 和Sno 一起作 SC 的联合主码(键)。
(5)域:域表示某一属性的取值范围。例如,属性 "性别" 的域是(‘男’,‘女’),属性 "专业" 的属性可以是大数据、网安,计科...
(6)分量:元组中的一个属性值。
(7)关系模式:用于描述关系,表示为:关系名(属性1, 属性2, ..., 属性n),例如:学生(姓名, 学号, 性别, 专业, 班级)←就是关系模式。
5.数据库系统三级模式结构
(1)外模式:外模式描述的是数据的局部逻辑结构,对于同一个模式,可以有任意多个外模式。对于每一个外模式,数据库系统都有一个 外模式/模式映像 来定义该外模式与模式之间的对应关系。
(2)模式映像:当模式改变时(如增加新的关系、新的属性,改变属性的数据类型等),由数据库管理员对各个 外模式/模式 的映像做相应改变,可以使外模式保持不变。应用程序是依据数据的外模式编写的,因而应用程序不必修改,保证了数据与程序之间的逻辑独立性,简称数据的逻辑独立性。
(3)模式:模式定义了数据库全局逻辑结构与存储结构之间的对应关系,数据库只有一个模式,也只有一个内模式,所以 模式/内模式映像 是唯一的。
(4)内模式映像:当数据库的存储结构改变时,由数据库管理员对 模式/内模式映像 做相应改变,可以使模式保持不变,因而应用程序也不必改变,保证了数据与程序的物理独立性。
6. 数据库系统的组成
数据库系统的组成元素包括:数据库管理员、系统分析员和数据库设计员、应用程序员、最终用户。
二、关系模型
1.域
域是一组具有相同数据类型的值的集合。
例如:整数、{男, 女}、0~100等,都可以是域。
2.笛卡尔积
笛卡尔积是域上的一种集合运算。
一个域允许的不同取值个数称为这个域的基数。
笛卡儿积可表示为一张二维表。表中的每行对应一个元组,表中的每一列的值来自个域。例如给出三个域:
D1 = 导师集合SUPERVISOR = {张清玫,刘逸}
D2 = 专业集合SPECIALITY = {计算机专业,信息专业}
D3 = 研究生集合POSTGRADUATE = {李勇,刘晨,王敏}
其中,(张清玫,计算机专业,李勇)、(张清玫,计算机专业,刘晨)等都是元组。张清玫、计算机专业、李勇、刘晨等都是分量。
该笛卡儿积的基数为 2x2x3=12,也就是说,D1xD2xD3一共有 2x2x3=12个元组。这12个元组可列成一张二维表,如表 2.1所示。
不难推断出,由笛卡尔积生成的表,是把原表的列数相加,行数相乘。
3.关系代数
关系代数是一种抽象的查询语言,它用对关系的运算来表达查询。
4.传统的集合运算
设关系R和关系S具有相同的目n(即两个关系都有n个属性,目的数量就是属性的数量),且相应的属性取自同个域,t是元组变量(t∈R表示t是R的一个元组)。
可以定义并、差、交、笛卡儿积运算如下:
5.专门的关系运算
专门的关系运算包括选择、投影、连接、除运算等
(1)选择:选择又称为限制(restriction)。它是在关系R中选择满足给定条件的诸元组。投影操作是从列的角度进行的运算。
(2)投影:关系R上的投影是从R中选择出若干属性列组成新的关系。
投影之后不仅取消了原关系中的某些列,而且还可能取消某些元组,因为取消了某些属性列后,就可能出现重复行,应取消这些完全相同的行。
(3)连接:从两个关系的笛卡儿积中选取属性间满足一定条件的元组。
连接运算中有两种最为重要也最为常用的连接,一种是等值连接(equijoin),另一种是自然连接(naturaljoin)。
等值连接:从两个关系的广义笛卡尔积中选取列属性值相等的元组。
自然连接:两个关系等值连接后去除属性值相同的属性列,只留一列。
三、关系数据库标准语言SQL
0.创建数据库
CREATE DATABASE <数据库名称>;
USE <数据库名称>;
1.建表
CREATE TABLE <表名>(
<列名> <数据类型> [<列级完整性约束>],
<列名> <数据类型> [<列级完整性约束>],
...,
[<表级完整性约束>]
);
例1:建立一个“学生”表 student。
CREATE TABLE student(
s_no CHAR(8) PRIMARY KEY, /* 列级完整性约束条件, s_no是主码 */
s_name VARCHAR(20) UNIQUE,
s_sex CHAR(6),
s_birthdate DATE,
s_major VARCHAR(40)
);
例2:建立一个“课程”表 course。
CREATE TABLE course(
c_no CHAR(8) PRIMARY KEY,
c_name VARCHAR(40) NOT NULL,
c_credit SMALLINT
);
例3:建立学生选课表SC。
CREATE TABLE sc(
s_no CHAR(8),
c_no CHAR(8),
grade SMALLINT,
teach_class CHAR(8),
PRIMARY KEY(s_no,c_no), /* 主码由两个属性构成,必须作为表级完整性进行定义 */
FOREIGN KEY(s_no) REFERENCES student(s_no),/* 表级完整性约束条件,s_no是外码,被参照表是student */
FOREIGN KEY(c_no) REFERENCES course(c_no)
);
2.修改表结构
ALTER TABLE <表名>
ADD [COLUMN] <新列名> <数据类型> [<完整性约束>]
ADD <表级完整性约束>
DROP [COLUMN] <列名> [CASCADE | RESTRICT] /* 若选择CASCADE,则该表的删除没有限制条件。在删除基本表的同时,相关的依赖对象,例如视图,都将被一起删除。默认情况是 RESTRICT */
DROP CONSTRAINT <完整性约束名> [RESTRICT | CASCADE]
RENAME COLUMN <列名> to <新列名>
ALTER COLUMN <列名> TYPE <数据类型>
其中:
(1)<表名>是要修改的基本表。
(2)ADD子句用于增加新列、新的列级完整性约束条件和新的表级完整性约束条件。 (3)DROP COLUMN 子句用于删除表中的列,如果指定了CASCADE短语,则自动删除引用了该列的其他对象,比如视图;如果指定了RESTRICT短语,则如果该列被其他对象引用,RDBMS将拒绝删除该列。
(4)DROP CONSTRAINT 子句用于删除指定的完整性约束条件。
(5)ALTERCOLUMN 子句用于修改原有的列定义,包括修改列名和数据类型。
例1:向student表中添加 "邮箱地址" 列s_email,其数据类型为字符型。
ALTER TABLE student
ADD s_email VARCHAR(30);
例2:将年龄的数据类型由字符型(假设原来的数据类型是字符型)改为整数。
ALTER TABLE student
ALTER COLUMN s_age INT;
例3:增加课程名称必须取唯一值的约束条件。
ALTER TABLE course
ADD UNIQUE(c_name);
例4:删除课程表 sc 中c_name一列。
ALTER TABLE sc
DROP COLUMN c_name;
3.删除基本表
若选择CASCADE,则该表的删除没有限制条件。在删除基本表的同时,相关的依赖对象,例如视图,都将被一起删除。默认情况是 RESTRICT。
DROP TABLE <表名> [RESTRICT | CASCADE];
例1:删除 student 表。
DROP TABLE student CASCADE;
4.修改数据
修改操作又称为更新操作 。
UPDATE <表名>
SET <列名>=<表达式> [,<列名>=<表达式>]…
[WHERE<条件>];
例1:将学生 201215121的年龄改为22岁。
UPDATE student
SET s_age=22
WHERE s_no='201215121';
例2:将所有学生的年龄增加1岁 。
UPDATE student
set s_age=s_age+1;
5.删除数据
DELETE
FROM <表名>
[WHERE<条件>];
例1:删除学号为201215128的学生记录。
DELETE FROM student
WHERE s_no='201215128';
例2:删除所有的学生选课记录。
DELETE FROM sc;
6.创建视图
关系数据库管理系统执行CREATE VIEW语句的结果只是把视图的定义存入数据字典,并不执行其中的SELECT语句。只是在对视图查询时,才按视图的定义从基本表中将数据查出。也就是需要用到视图的时候才取出基本表中的数据到视图中,这样操作的一个重要作用是可以保护数据,视图可以限制对基础数据的访问,只展示给用户他们需要看到的数据。比如,可以创建一个只包含员工公开信息的视图,而隐藏敏感信息如薪水等。
CREATE VIEW <视图名> [(<列名>[,<列名>]…)]
AS <子查询(select语句)>
[WITH CHECK OPTION];
WITH CHECK OPTION表示对视图进行UPDATE、INSERT和DELETE 操作时要保证更新、插入或删除的行满足视图定义中的谓词条件(即子查询中的条件表达式)。
谓词条件”指的是构成视图的基础查询中 WHERE 子句(或其他限制条件)所指定的条件。举例来说,如果有一个存储员工信息的表格 employees,并且要创建一个只包含销售部(department = 'Sales')员工的视图,那么这样定义视图:
CREATE VIEW sales_staff
AS
SELECT *
FROM employees
WHERE department = 'Sales'
WITH CHECK OPTION;
谓词条件”是 department = 'Sales'。这个条件限制了视图 sales_staff 包含的行只能是 department 列值为 'Sales' 的那些行。 并且任何尝试通过这个视图添加或修改记录,使得记录不满足 department = 'Sales' 的条件的操作都无法进行。
例1:建立信息系学生的视图。
CREATE VIEW IS_Student1
AS
SELECT s_no,s_name,s_age
FROM student
WHERE s_major='IS';
例2:建立信息系学生的视图,并要求进行修改和插入操作时仍需保证该视图只有信息系的学生。
CREATE VIEW IS_Student2
AS
SELECT s_no,s_name,s_age
FROM student
WHERE s_major='IS'
WITH CHECK OPTION;
由于在定义IS Student视图时加上了 WITH CHECK OPTION 子句,以后对该视图进行插入、修改和删除操作时,关系数据库管理系统会自动加上 Sdept='IS' 的条件。
例3: 建立信息系选修了1号课程的学生的视图(包括学号、姓名、成绩)。
CREATE VIEW IS_S1(Sno,Sname,Grade)
AS
SELECT student.s_no,s_name,grade
FROM student,sc
WHERE s_major='IS' AND
student.s_no=sc.c_no AND
sc.c_no='1';
IS_S1(Sno,Sname,Grade)指定了视图列的别名,如果不指定别名,直接写IS_S1,视图将会直接使用基础查询中指定的列名。
视图不仅可以建立在一个或多个基本表上,也可以建立在一个或多个已定义好的视图上,或建立在基本表与视图上。
例4:将学生的学号及平均成绩定义为一个视图。
CREATE VIEW S_G(Sno,Gavg)
AS
SELECT s_no,AVG(grade)
FROM sc
GROUP BY s_no;
7.删除视图
DROP VIEW <视图名> [CASCADE];
例1: 删除视图IS_Student。
DROP VIEW IS_Student1;
8.查询视图
视图定义后,就像对基本表一样对视图进行查询。
例1:在IS_Student2学生的视图中找出年龄小于20岁的学生。
SELECT s_no,s_age
FROM IS_Student2
WHERE s_age<20;
视图定义中的子查询和用户的查询结合起来,转换成等价的对基本表的查询,然后再执行修正了的查询。这一转换过程称为视图消解(view resolution)。
例1转换后的查询语句为:
SELECT s_no,s_age
FROM student
WHERE s_major='IS' AND s_age<20;
9.更新视图
更新视图是指通过视图来插入(INSERT)、删除(DELETE)和修改(UPDATE)数据。由于视图是不实际存储数据的虚表,因此对视图的更新最终要转换为对基本表的更新。像查询视图那样,对视图的更新操作也是通过视图消解,转换为对基本表的更新操作。
例1:将信息系学生视图 IS_Student2 中学号为“201215122”的学生姓名改为“刘辰” 。
UPDATE IS_Student2
SET s_name='刘辰'
WHERE s_no='201215122';
转换后的更新语句为:
UPDATE student
SET s_name='刘辰'
WHERE s_no='201215122' AND s_major='IS';
10.建立索引
建立索引的主要作用是提高数据检索的效率,就像书的目录可以帮助你快速找到所需的页面一样。索引是数据库管理系统中的一种数据结构,它能够帮助快速定位到存储在数据表中的特定信息,而不需要扫描整个表。
CREATE [UNIQUE][CLUSTER] INDEX <索引名>
ON <表名>(<列名>[<次序>][,<列名>[<次序>]]…);
例1:假设有一个商品表commodity,给表中商品价格com_price一列设置一个索引com_jiage。
CREATE INDEX com_jiage on commodity(com_price);
11.修改索引
ALTER INDEX <旧索引名> RENAME TO <新索引名>;
例1:修改 commodity 表的 com_jiage 索引为com_jiaqian。
ALTER INDEX com_jiage RENAME TO jiaqian;
12.删除索引
DROP INDEX <索引名>;
例1: 删除commodity表的 com_jiage 索引。
DROP INDEX com_jiage;
13.数据字典
数据字典是关系数据库管理系统内部的一组系统表,它记录了数据库中所有的定义信息,包括关系模式定义、视图定义、索引定义、完整性约束定义、各类用户对数据库的操作权限、统计信息等。关系数据库管理系统在执行SOL的数据定义语句时,实际上就是在更新数据字典表中的相应信息。在进行查询优化和查询处理时,数据字典中的信息是其重要依据。
14.数据查询
一般格式如下:
SELECT [ALL | DISTINCT] <目标列表达式> [别名] [, <目标列表达式> [别名]] ...
FROM <表名或视图名> [别名] [,<表名或视图名>]... | (<SELECT 语句>) [AS] <别名>
[WHERE<条件表达式>]
[GROUPBY <列名1> [HAVING <条件表达式>]]
[ORDER BY <列名2> [ASC | DESC]];
下述表均为虚构表。
DISTINCT
DISTINCT的作用是去重,当一个学生有多门课程不及格,他的学号也只列一次。
例1:查询考试成绩不及格的学生的学号。
SELECT DISTINCT Sno
FROM SC
WHERE Grade<60;
例2:查询年龄不在 20~23 岁(包括20 岁和 23 岁)之间的学生的姓名、系别和年龄。
SELECT Sname,Sdept,Sage
FROM Student
WHERE Sage NOT BETWEEN 20 AND 23;
谓词 IN
IN 可以用来查找属性值属于指定集合的元组。
例1:查询计算机科学系(CS)、数学系(MA)和信息系(IS)学生的姓名和性别。
SELECT Sname,Ssex
FROM Student
WHERE Sdept IN ('CS',MA','IS' );
例1语句等价于:
SELECT Sname, Ssex
FROM Student
WHERE Sdept = 'CS' OR Sdept = 'MA' OR Sdept = 'IS';
此外还要NOT IN 、!=。
谓词 LIKE
LIKE 可以用来进行字符串的匹配。
%(百分号)代表任意长度(长度可以为0)的字符串。
_(下横线)代表任意单个字符
例1:查询所有姓刘的学生的姓名、学号和性别。
SELECT Sname,Sno,Ssex
FROM Student
WHERE Sname LIKE '刘%';
例2:查询姓“欧阳”且全名为三个汉字的学生的姓名。
SELECT Sname
FROM Student
WHERE Sname LIKE'欧阳_';
例3:查询名字中第二个字为“阳”的学生的姓名和学号。
SELECT Sname,Sno
FROM Student
WHERE Sname LIKE'_阳%';
例4:查询所有不姓刘的学生的姓名、学号和性别。
SELECT Sname,Sno,Ssex
FROM Student
WHERE Sname NOT LIKE'刘%';
% 和 _
如果用户要查询的字符串本身就含有通配符 % 或 _ ,这时就要使用 ESCAPE '<换码字符>'短语对通配符进行转义了。
例1:查询 DB_Design 课程的课程号和学分。
SELECT Cno,Ccredit
FROM Course
WHERE Cname LIKE 'DB\_Design' 'ESCAPE'\';
ESCAPE'\'表示“\”为换码字符。这样匹配串中紧跟在“\”后面的字符“”不再具有通配符的含义,转义为普通的“_”字符。
ORDER BY
ORDER BY 子句可以对查询结果按照一个或多个属性列的升序(ASC)或降序(DESC)排列,默认值为升序。
升序在表中从上到下数值越来越大,字母则是以字母"A"开头的单词会放在前面,以"Z"开头的单词会放在后面。
例1:查询选修了3号课程的学生的学号及其成绩,查询结果按分数的降序排列。
SELECT Sno,Grade
FROM SC
WHERE Cno='3'
ORDER BY Grade DESC;
不写 DESC 即 ORDER BY Grade 则按升序排列。
聚集函数
例1:查询学生总人数。
SELECT COUNT(*)
FROM Student;
例2:查询选修了课程的学生人数。
SELECT COUNT(DISTINCT Sno)
FROM SC;
学生每选修一门课,在SC中都有一条相应的记录。一个学生要选修多门课程,为避免重复计算学生人数,必须在COUNT函数中用DISTINCT短语。
例3:计算选修1号课程的学生平均成绩。
SELECT AVG(Grade)
FROM SC
WHERE Cno='1';
GROUP BY子句
书上原句:GROUP BY子句将查询结果按某一列或多列的值分组,值相等的为一组。
我个人不是很理解这句话,但是通过结合后面的sql语句来说,group by会和聚集函数一起使用,例如:求各个课程号及选修该课程的人数,很明显题目要求的是课程号和选此课程号的人数,这个时候就需要进行分组,又例如:查询2019年第2学期选修课程数超过10门的学生学号,很明显题目要求的是 学生学号 ,其中还有两个条件: 2019年第2学期 和 选修课程数超过10门 ,2019年第2学期是对于基本表的条件,超过10门是对于2019年筛选之后的表的再次筛选,2019年第2学期简单用where子句就可以表达,同样超过10门也可以where count(cno)>10表示,但是where子句不用聚集函数作为条件表达式,此时就需要用到having count(cno)>10。
例1:求各个课程号及选修该课程的人数。
select cno, count(sno)
from SC
group by cno;
例2:查询选修了三门以上课程的学生学号。
select sno
from SC
group by sno
having count(cno)>3;
例3:查询平均成绩大于等于90分的学生学号和平均成绩。
select sno, avg(grade)
from SC
group by sno
having avg(grade) >= 90;
对于这三个例子我有为什么要进行分组的疑问,虽说group by会对结果进行去重,但是为什么不能用distinct代替,因为Having子句要和GROUP BY子句联合起来才能使用,Having子句不能单独
使用。而where子句不用聚集函数作为条件表达式,所以必须用having子句,进而必须分组。当然逻辑上也许存在一定关系,不做研究。
例4:查询2019年第2学期选修课程数超过10门的学生学号。
select sno
from SC
where semester='2019/2'
group by sno
having count(cno)>10
15.连接查询
例1:查询选修2号课程且成绩在90分以上的所有学生的学号和姓名。
SELECT Student.Sno, Sname
FROM Student, SC
WHERE Student.Sno=SC.Sno AND SC.Cno='2'AND SC.Grade>90:
例2:查询每个学生的学号、姓名、选修的课程名及成绩。
SELECT Student.Sno, Sname, Cname, Grade
FROM Student, SC, Course
WHERE Student.Sno=SC.Sno AND SC.Cno=Course.Cno;
16.插入数据
例1:将学生张成民的信息插入到 Student 表中。
insert into Student
values (201215126,'张成民','男',18,'CS');
例2:插入一条选课记录('201215128,1)。
若是要插入指定属性值,需要指定属性列。
insert
into SC(Sno,Cno)
values('201215128','1');
四、关系模式的范式判断和规范化
求候选码请参考文章: 一篇文章讲清楚怎么求候选码-优快云博客
范式判断和规范化请参考文章:关系模式的范式判断和规范化-优快云博客
五、数据库设计步骤和E-R图画法
请参考文章:数据库设计步骤、E-R图转关系模式、E-R图的画法-优快云博客
六、语法树优化
请参考文章:数据库语法树优化_语法树 数据库-优快云博客
七、11章、12章知识点
1.事务的特性
原子性(Atomicity)
原子性意味着事务中的所有操作要么全部完成,要么全部不完成。如果事务中的某个操作失败,整个事务将被回滚(撤销),数据库状态回到事务开始之前的状态。这保证了事务是不可分割的单元。
一致性(Consistency)
一致性确保事务从一个一致的状态转移到另一个一致的状态。在事务开始和完成时,数据库的完整性约束不被破坏。
隔离性(Isolation)
隔离性保证了并发执行的事务是彼此隔离的,事务的执行不会被其他事务的操作干扰。
持续性(Durability)
持续性意味着一旦事务被提交,它对数据库的修改就是永久性的,即使发生系统故障也不会丢失。数据库系统通过将事务日志记录到非易失存储介质来保证事务的持续性。
2.故障的种类
事务内部的故障(Transaction Failures)
事务内部的故障指的是事务在执行过程中遇到的问题,导致事务不能继续进行。这类故障可能是由于逻辑错误、数据不一致、违反完整性约束或资源限制(如死锁)等原因造成的。数据库管理系统通常通过事务回滚机制来处理这种故障,以确保数据的一致性和系统的稳定性。
系统故障(System Failures)
系统故障通常指的是操作系统、硬件或软件组件的故障,这会导致正在运行的事务丢失或系统停止工作。例如,电源故障、系统崩溃或网络中断都属于系统故障。为了应对系统故障,数据库系统通常会使用日志文件和检查点(checkpoint)技术来恢复到最近一次一致的状态。
介质故障(Media Failures)
介质故障指的是存储介质(如硬盘驱动器)的物理损坏,这可能会导致存储在介质上的数据部分或全部丢失。对于介质故障,恢复数据通常需要使用备份文件和/或磁盘镜像技术,以复制丢失的数据。
计算机病毒(Computer Viruses)
计算机病毒是一种恶意软件,它可以复制自身并感染其他计算机文件,可能会损坏数据、窃取信息、破坏系统功能或者使系统资源消耗殆尽。
恢复种类则包含:事务故障的恢复、系统故障的恢复、介质故障的恢复。
3.并发操作带来的数据不一致性体现
丢失修改(Lost Update)
丢失修改发生在两个或更多的事务读取同一数据后,其中一个事务的写操作被另一个事务的写操作覆盖,导致第一个事务的更改丢失。这通常发生在没有适当锁机制或并发控制机制的情况下。
示例:假设两个事务T1和T2同时读取了一个账户余额为100。T1将余额更新为150,而T2将余额更新为200。如果T2的更新在T1之后发生,那么T1的修改就会丢失,结果只反映了T2的更新。
不可重复读(Non-repeatable Read)
不可重复读是指一个事务中的两次相同的查询返回了不同的结果集,这是因为另一个并发事务在两次查询间更新了数据。这种现象说明一个事务无法两次读取到同样的数据。
示例:事务T1读取了一个账户的余额为100。在T1没有完成之前,另一个事务T2将该账户的余额更新为200并提交了事务。如果T1再次读取该账户余额,它将会读到200,与它第一次读到的100不一致。
读“脏”数据(Dirty Read)
读“脏”数据是指一个事务读取了另一个事务未提交的数据。如果那个事务失败回滚,读到的数据将是无效的,这可能导致错误的决策和计算。
示例:事务T1修改了一个账户余额为200,但还没有提交事务。这时,事务T2读取了这个账户的余额,结果是200。如果T1因为某些原因回滚了修改,T2读到的200就是一个“脏”数据。
4.封锁、共享锁、排它锁
封锁(Locking)
封锁就是事务T在对某个数据对象操作之前先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其它的事务不能更新此数据对象。
共享锁(S锁,Shared Lock)
共享锁是指当一个事务想要读取数据库中的数据时,它会在这些数据上设置共享锁。共享锁允许多个读事务同时访问同一资源,因为读操作不会改变数据,所以多个事务可以安全地同时进行读取。然而,如果一个事务对数据加了共享锁,其他事务就不能对这些数据加排他锁(即不能写入),直到所有的共享锁都被释放。也就是说,如果事务T对数据加了共享锁,那么所有事务(包括第一个对该数据加锁的事务)对于该数据可读不可写。而且所有事务不能对该数据加排它锁,但所有事务都可以对数据加排它锁。
排他锁(X锁,Exclusive Lock)
排他锁是指当一个事务想要更新或删除数据库中的数据时,它会在这些数据上设置排他锁。排他锁确保没有其他事务可以同时读取或写入被锁定的数据。如果一个数据项被加上排他锁,其他任何事务都不能对其加任何类型的锁。排他锁保证了事务可以安全地更改数据,不会产生丢失修改、不可重复读或脏读等问题。
八、参考资料
王珊 杜小用 陈红. 数据库系统概论(第6版). 高等教育出版社. 2023
https://zh.wikipedia.org/wiki/%E5%85%B3%E7%B3%BB%E6%A8%A1%E5%9E%8B
关系模型_百度百科
第三讲 关系模型之基本概念 · GitBook
数据库中的实体、元组、字段、属性、码、分量、依赖关系、完全部份传递依赖、范式等你了解吗?【笔记自用】_数据实体-优快云博客
MySQL中三级模式和二级映像指的是什么?
笛卡尔积 等值连接 自然连接_哔哩哔哩_bilibili