EagleBear2002 的博客

这里必须根绝一切犹豫,这里任何怯懦都无济于事

商业事务与系统事务

商业活动(Business Activity):例如,用户浏览产品目录,选中了一瓶价格很实惠的 Talisker 威士忌,填入信用卡信息,然后确认订单。

需要确保最终一致性,但是出于时间、交互的考虑,无法使用事务加以实现

  1. 如使用事务实现,必须锁住数据库中各个元素。而长时间锁定元素是不现实的。
  2. 因此,应用程序通常只在处理完用户交互操作之后才开始系统事务,这样的话,锁定时间就比较短了。
  3. 然而当需要计算和决策的时候,数据有可能已经改动了。价格表上 Talisker 威士忌的售价也许已经变了,或是某人可能会修改客户的地址,从而导致运费改变

条件更新(conditional update),客户端执行操作时,将重新读取商业活动所依赖的信息,并检测该信息在首次读取之后是否一直没有变动,若一直未变,则将其展示给用户。

阅读全文 »

关系型数据库试图通过强一致性来避免各种不一致的问题。NoSQL 领域则讨论 CAP 定理和最终一致性。

更新一致性

  1. 写冲突:当两个客户端试图同时修改一份数据时
  2. 读写冲突:当某客户端在另一个客户端执行写入操作的过程中读取数据时

解决方式:

  1. 悲观处理:使用写入锁避免冲突,大幅降低系统反应能力
  2. 乐观处理:在事后检测冲突并将其修复,条件更新(conditional update):任意客户在执行更新操作之前,都要先测试数据的当前值和其上一次读入的值是否相同
  3. 乐观处理:保存冲突数据 。用户自行合并(merge)或自动合并(面向特定领域),用于分布式版本控制系统
阅读全文 »

单一服务器

分片

把数据的各个部分存放于不同的服务器中,以此实现横向扩展。该技术称为分片。

分片
  1. 分片可以同时提升读取与写入效率
  2. 分片对改善数据库的故障恢复能力帮助并不大。
阅读全文 »

聚合

在领域驱动设计中,把一组相互关联的对象视为一个整体单元来操作,而这个单元就叫聚合(aggregate)。

  1. 通过原子操作(atomic operation)新聚合的值(含一致性管理)。
  2. 以聚合为单位与数据存储通信
  3. 在集群中操作数据库时,用聚合为单位来复制和分片
  4. 由于程序员经常通过聚合结构来操作数据,故而采用聚合也能让其工作更为轻松
  5. 面向聚合操作数据时所用的单元,其结构比元组集合复杂得多
关系模型
聚合数据模型
阅读全文 »

关系型数据库的价值

阻抗失谐

基于关系代数(relational algebra),关系模型把数据组织成关系(relation)和元组(tuple)。元组是由键值对(name-value pair)构成的集合,而关系则是元组的集合。

SQL 操作所使用及返回的数据都是关系元组不能包含嵌套记录(nested record)或列表(list)等任何结构。而内存中的数据结构则无此限制,它可以使用的数据组织形式比关系更丰富。

关系模型和内存中的数据结构之间存在差异。这种现象通常称为阻抗失谐

阅读全文 »

事务

事务(Transaction,缩写 txn)是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位。

事务是恢复和并发控制的基本单位。

事务的 ACID 特性:

  • 原子性(Atomicity):事务是数据库的逻辑工作单位,事务中包括的诸操作要么都做,要么都不
  • 一致性(Consistency)
  • 隔离性(Isolation)
  • 持续性(Durability)
阅读全文 »

关系模式及范式

关系模式由五部分组成,是一个五元组: \(R(U, D, \textup{DOM}, F)\)

  1. 关系名 \(R\) 是符号化的元组语义
  2. \(U\) 为一组属性
  3. \(D\) 为属性组 \(U\) 中的属性所来自的域
  4. \(\textup{DOM}\) 为属性到域的映射
  5. \(F\) 为属性组 \(U\) 上的一组数据依赖

由于 \(D\)\(\textup{DOM}\) 与模式设计关系不大,因此可以把关系模式看作一个三元组:$R U, F $

作为二维表,关系要符合一个最基本的条件:每个分量必须是不可分开的数据项。满足了这个条件的关系模式就属于第一范式(1NF)。

阅读全文 »

实体完整性

参照完整性

用户定义的完整性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# [例 5.7] Student 表的 Ssex 只允许取“男”或“女”。
CREATE TABLE Student
(
Sno CHAR(9) PRIMARY KEY,
Sname CHAR(8) NOT NULL,
Ssex CHAR(2) CHECK (Ssex IN ('男', '女')), /*性别属性 Ssex 只允许取'男'或'女' */
Sage SMALLINT,
Sdept CHAR(20)
);

# [例 5.8] SC 表的 Grade 的值应该在 0100 之间。
CREATE TABLE SC
(
Sno CHAR(9),
Cno CHAR(4),
Grade SMALLINT CHECK (Grade >= 0 AND Grade <= 100), /*Grade 取值范围是 0 到 100*/
PRIMARY KEY (Sno, Cno),
FOREIGN KEY (Sno) REFERENCES Student (Sno),
FOREIGN KEY (Cno) REFERENCES Course (Cno)
);

# [例 5.9]当学生的性别是男时,其名字不能以 Ms.打头。
CREATE TABLE Student
(
Sno CHAR(9),
Sname CHAR(8) NOT NULL,
Ssex CHAR(2) CHECK (Ssex IN ('男', '女')),
Sage SMALLINT,
Sdept CHAR(20),
PRIMARY KEY (Sno),
CHECK (Ssex = '女' OR Sname NOT LIKE 'Ms.%') /*定义了元组中 Sname 和 Ssex 两个属性值之间的约束条件*/
);

# [例 5.10]建立学生登记表 Student,要求学号在 90000~99999 之间,姓名不能取空值,年龄小于 30,性别只能是“男”或“女”。
CREATE TABLE Student
(
Sno NUMERIC(6) CONSTRAINT C1 CHECK (Sno BETWEEN 90000 AND 99999),
Sname CHAR(20) CONSTRAINT C2 NOT NULL,
Sage NUMERIC(3) CONSTRAINT C3 CHECK (Sage < 30),
Ssex CHAR(2) CONSTRAINT C4 CHECK (Ssex IN ( ‘男’,'女')),
CONSTRAINT StudentKey PRIMARY KEY (Sno)
);

# [例 5.11]建立教师表 TEACHER,要求每个教师的应发工资不低于 3000 元。应发工资是工资列 Sal 与扣除项 Deduct 之和。
CREATE TABLE TEACHER
(
Eno NUMERIC(4) PRIMARY KEY, /*在列级定义主码*/
Ename CHAR(10),
Job CHAR(8),
Sal NUMERIC(7, 2),
Deduct NUMERIC(7, 2),
Deptno NUMERIC(2),
CONSTRAINT TEACHERFKey FOREIGN KEY (Deptno)
REFERENCES DEPT (Deptno),
CONSTRAINT C1 CHECK (Sal + Deduct >= 3000)
);

# [例 5.12]去掉例 5.10 Student 表中对性别的限制。
ALTER TABLE Student
DROP CONSTRAINT C4;
# [例 5.13] 修改表 Student 中的约束条件,要求学号改为在 900000~999999 之间,年龄由小于 30 改为小于 40 可以先删除原来的约束条件,再增加新的约束条件
ALTER TABLE Student
DROP CONSTRAINT C1;
ALTER TABLE Student
ADD CONSTRAINT C1 CHECK (Sno BETWEEN 900000 AND 999999);
ALTER TABLE Student
DROP CONSTRAINT C3;
ALTER TABLE Student
ADD CONSTRAINT C3 CHECK (Sage < 40);

完整性约束命名子句

阅读全文 »