fix punctuation marks

This commit is contained in:
Gang Yin 2022-01-06 13:42:44 +08:00
parent 072814f29e
commit bbc7bb8d5a
12 changed files with 50 additions and 50 deletions

View File

@ -17,7 +17,7 @@
> >
> —— Vonng > —— Vonng
现今,尤其是在互联网领域,大多数应用都属于数据密集型应用。本书从底层数据结构到顶层架构设计,将数据系统设计中的精髓娓娓道来。其中的宝贵经验无论是对架构师DBA、还是后端工程师、甚至产品经理都会有帮助。 现今,尤其是在互联网领域,大多数应用都属于数据密集型应用。本书从底层数据结构到顶层架构设计,将数据系统设计中的精髓娓娓道来。其中的宝贵经验无论是对架构师DBA、还是后端工程师、甚至产品经理都会有帮助。
这是一本理论结合实践的书,书中很多问题,译者在实际场景中都曾遇到过,读来让人击节扼腕。如果能早点读到这本书,该少走多少弯路啊! 这是一本理论结合实践的书,书中很多问题,译者在实际场景中都曾遇到过,读来让人击节扼腕。如果能早点读到这本书,该少走多少弯路啊!
@ -138,9 +138,9 @@
0. 全文校订 by [@yingang](https://github.com/yingang) 0. 全文校订 by [@yingang](https://github.com/yingang)
1. [序言初翻修正](https://github.com/Vonng/ddia/commit/afb5edab55c62ed23474149f229677e3b42dfc2c) by [@seagullbird](https://github.com/Vonng/ddia/commits?author=seagullbird) 1. [序言初翻修正](https://github.com/Vonng/ddia/commit/afb5edab55c62ed23474149f229677e3b42dfc2c) by [@seagullbird](https://github.com/Vonng/ddia/commits?author=seagullbird)
2. [第一章语法标点校正](https://github.com/Vonng/ddia/commit/973b12cd8f8fcdf4852f1eb1649ddd9d187e3644) by [@nevertiree](https://github.com/Vonng/ddia/commits?author=nevertiree) 2. [第一章语法标点校正](https://github.com/Vonng/ddia/commit/973b12cd8f8fcdf4852f1eb1649ddd9d187e3644) by [@nevertiree](https://github.com/Vonng/ddia/commits?author=nevertiree)
3. [第六章部分校正](https://github.com/Vonng/ddia/commit/d4eb0852c0ec1e93c8aacc496c80b915bb1e6d48) 与[第十章的初翻](https://github.com/Vonng/ddia/commit/9de8dbd1bfe6fbb03b3bf6c1a1aa2291aed2490e) by @[MuAlex](https://github.com/Vonng/ddia/commits?author=MuAlex) 3. [第六章部分校正](https://github.com/Vonng/ddia/commit/d4eb0852c0ec1e93c8aacc496c80b915bb1e6d48) 与[第十章的初翻](https://github.com/Vonng/ddia/commit/9de8dbd1bfe6fbb03b3bf6c1a1aa2291aed2490e) by [@MuAlex](https://github.com/Vonng/ddia/commits?author=MuAlex)
4. [第一部分](part-i.md)前言,[ch2](ch2.md)校正 by [@jiajiadebug](https://github.com/Vonng/ddia/commits?author=jiajiadebug) 4. [第一部分](part-i.md)前言,[ch2](ch2.md)校正 by [@jiajiadebug](https://github.com/Vonng/ddia/commits?author=jiajiadebug)
5. [词汇表](glossary.md)、[后记](colophon.md)关于野猪的部分 by @[Chowss](https://github.com/Vonng/ddia/commits?author=Chowss) 5. [词汇表](glossary.md)、[后记](colophon.md)关于野猪的部分 by [@Chowss](https://github.com/Vonng/ddia/commits?author=Chowss)
6. [繁體中文](https://github.com/Vonng/ddia/pulls)版本与转换脚本 by [@afunTW](https://github.com/afunTW) 6. [繁體中文](https://github.com/Vonng/ddia/pulls)版本与转换脚本 by [@afunTW](https://github.com/afunTW)
7. 感谢所有作出贡献,提出意见的朋友们: 7. 感谢所有作出贡献,提出意见的朋友们:

22
ch2.md
View File

@ -226,7 +226,7 @@ CODASYL中的查询是通过利用遍历记录列和跟随访问路径表在数
#### 哪种数据模型更有助于简化应用代码? #### 哪种数据模型更有助于简化应用代码?
如果应用程序中的数据具有类似文档的结构(即,一对多关系树,通常一次性加载整个树),那么使用文档模型可能是一个好主意。将类似文档的结构分解成多个表(如[图2-1](img/fig2-1.png)中的`positions``education`和`contact_info`)的关系技术可能导致繁琐的模式和不必要的复杂的应用程序代码。 如果应用程序中的数据具有类似文档的结构(即,一对多关系树,通常一次性加载整个树),那么使用文档模型可能是一个好主意。将类似文档的结构分解成多个表(如[图2-1](img/fig2-1.png)中的`positions``education`和`contact_info`)的关系技术可能导致繁琐的模式和不必要的复杂的应用程序代码。
文档模型有一定的局限性例如不能直接引用文档中的嵌套的项目而是需要说“用户251的位置列表中的第二项”很像层次模型中的访问路径。但是只要文件嵌套不太深这通常不是问题。 文档模型有一定的局限性例如不能直接引用文档中的嵌套的项目而是需要说“用户251的位置列表中的第二项”很像层次模型中的访问路径。但是只要文件嵌套不太深这通常不是问题。
@ -286,7 +286,7 @@ UPDATE users SET first_name = substring_index(name, ' ', 1); -- MySQL
自2000年代中期以来大多数关系数据库系统MySQL除外都已支持XML。这包括对XML文档进行本地修改的功能以及在XML文档中进行索引和查询的功能。这允许应用程序使用那种与文档数据库应当使用的非常类似的数据模型。 自2000年代中期以来大多数关系数据库系统MySQL除外都已支持XML。这包括对XML文档进行本地修改的功能以及在XML文档中进行索引和查询的功能。这允许应用程序使用那种与文档数据库应当使用的非常类似的数据模型。
从9.3版本开始的PostgreSQL 【8】从5.7版本开始的MySQL以及从版本10.5开始的IBM DB2 [30]也对JSON文档提供了类似的支持级别。鉴于用在Web APIs的JSON流行趋势其他关系数据库很可能会跟随他们的脚步并添加JSON支持。 从9.3版本开始的PostgreSQL 【8】从5.7版本开始的MySQL以及从版本10.5开始的IBM DB2【30】也对JSON文档提供了类似的支持级别。鉴于用在Web APIs的JSON流行趋势其他关系数据库很可能会跟随他们的脚步并添加JSON支持。
在文档数据库中RethinkDB在其查询语言中支持类似关系的连接一些MongoDB驱动程序可以自动解析数据库引用有效地执行客户端连接尽管这可能比在数据库中执行的连接慢需要额外的网络往返并且优化更少 在文档数据库中RethinkDB在其查询语言中支持类似关系的连接一些MongoDB驱动程序可以自动解析数据库引用有效地执行客户端连接尽管这可能比在数据库中执行的连接慢需要额外的网络往返并且优化更少
@ -541,18 +541,18 @@ db.observations.aggregate([
### 属性图 ### 属性图
在属性图模型中,每个**顶点vertex** 包括: 在属性图模型中每个顶点vertex包括
* 唯一的标识符 * 唯一的标识符
* 一组 **出边outgoing edges** * 一组出边outgoing edges
* 一组 **入边ingoing edges** * 一组入边ingoing edges
* 一组属性(键值对) * 一组属性(键值对)
每条 **edge** 包括: 每条边edge包括
* 唯一标识符 * 唯一标识符
* **边的起点/尾部顶点tail vertex** * 边的起点(**尾部顶点**即tail vertex
* **边的终点/头部顶点head vertex** * 边的终点(**头部顶点**即head vertex
* 描述两个顶点之间关系类型的标签 * 描述两个顶点之间关系类型的标签
* 一组属性(键值对) * 一组属性(键值对)
@ -640,11 +640,11 @@ RETURN person.name
答案是肯定的,但有些困难。在关系数据库中,你通常会事先知道在查询中需要哪些连接。在图查询中,你可能需要在找到待查找的顶点之前,遍历可变数量的边。也就是说,连接的数量事先并不确定。 答案是肯定的,但有些困难。在关系数据库中,你通常会事先知道在查询中需要哪些连接。在图查询中,你可能需要在找到待查找的顶点之前,遍历可变数量的边。也就是说,连接的数量事先并不确定。
在我们的例子中这发生在Cypher查询中的`() -[:WITHIN*0..]-> ()`规则中。一个人的`LIVES_IN`边可以指向任何类型的位置:街道、城市、地区、地区、国家等。城市可以在一个地区,在一个州内的一个地区,在一个国家内的一个州等等。`LIVES_IN`边可以直接指向正在查找的位置,或者一个在位置层次结构中隔了数层的位置。 在我们的例子中这发生在Cypher查询中的`() -[:WITHIN*0..]-> ()`规则中。一个人的`LIVES_IN`边可以指向任何类型的位置:街道、城市、地区、地区、国家等。一个城市可以在WITHIN一个地区内一个地区可以在WITHIN在一个州内一个州可以在WITHIN一个国家内等等。`LIVES_IN`边可以直接指向正在查找的位置,或者一个在位置层次结构中隔了数层的位置。
在Cypher中用`WITHIN * 0`非常简洁地表述了上述事实:“沿着`WITHIN`边,零次或多次”。它很像正则表达式中的`*`运算符。 在Cypher中用`WITHIN*0..`非常简洁地表述了上述事实:“沿着`WITHIN`边,零次或多次”。它很像正则表达式中的`*`运算符。
自SQL:1999查询可变长度遍历路径的思想可以使用称为**递归公用表表达式**`WITH RECURSIVE`语法)的东西来表示。[例2-5]()显示了同样的查询 - 查找从美国移民到欧洲的人的姓名 - 在SQL使用这种技术PostgreSQLIBM DB2Oracle和SQL Server均支持来表述。但是与Cypher相比其语法非常笨拙。 自SQL:1999查询可变长度遍历路径的思想可以使用称为**递归公用表表达式**`WITH RECURSIVE`语法)的东西来表示。[例2-5]()显示了同样的查询 - 查找从美国移民到欧洲的人的姓名 - 在SQL使用这种技术PostgreSQL、IBM DB2、Oracle和SQL Server均支持来表述。但是与Cypher相比其语法非常笨拙。
**例2-5 与示例2-4同样的查询在SQL中使用递归公用表表达式表示** **例2-5 与示例2-4同样的查询在SQL中使用递归公用表表达式表示**

14
ch4.md
View File

@ -70,7 +70,7 @@
因此,除非临时使用,采用语言内置编码通常是一个坏主意。 因此,除非临时使用,采用语言内置编码通常是一个坏主意。
### JSONXML和二进制变体 ### JSONXML和二进制变体
当我们谈到可以被多种编程语言读写的标准编码时JSON和XML是最显眼的角逐者。它们广为人知广受支持也“广受憎恶”。 XML经常收到批评过于冗长与且过份复杂【9】。 JSON的流行则主要源于通过成为JavaScript的一个子集Web浏览器的内置支持以及相对于XML的简单性。 CSV是另一种流行的与语言无关的格式尽管其功能相对较弱。 当我们谈到可以被多种编程语言读写的标准编码时JSON和XML是最显眼的角逐者。它们广为人知广受支持也“广受憎恶”。 XML经常收到批评过于冗长与且过份复杂【9】。 JSON的流行则主要源于通过成为JavaScript的一个子集Web浏览器的内置支持以及相对于XML的简单性。 CSV是另一种流行的与语言无关的格式尽管其功能相对较弱。
@ -148,7 +148,7 @@ Thrift和Protocol Buffers每一个都带有一个代码生成工具它采用
**图4-2 使用Thrift二进制协议编码的记录** **图4-2 使用Thrift二进制协议编码的记录**
[^iii]: 实际上Thrift有三种二进制协议BinaryProtocol、CompactProtocol和DenseProtocol尽管DenseProtocol只支持C ++实现,所以不算作跨语言[18]。 除此之外它还有两种不同的基于JSON的编码格式【19】。 真逗! [^iii]: 实际上Thrift有三种二进制协议BinaryProtocol、CompactProtocol和DenseProtocol尽管DenseProtocol只支持C ++实现,所以不算作跨语言【18】。 除此之外它还有两种不同的基于JSON的编码格式【19】。 真逗!
与[图4-1](Img/fig4-1.png)类似,每个字段都有一个类型注释(用于指示它是一个字符串,整数,列表等),还可以根据需要指定长度(字符串的长度,列表中的项目数) 。出现在数据中的字符串`(“Martin”, “daydreaming”, “hacking”)`也被编码为ASCII或者说UTF-8与之前类似。 与[图4-1](Img/fig4-1.png)类似,每个字段都有一个类型注释(用于指示它是一个字符串,整数,列表等),还可以根据需要指定长度(字符串的长度,列表中的项目数) 。出现在数据中的字符串`(“Martin”, “daydreaming”, “hacking”)`也被编码为ASCII或者说UTF-8与之前类似。
@ -395,7 +395,7 @@ Web浏览器不是唯一的客户端类型。例如在移动设备或桌面
[^vi]: 即使在每个阵营内也有很多争论。 例如,**HATEOAS超媒体作为应用程序状态的引擎** 就经常引发讨论【35】。 [^vi]: 即使在每个阵营内也有很多争论。 例如,**HATEOAS超媒体作为应用程序状态的引擎** 就经常引发讨论【35】。
REST不是一个协议而是一个基于HTTP原则的设计哲学【34,35】。它强调简单的数据格式使用URL来标识资源并使用HTTP功能进行缓存控制身份验证和内容类型协商。与SOAP相比REST已经越来越受欢迎至少在跨组织服务集成的背景下【36】并经常与微服务相关[31]。根据REST原则设计的API称为RESTful。 REST不是一个协议而是一个基于HTTP原则的设计哲学【34,35】。它强调简单的数据格式使用URL来标识资源并使用HTTP功能进行缓存控制身份验证和内容类型协商。与SOAP相比REST已经越来越受欢迎至少在跨组织服务集成的背景下【36】并经常与微服务相关【31】。根据REST原则设计的API称为RESTful。
相比之下SOAP是用于制作网络API请求的基于XML的协议[^vii]。虽然它最常用于HTTP但其目的是独立于HTTP并避免使用大多数HTTP功能。相反它带有庞大而复杂的多种相关标准Web服务框架称为`WS-*`它们增加了各种功能【37】。 相比之下SOAP是用于制作网络API请求的基于XML的协议[^vii]。虽然它最常用于HTTP但其目的是独立于HTTP并避免使用大多数HTTP功能。相反它带有庞大而复杂的多种相关标准Web服务框架称为`WS-*`它们增加了各种功能【37】。
@ -421,7 +421,7 @@ Web服务仅仅是通过网络进行API请求的一系列技术的最新版本
* 每次调用本地功能时,通常需要大致相同的时间来执行。网络请求比函数调用要慢得多,而且其延迟也是非常可变的:好的时候它可能会在不到一毫秒的时间内完成,但是当网络拥塞或者远程服务超载时,可能需要几秒钟的时间完成一样的东西。 * 每次调用本地功能时,通常需要大致相同的时间来执行。网络请求比函数调用要慢得多,而且其延迟也是非常可变的:好的时候它可能会在不到一毫秒的时间内完成,但是当网络拥塞或者远程服务超载时,可能需要几秒钟的时间完成一样的东西。
* 调用本地函数时,可以高效地将引用(指针)传递给本地内存中的对象。当你发出一个网络请求时,所有这些参数都需要被编码成可以通过网络发送的一系列字节。如果参数是像数字或字符串这样的基本类型倒是没关系,但是对于较大的对象很快就会变成问题。 * 调用本地函数时,可以高效地将引用(指针)传递给本地内存中的对象。当你发出一个网络请求时,所有这些参数都需要被编码成可以通过网络发送的一系列字节。如果参数是像数字或字符串这样的基本类型倒是没关系,但是对于较大的对象很快就会变成问题。
- 客户端和服务可以用不同的编程语言实现所以RPC框架必须将数据类型从一种语言翻译成另一种语言。这可能会捅出大篓子因为不是所有的语言都具有相同的类型 —— 例如回想一下JavaScript的数字大于$2^{53}$的问题(请参阅“[JSONXML和二进制变体](#JSONXML和二进制变体)”)。用单一语言编写的单个进程中不存在此问题。 - 客户端和服务可以用不同的编程语言实现所以RPC框架必须将数据类型从一种语言翻译成另一种语言。这可能会捅出大篓子因为不是所有的语言都具有相同的类型 —— 例如回想一下JavaScript的数字大于$2^{53}$的问题(请参阅“[JSON、XML和二进制变体](#JSON、XML和二进制变体)”)。用单一语言编写的单个进程中不存在此问题。
所有这些因素意味着尝试使远程服务看起来像编程语言中的本地对象一样毫无意义,因为这是一个根本不同的事情。 REST的部分吸引力在于它并不试图隐藏它是一个网络协议的事实尽管这似乎并没有阻止人们在REST之上构建RPC库 所有这些因素意味着尝试使远程服务看起来像编程语言中的本地对象一样毫无意义,因为这是一个根本不同的事情。 REST的部分吸引力在于它并不试图隐藏它是一个网络协议的事实尽管这似乎并没有阻止人们在REST之上构建RPC库
@ -469,7 +469,7 @@ RPC方案的前后向兼容性属性从它使用的编码方式中继承
#### 消息代理 #### 消息代理
过去,**消息代理Message Broker** 主要是TIBCOIBM WebSphere和webMethods等公司的商业软件的秀场。最近像RabbitMQActiveMQHornetQNATS和Apache Kafka这样的开源实现已经流行起来。我们将在[第十一章](ch11.md)中对它们进行更详细的比较。 过去,**消息代理Message Broker** 主要是TIBCO、IBM WebSphere和webMethods等公司的商业软件的秀场。最近像RabbitMQ、ActiveMQ、HornetQ、NATS和Apache Kafka这样的开源实现已经流行起来。我们将在[第十一章](ch11.md)中对它们进行更详细的比较。
详细的交付语义因实现和配置而异,但通常情况下,消息代理的使用方式如下:一个进程将消息发送到指定的队列或主题,代理确保将消息传递给那个队列或主题的一个或多个消费者或订阅者。在同一主题上可以有许多生产者和许多消费者。 详细的交付语义因实现和配置而异,但通常情况下,消息代理的使用方式如下:一个进程将消息发送到指定的队列或主题,代理确保将消息传递给那个队列或主题的一个或多个消费者或订阅者。在同一主题上可以有许多生产者和许多消费者。
@ -507,8 +507,8 @@ Actor模型是单个进程中并发的编程模型。逻辑被封装在actor中
我们讨论了几种数据编码格式及其兼容性属性: 我们讨论了几种数据编码格式及其兼容性属性:
* 编程语言特定的编码仅限于单一编程语言,并且往往无法提供前向和后向兼容性。 * 编程语言特定的编码仅限于单一编程语言,并且往往无法提供前向和后向兼容性。
* JSONXML和CSV等文本格式非常普遍其兼容性取决于你如何使用它们。他们有可选的模式语言这有时是有用的有时是一个障碍。这些格式对于数据类型有些模糊所以你必须小心数字和二进制字符串。 * JSONXML和CSV等文本格式非常普遍其兼容性取决于你如何使用它们。他们有可选的模式语言这有时是有用的有时是一个障碍。这些格式对于数据类型有些模糊所以你必须小心数字和二进制字符串。
* 像ThriftProtocol Buffers和Avro这样的二进制模式驱动格式允许使用清晰定义的前向和后向兼容性语义进行紧凑高效的编码。这些模式可以用于静态类型语言的文档和代码生成。但是他们有一个缺点就是在数据可读之前需要对数据进行解码。 * 像ThriftProtocol Buffers和Avro这样的二进制模式驱动格式允许使用清晰定义的前向和后向兼容性语义进行紧凑高效的编码。这些模式可以用于静态类型语言的文档和代码生成。但是他们有一个缺点就是在数据可读之前需要对数据进行解码。
我们还讨论了数据流的几种模式,说明了数据编码重要性的不同场景: 我们还讨论了数据流的几种模式,说明了数据编码重要性的不同场景:

2
ch5.md
View File

@ -545,7 +545,7 @@ PostgreSQL和Oracle等使用这种复制方法【16】。主要缺点是日志
但是,即使在$w + r> n$的情况下,也可能存在返回陈旧值的边缘情况。这取决于实现,但可能的情况包括: 但是,即使在$w + r> n$的情况下,也可能存在返回陈旧值的边缘情况。这取决于实现,但可能的情况包括:
* 如果使用宽松的法定人数(见“[宽松的法定人数与提示移交](#宽松的法定人数与提示移交)”w个写入和r个读取落在完全不同的节点上因此r节点和w之间不再保证有重叠节点【46】。 * 如果使用宽松的法定人数(见“[宽松的法定人数与提示移交](#宽松的法定人数与提示移交)”w个写入和r个读取落在完全不同的节点上因此r节点和w之间不再保证有重叠节点【46】。
* 如果两个写入同时发生,不清楚哪一个先发生。在这种情况下,唯一安全的解决方案是合并并发写入(请参阅“[处理写入冲突](#处理写入冲突)”)。如果根据时间戳(最后写入胜利)挑选出一个胜者,则由于时钟偏差[35],写入可能会丢失。我们将在“[检测并发写入](#检测并发写入)”继续讨论此话题。 * 如果两个写入同时发生,不清楚哪一个先发生。在这种情况下,唯一安全的解决方案是合并并发写入(请参阅“[处理写入冲突](#处理写入冲突)”)。如果根据时间戳(最后写入胜利)挑选出一个胜者,则由于时钟偏差【35】,写入可能会丢失。我们将在“[检测并发写入](#检测并发写入)”继续讨论此话题。
* 如果写操作与读操作同时发生,写操作可能仅反映在某些副本上。在这种情况下,不确定读取是返回旧值还是新值。 * 如果写操作与读操作同时发生,写操作可能仅反映在某些副本上。在这种情况下,不确定读取是返回旧值还是新值。
* 如果写操作在某些副本上成功而在其他节点上失败例如因为某些节点上的磁盘已满在小于w个副本上写入成功。所以整体判定写入失败但整体写入失败并没有在写入成功的副本上回滚。这意味着如果一个写入虽然报告失败后续的读取仍然可能会读取这次失败写入的值【47】。 * 如果写操作在某些副本上成功而在其他节点上失败例如因为某些节点上的磁盘已满在小于w个副本上写入成功。所以整体判定写入失败但整体写入失败并没有在写入成功的副本上回滚。这意味着如果一个写入虽然报告失败后续的读取仍然可能会读取这次失败写入的值【47】。
* 如果携带新值的节点失败需要读取其他带有旧值的副本。并且其数据从带有旧值的副本中恢复则存储新值的副本数可能会低于w从而打破法定人数条件。 * 如果携带新值的节点失败需要读取其他带有旧值的副本。并且其数据从带有旧值的副本中恢复则存储新值的副本数可能会低于w从而打破法定人数条件。

4
ch7.md
View File

@ -226,7 +226,7 @@ SELECT COUNT*FROM emails WHERE recipient_id = 2 AND unread_flag = true
比起盲目地依赖工具,我们应该对存在的并发问题的种类,以及如何防止这些问题有深入的理解。然后就可以使用我们所掌握的工具来构建可靠和正确的应用程序。 比起盲目地依赖工具,我们应该对存在的并发问题的种类,以及如何防止这些问题有深入的理解。然后就可以使用我们所掌握的工具来构建可靠和正确的应用程序。
在本节中,我们将看几个在实践中使用的弱(**非串行的**即nonserializable隔离级别并详细讨论哪种竞争条件可能发生也可能不发生以便你可以决定什么级别适合你的应用程序。一旦我们完成了这个工作我们将详细讨论可串行化请参阅“[可串行化](#可串行化)”)。我们讨论的隔离级别将是非正式的,通过示例来进行。如果你需要严格的定义和分析它们的属性,你可以在学术文献中找到它们[28,29,30] 在本节中,我们将看几个在实践中使用的弱(**非串行的**即nonserializable隔离级别并详细讨论哪种竞争条件可能发生也可能不发生以便你可以决定什么级别适合你的应用程序。一旦我们完成了这个工作我们将详细讨论可串行化请参阅“[可串行化](#可串行化)”)。我们讨论的隔离级别将是非正式的,通过示例来进行。如果你需要严格的定义和分析它们的属性,你可以在学术文献中找到它们【28,29,30】
### 读已提交 ### 读已提交
@ -281,7 +281,7 @@ SELECT COUNT*FROM emails WHERE recipient_id = 2 AND unread_flag = true
出于这个原因,大多数数据库[^vi]使用[图7-4](img/fig7-4.png)的方式防止脏读:对于写入的每个对象,数据库都会记住旧的已提交值,和由当前持有写入锁的事务设置的新值。当事务正在进行时,任何其他读取对象的事务都会拿到旧值。 只有当新值提交后,事务才会切换到读取新值。 出于这个原因,大多数数据库[^vi]使用[图7-4](img/fig7-4.png)的方式防止脏读:对于写入的每个对象,数据库都会记住旧的已提交值,和由当前持有写入锁的事务设置的新值。当事务正在进行时,任何其他读取对象的事务都会拿到旧值。 只有当新值提交后,事务才会切换到读取新值。
[^vi]: 在撰写本文时,唯一在读已提交隔离级别使用读锁的主流数据库是使用`read_committed_snapshot = off`配置的IBM DB2和Microsoft SQL Server [23,36] [^vi]: 在撰写本文时,唯一在读已提交隔离级别使用读锁的主流数据库是使用`read_committed_snapshot = off`配置的IBM DB2和Microsoft SQL Server 【23,36】
### 快照隔离和可重复读 ### 快照隔离和可重复读

View File

@ -1,4 +1,4 @@
# 术语表 【DRAFT】 # 术语表
> 请注意,本术语表中的定义简短而简单,旨在传达核心思想,而不是术语的完整细微之处。 有关更多详细信息,请参阅正文中的参考资料。 > 请注意,本术语表中的定义简短而简单,旨在传达核心思想,而不是术语的完整细微之处。 有关更多详细信息,请参阅正文中的参考资料。

View File

@ -17,7 +17,7 @@
> >
> —— Vonng > —— Vonng
現今,尤其是在網際網路領域,大多數應用都屬於資料密集型應用。本書從底層資料結構到頂層架構設計,將資料系統設計中的精髓娓娓道來。其中的寶貴經驗無論是對架構師DBA、還是後端工程師、甚至產品經理都會有幫助。 現今,尤其是在網際網路領域,大多數應用都屬於資料密集型應用。本書從底層資料結構到頂層架構設計,將資料系統設計中的精髓娓娓道來。其中的寶貴經驗無論是對架構師DBA、還是後端工程師、甚至產品經理都會有幫助。
這是一本理論結合實踐的書,書中很多問題,譯者在實際場景中都曾遇到過,讀來讓人擊節扼腕。如果能早點讀到這本書,該少走多少彎路啊! 這是一本理論結合實踐的書,書中很多問題,譯者在實際場景中都曾遇到過,讀來讓人擊節扼腕。如果能早點讀到這本書,該少走多少彎路啊!
@ -138,9 +138,9 @@
0. 全文校訂 by [@yingang](https://github.com/yingang) 0. 全文校訂 by [@yingang](https://github.com/yingang)
1. [序言初翻修正](https://github.com/Vonng/ddia/commit/afb5edab55c62ed23474149f229677e3b42dfc2c) by [@seagullbird](https://github.com/Vonng/ddia/commits?author=seagullbird) 1. [序言初翻修正](https://github.com/Vonng/ddia/commit/afb5edab55c62ed23474149f229677e3b42dfc2c) by [@seagullbird](https://github.com/Vonng/ddia/commits?author=seagullbird)
2. [第一章語法標點校正](https://github.com/Vonng/ddia/commit/973b12cd8f8fcdf4852f1eb1649ddd9d187e3644) by [@nevertiree](https://github.com/Vonng/ddia/commits?author=nevertiree) 2. [第一章語法標點校正](https://github.com/Vonng/ddia/commit/973b12cd8f8fcdf4852f1eb1649ddd9d187e3644) by [@nevertiree](https://github.com/Vonng/ddia/commits?author=nevertiree)
3. [第六章部分校正](https://github.com/Vonng/ddia/commit/d4eb0852c0ec1e93c8aacc496c80b915bb1e6d48) 與[第十章的初翻](https://github.com/Vonng/ddia/commit/9de8dbd1bfe6fbb03b3bf6c1a1aa2291aed2490e) by @[MuAlex](https://github.com/Vonng/ddia/commits?author=MuAlex) 3. [第六章部分校正](https://github.com/Vonng/ddia/commit/d4eb0852c0ec1e93c8aacc496c80b915bb1e6d48) 與[第十章的初翻](https://github.com/Vonng/ddia/commit/9de8dbd1bfe6fbb03b3bf6c1a1aa2291aed2490e) by [@MuAlex](https://github.com/Vonng/ddia/commits?author=MuAlex)
4. [第一部分](part-i.md)前言,[ch2](ch2.md)校正 by [@jiajiadebug](https://github.com/Vonng/ddia/commits?author=jiajiadebug) 4. [第一部分](part-i.md)前言,[ch2](ch2.md)校正 by [@jiajiadebug](https://github.com/Vonng/ddia/commits?author=jiajiadebug)
5. [詞彙表](glossary.md)、[後記](colophon.md)關於野豬的部分 by @[Chowss](https://github.com/Vonng/ddia/commits?author=Chowss) 5. [詞彙表](glossary.md)、[後記](colophon.md)關於野豬的部分 by [@Chowss](https://github.com/Vonng/ddia/commits?author=Chowss)
6. [繁體中文](https://github.com/Vonng/ddia/pulls)版本與轉換指令碼 by [@afunTW](https://github.com/afunTW) 6. [繁體中文](https://github.com/Vonng/ddia/pulls)版本與轉換指令碼 by [@afunTW](https://github.com/afunTW)
7. 感謝所有作出貢獻,提出意見的朋友們: 7. 感謝所有作出貢獻,提出意見的朋友們:

View File

@ -226,7 +226,7 @@ CODASYL中的查詢是透過利用遍歷記錄列和跟隨訪問路徑表在資
#### 哪種資料模型更有助於簡化應用程式碼? #### 哪種資料模型更有助於簡化應用程式碼?
如果應用程式中的資料具有類似文件的結構(即,一對多關係樹,通常一次性載入整個樹),那麼使用文件模型可能是一個好主意。將類似文件的結構分解成多個表(如[圖2-1](../img/fig2-1.png)中的`positions``education`和`contact_info`)的關係技術可能導致繁瑣的模式和不必要的複雜的應用程式程式碼。 如果應用程式中的資料具有類似文件的結構(即,一對多關係樹,通常一次性載入整個樹),那麼使用文件模型可能是一個好主意。將類似文件的結構分解成多個表(如[圖2-1](../img/fig2-1.png)中的`positions``education`和`contact_info`)的關係技術可能導致繁瑣的模式和不必要的複雜的應用程式程式碼。
文件模型有一定的侷限性例如不能直接引用文件中的巢狀的專案而是需要說“使用者251的位置列表中的第二項”很像層次模型中的訪問路徑。但是只要檔案巢狀不太深這通常不是問題。 文件模型有一定的侷限性例如不能直接引用文件中的巢狀的專案而是需要說“使用者251的位置列表中的第二項”很像層次模型中的訪問路徑。但是只要檔案巢狀不太深這通常不是問題。
@ -286,7 +286,7 @@ UPDATE users SET first_name = substring_index(name, ' ', 1); -- MySQL
自2000年代中期以來大多數關係資料庫系統MySQL除外都已支援XML。這包括對XML文件進行本地修改的功能以及在XML文件中進行索引和查詢的功能。這允許應用程式使用那種與文件資料庫應當使用的非常類似的資料模型。 自2000年代中期以來大多數關係資料庫系統MySQL除外都已支援XML。這包括對XML文件進行本地修改的功能以及在XML文件中進行索引和查詢的功能。這允許應用程式使用那種與文件資料庫應當使用的非常類似的資料模型。
從9.3版本開始的PostgreSQL 【8】從5.7版本開始的MySQL以及從版本10.5開始的IBM DB2 [30]也對JSON文件提供了類似的支援級別。鑑於用在Web APIs的JSON流行趨勢其他關係資料庫很可能會跟隨他們的腳步並新增JSON支援。 從9.3版本開始的PostgreSQL 【8】從5.7版本開始的MySQL以及從版本10.5開始的IBM DB2【30】也對JSON文件提供了類似的支援級別。鑑於用在Web APIs的JSON流行趨勢其他關係資料庫很可能會跟隨他們的腳步並新增JSON支援。
在文件資料庫中RethinkDB在其查詢語言中支援類似關係的連線一些MongoDB驅動程式可以自動解析資料庫引用有效地執行客戶端連線儘管這可能比在資料庫中執行的連線慢需要額外的網路往返並且最佳化更少 在文件資料庫中RethinkDB在其查詢語言中支援類似關係的連線一些MongoDB驅動程式可以自動解析資料庫引用有效地執行客戶端連線儘管這可能比在資料庫中執行的連線慢需要額外的網路往返並且最佳化更少
@ -541,18 +541,18 @@ db.observations.aggregate([
### 屬性圖 ### 屬性圖
在屬性圖模型中,每個**頂點vertex** 包括: 在屬性圖模型中每個頂點vertex包括
* 唯一的識別符號 * 唯一的識別符號
* 一組 **出邊outgoing edges** * 一組出邊outgoing edges
* 一組 **入邊ingoing edges** * 一組入邊ingoing edges
* 一組屬性(鍵值對) * 一組屬性(鍵值對)
每條 **edge** 包括: 每條邊edge包括
* 唯一識別符號 * 唯一識別符號
* **邊的起點/尾部頂點tail vertex** * 邊的起點(**尾部頂點**即tail vertex
* **邊的終點/頭部頂點head vertex** * 邊的終點(**頭部頂點**即head vertex
* 描述兩個頂點之間關係型別的標籤 * 描述兩個頂點之間關係型別的標籤
* 一組屬性(鍵值對) * 一組屬性(鍵值對)
@ -640,11 +640,11 @@ RETURN person.name
答案是肯定的,但有些困難。在關係資料庫中,你通常會事先知道在查詢中需要哪些連線。在圖查詢中,你可能需要在找到待查詢的頂點之前,遍歷可變數量的邊。也就是說,連線的數量事先並不確定。 答案是肯定的,但有些困難。在關係資料庫中,你通常會事先知道在查詢中需要哪些連線。在圖查詢中,你可能需要在找到待查詢的頂點之前,遍歷可變數量的邊。也就是說,連線的數量事先並不確定。
在我們的例子中這發生在Cypher查詢中的`() -[:WITHIN*0..]-> ()`規則中。一個人的`LIVES_IN`邊可以指向任何型別的位置:街道、城市、地區、地區、國家等。城市可以在一個地區,在一個州內的一個地區,在一個國家內的一個州等等。`LIVES_IN`邊可以直接指向正在查詢的位置,或者一個在位置層次結構中隔了數層的位置。 在我們的例子中這發生在Cypher查詢中的`() -[:WITHIN*0..]-> ()`規則中。一個人的`LIVES_IN`邊可以指向任何型別的位置:街道、城市、地區、地區、國家等。一個城市可以在WITHIN一個地區內一個地區可以在WITHIN在一個州內一個州可以在WITHIN一個國家內等等。`LIVES_IN`邊可以直接指向正在查詢的位置,或者一個在位置層次結構中隔了數層的位置。
在Cypher中用`WITHIN * 0`非常簡潔地表述了上述事實:“沿著`WITHIN`邊,零次或多次”。它很像正則表示式中的`*`運算子。 在Cypher中用`WITHIN*0..`非常簡潔地表述了上述事實:“沿著`WITHIN`邊,零次或多次”。它很像正則表示式中的`*`運算子。
自SQL:1999查詢可變長度遍歷路徑的思想可以使用稱為**遞迴公用表表達式**`WITH RECURSIVE`語法)的東西來表示。[例2-5]()顯示了同樣的查詢 - 查詢從美國移民到歐洲的人的姓名 - 在SQL使用這種技術PostgreSQLIBM DB2Oracle和SQL Server均支援來表述。但是與Cypher相比其語法非常笨拙。 自SQL:1999查詢可變長度遍歷路徑的思想可以使用稱為**遞迴公用表表達式**`WITH RECURSIVE`語法)的東西來表示。[例2-5]()顯示了同樣的查詢 - 查詢從美國移民到歐洲的人的姓名 - 在SQL使用這種技術PostgreSQL、IBM DB2、Oracle和SQL Server均支援來表述。但是與Cypher相比其語法非常笨拙。
**例2-5 與示例2-4同樣的查詢在SQL中使用遞迴公用表表達式表示** **例2-5 與示例2-4同樣的查詢在SQL中使用遞迴公用表表達式表示**

View File

@ -70,7 +70,7 @@
因此,除非臨時使用,採用語言內建編碼通常是一個壞主意。 因此,除非臨時使用,採用語言內建編碼通常是一個壞主意。
### JSONXML和二進位制變體 ### JSONXML和二進位制變體
當我們談到可以被多種程式語言讀寫的標準編碼時JSON和XML是最顯眼的角逐者。它們廣為人知廣受支援也“廣受憎惡”。 XML經常收到批評過於冗長與且過份複雜【9】。 JSON的流行則主要源於透過成為JavaScript的一個子集Web瀏覽器的內建支援以及相對於XML的簡單性。 CSV是另一種流行的與語言無關的格式儘管其功能相對較弱。 當我們談到可以被多種程式語言讀寫的標準編碼時JSON和XML是最顯眼的角逐者。它們廣為人知廣受支援也“廣受憎惡”。 XML經常收到批評過於冗長與且過份複雜【9】。 JSON的流行則主要源於透過成為JavaScript的一個子集Web瀏覽器的內建支援以及相對於XML的簡單性。 CSV是另一種流行的與語言無關的格式儘管其功能相對較弱。
@ -148,7 +148,7 @@ Thrift和Protocol Buffers每一個都帶有一個程式碼生成工具它採
**圖4-2 使用Thrift二進位制協議編碼的記錄** **圖4-2 使用Thrift二進位制協議編碼的記錄**
[^iii]: 實際上Thrift有三種二進位制協議BinaryProtocol、CompactProtocol和DenseProtocol儘管DenseProtocol只支援C ++實現,所以不算作跨語言[18]。 除此之外它還有兩種不同的基於JSON的編碼格式【19】。 真逗! [^iii]: 實際上Thrift有三種二進位制協議BinaryProtocol、CompactProtocol和DenseProtocol儘管DenseProtocol只支援C ++實現,所以不算作跨語言【18】。 除此之外它還有兩種不同的基於JSON的編碼格式【19】。 真逗!
與[圖4-1](Img/fig4-1.png)類似,每個欄位都有一個型別註釋(用於指示它是一個字串,整數,列表等),還可以根據需要指定長度(字串的長度,列表中的專案數) 。出現在資料中的字串`(“Martin”, “daydreaming”, “hacking”)`也被編碼為ASCII或者說UTF-8與之前類似。 與[圖4-1](Img/fig4-1.png)類似,每個欄位都有一個型別註釋(用於指示它是一個字串,整數,列表等),還可以根據需要指定長度(字串的長度,列表中的專案數) 。出現在資料中的字串`(“Martin”, “daydreaming”, “hacking”)`也被編碼為ASCII或者說UTF-8與之前類似。
@ -395,7 +395,7 @@ Web瀏覽器不是唯一的客戶端型別。例如在移動裝置或桌面
[^vi]: 即使在每個陣營內也有很多爭論。 例如,**HATEOAS超媒體作為應用程式狀態的引擎** 就經常引發討論【35】。 [^vi]: 即使在每個陣營內也有很多爭論。 例如,**HATEOAS超媒體作為應用程式狀態的引擎** 就經常引發討論【35】。
REST不是一個協議而是一個基於HTTP原則的設計哲學【34,35】。它強調簡單的資料格式使用URL來標識資源並使用HTTP功能進行快取控制身份驗證和內容型別協商。與SOAP相比REST已經越來越受歡迎至少在跨組織服務整合的背景下【36】並經常與微服務相關[31]。根據REST原則設計的API稱為RESTful。 REST不是一個協議而是一個基於HTTP原則的設計哲學【34,35】。它強調簡單的資料格式使用URL來標識資源並使用HTTP功能進行快取控制身份驗證和內容型別協商。與SOAP相比REST已經越來越受歡迎至少在跨組織服務整合的背景下【36】並經常與微服務相關【31】。根據REST原則設計的API稱為RESTful。
相比之下SOAP是用於製作網路API請求的基於XML的協議[^vii]。雖然它最常用於HTTP但其目的是獨立於HTTP並避免使用大多數HTTP功能。相反它帶有龐大而複雜的多種相關標準Web服務框架稱為`WS-*`它們增加了各種功能【37】。 相比之下SOAP是用於製作網路API請求的基於XML的協議[^vii]。雖然它最常用於HTTP但其目的是獨立於HTTP並避免使用大多數HTTP功能。相反它帶有龐大而複雜的多種相關標準Web服務框架稱為`WS-*`它們增加了各種功能【37】。
@ -421,7 +421,7 @@ Web服務僅僅是透過網路進行API請求的一系列技術的最新版本
* 每次呼叫本地功能時,通常需要大致相同的時間來執行。網路請求比函式呼叫要慢得多,而且其延遲也是非常可變的:好的時候它可能會在不到一毫秒的時間內完成,但是當網路擁塞或者遠端服務超載時,可能需要幾秒鐘的時間完成一樣的東西。 * 每次呼叫本地功能時,通常需要大致相同的時間來執行。網路請求比函式呼叫要慢得多,而且其延遲也是非常可變的:好的時候它可能會在不到一毫秒的時間內完成,但是當網路擁塞或者遠端服務超載時,可能需要幾秒鐘的時間完成一樣的東西。
* 呼叫本地函式時,可以高效地將引用(指標)傳遞給本地記憶體中的物件。當你發出一個網路請求時,所有這些引數都需要被編碼成可以透過網路傳送的一系列位元組。如果引數是像數字或字串這樣的基本型別倒是沒關係,但是對於較大的物件很快就會變成問題。 * 呼叫本地函式時,可以高效地將引用(指標)傳遞給本地記憶體中的物件。當你發出一個網路請求時,所有這些引數都需要被編碼成可以透過網路傳送的一系列位元組。如果引數是像數字或字串這樣的基本型別倒是沒關係,但是對於較大的物件很快就會變成問題。
- 客戶端和服務可以用不同的程式語言實現所以RPC框架必須將資料型別從一種語言翻譯成另一種語言。這可能會捅出大簍子因為不是所有的語言都具有相同的型別 —— 例如回想一下JavaScript的數字大於$2^{53}$的問題(請參閱“[JSONXML和二進位制變體](#JSONXML和二進位制變體)”)。用單一語言編寫的單個程序中不存在此問題。 - 客戶端和服務可以用不同的程式語言實現所以RPC框架必須將資料型別從一種語言翻譯成另一種語言。這可能會捅出大簍子因為不是所有的語言都具有相同的型別 —— 例如回想一下JavaScript的數字大於$2^{53}$的問題(請參閱“[JSON、XML和二進位制變體](#JSON、XML和二進位制變體)”)。用單一語言編寫的單個程序中不存在此問題。
所有這些因素意味著嘗試使遠端服務看起來像程式語言中的本地物件一樣毫無意義,因為這是一個根本不同的事情。 REST的部分吸引力在於它並不試圖隱藏它是一個網路協議的事實儘管這似乎並沒有阻止人們在REST之上構建RPC庫 所有這些因素意味著嘗試使遠端服務看起來像程式語言中的本地物件一樣毫無意義,因為這是一個根本不同的事情。 REST的部分吸引力在於它並不試圖隱藏它是一個網路協議的事實儘管這似乎並沒有阻止人們在REST之上構建RPC庫
@ -469,7 +469,7 @@ RPC方案的前後向相容性屬性從它使用的編碼方式中繼承
#### 訊息代理 #### 訊息代理
過去,**訊息代理Message Broker** 主要是TIBCOIBM WebSphere和webMethods等公司的商業軟體的秀場。最近像RabbitMQActiveMQHornetQNATS和Apache Kafka這樣的開源實現已經流行起來。我們將在[第十一章](ch11.md)中對它們進行更詳細的比較。 過去,**訊息代理Message Broker** 主要是TIBCO、IBM WebSphere和webMethods等公司的商業軟體的秀場。最近像RabbitMQ、ActiveMQ、HornetQ、NATS和Apache Kafka這樣的開源實現已經流行起來。我們將在[第十一章](ch11.md)中對它們進行更詳細的比較。
詳細的交付語義因實現和配置而異,但通常情況下,訊息代理的使用方式如下:一個程序將訊息傳送到指定的佇列或主題,代理確保將訊息傳遞給那個佇列或主題的一個或多個消費者或訂閱者。在同一主題上可以有許多生產者和許多消費者。 詳細的交付語義因實現和配置而異,但通常情況下,訊息代理的使用方式如下:一個程序將訊息傳送到指定的佇列或主題,代理確保將訊息傳遞給那個佇列或主題的一個或多個消費者或訂閱者。在同一主題上可以有許多生產者和許多消費者。
@ -507,8 +507,8 @@ Actor模型是單個程序中併發的程式設計模型。邏輯被封裝在act
我們討論了幾種資料編碼格式及其相容性屬性: 我們討論了幾種資料編碼格式及其相容性屬性:
* 程式語言特定的編碼僅限於單一程式語言,並且往往無法提供前向和後向相容性。 * 程式語言特定的編碼僅限於單一程式語言,並且往往無法提供前向和後向相容性。
* JSONXML和CSV等文字格式非常普遍其相容性取決於你如何使用它們。他們有可選的模式語言這有時是有用的有時是一個障礙。這些格式對於資料型別有些模糊所以你必須小心數字和二進位制字串。 * JSONXML和CSV等文字格式非常普遍其相容性取決於你如何使用它們。他們有可選的模式語言這有時是有用的有時是一個障礙。這些格式對於資料型別有些模糊所以你必須小心數字和二進位制字串。
* 像ThriftProtocol Buffers和Avro這樣的二進位制模式驅動格式允許使用清晰定義的前向和後向相容性語義進行緊湊高效的編碼。這些模式可以用於靜態型別語言的文件和程式碼生成。但是他們有一個缺點就是在資料可讀之前需要對資料進行解碼。 * 像ThriftProtocol Buffers和Avro這樣的二進位制模式驅動格式允許使用清晰定義的前向和後向相容性語義進行緊湊高效的編碼。這些模式可以用於靜態型別語言的文件和程式碼生成。但是他們有一個缺點就是在資料可讀之前需要對資料進行解碼。
我們還討論了資料流的幾種模式,說明了資料編碼重要性的不同場景: 我們還討論了資料流的幾種模式,說明了資料編碼重要性的不同場景:

View File

@ -545,7 +545,7 @@ PostgreSQL和Oracle等使用這種複製方法【16】。主要缺點是日誌
但是,即使在$w + r> n$的情況下,也可能存在返回陳舊值的邊緣情況。這取決於實現,但可能的情況包括: 但是,即使在$w + r> n$的情況下,也可能存在返回陳舊值的邊緣情況。這取決於實現,但可能的情況包括:
* 如果使用寬鬆的法定人數(見“[寬鬆的法定人數與提示移交](#寬鬆的法定人數與提示移交)”w個寫入和r個讀取落在完全不同的節點上因此r節點和w之間不再保證有重疊節點【46】。 * 如果使用寬鬆的法定人數(見“[寬鬆的法定人數與提示移交](#寬鬆的法定人數與提示移交)”w個寫入和r個讀取落在完全不同的節點上因此r節點和w之間不再保證有重疊節點【46】。
* 如果兩個寫入同時發生,不清楚哪一個先發生。在這種情況下,唯一安全的解決方案是合併併發寫入(請參閱“[處理寫入衝突](#處理寫入衝突)”)。如果根據時間戳(最後寫入勝利)挑選出一個勝者,則由於時鐘偏差[35],寫入可能會丟失。我們將在“[檢測併發寫入](#檢測併發寫入)”繼續討論此話題。 * 如果兩個寫入同時發生,不清楚哪一個先發生。在這種情況下,唯一安全的解決方案是合併併發寫入(請參閱“[處理寫入衝突](#處理寫入衝突)”)。如果根據時間戳(最後寫入勝利)挑選出一個勝者,則由於時鐘偏差【35】,寫入可能會丟失。我們將在“[檢測併發寫入](#檢測併發寫入)”繼續討論此話題。
* 如果寫操作與讀操作同時發生,寫操作可能僅反映在某些副本上。在這種情況下,不確定讀取是返回舊值還是新值。 * 如果寫操作與讀操作同時發生,寫操作可能僅反映在某些副本上。在這種情況下,不確定讀取是返回舊值還是新值。
* 如果寫操作在某些副本上成功而在其他節點上失敗例如因為某些節點上的磁碟已滿在小於w個副本上寫入成功。所以整體判定寫入失敗但整體寫入失敗並沒有在寫入成功的副本上回滾。這意味著如果一個寫入雖然報告失敗後續的讀取仍然可能會讀取這次失敗寫入的值【47】。 * 如果寫操作在某些副本上成功而在其他節點上失敗例如因為某些節點上的磁碟已滿在小於w個副本上寫入成功。所以整體判定寫入失敗但整體寫入失敗並沒有在寫入成功的副本上回滾。這意味著如果一個寫入雖然報告失敗後續的讀取仍然可能會讀取這次失敗寫入的值【47】。
* 如果攜帶新值的節點失敗需要讀取其他帶有舊值的副本。並且其資料從帶有舊值的副本中恢復則儲存新值的副本數可能會低於w從而打破法定人數條件。 * 如果攜帶新值的節點失敗需要讀取其他帶有舊值的副本。並且其資料從帶有舊值的副本中恢復則儲存新值的副本數可能會低於w從而打破法定人數條件。

View File

@ -226,7 +226,7 @@ SELECT COUNT*FROM emails WHERE recipient_id = 2 AND unread_flag = true
比起盲目地依賴工具,我們應該對存在的併發問題的種類,以及如何防止這些問題有深入的理解。然後就可以使用我們所掌握的工具來構建可靠和正確的應用程式。 比起盲目地依賴工具,我們應該對存在的併發問題的種類,以及如何防止這些問題有深入的理解。然後就可以使用我們所掌握的工具來構建可靠和正確的應用程式。
在本節中,我們將看幾個在實踐中使用的弱(**非序列的**即nonserializable隔離級別並詳細討論哪種競爭條件可能發生也可能不發生以便你可以決定什麼級別適合你的應用程式。一旦我們完成了這個工作我們將詳細討論可序列化請參閱“[可序列化](#可序列化)”)。我們討論的隔離級別將是非正式的,透過示例來進行。如果你需要嚴格的定義和分析它們的屬性,你可以在學術文獻中找到它們[28,29,30] 在本節中,我們將看幾個在實踐中使用的弱(**非序列的**即nonserializable隔離級別並詳細討論哪種競爭條件可能發生也可能不發生以便你可以決定什麼級別適合你的應用程式。一旦我們完成了這個工作我們將詳細討論可序列化請參閱“[可序列化](#可序列化)”)。我們討論的隔離級別將是非正式的,透過示例來進行。如果你需要嚴格的定義和分析它們的屬性,你可以在學術文獻中找到它們【28,29,30】
### 讀已提交 ### 讀已提交
@ -281,7 +281,7 @@ SELECT COUNT*FROM emails WHERE recipient_id = 2 AND unread_flag = true
出於這個原因,大多數資料庫[^vi]使用[圖7-4](../img/fig7-4.png)的方式防止髒讀:對於寫入的每個物件,資料庫都會記住舊的已提交值,和由當前持有寫入鎖的事務設定的新值。當事務正在進行時,任何其他讀取物件的事務都會拿到舊值。 只有當新值提交後,事務才會切換到讀取新值。 出於這個原因,大多數資料庫[^vi]使用[圖7-4](../img/fig7-4.png)的方式防止髒讀:對於寫入的每個物件,資料庫都會記住舊的已提交值,和由當前持有寫入鎖的事務設定的新值。當事務正在進行時,任何其他讀取物件的事務都會拿到舊值。 只有當新值提交後,事務才會切換到讀取新值。
[^vi]: 在撰寫本文時,唯一在讀已提交隔離級別使用讀鎖的主流資料庫是使用`read_committed_snapshot = off`配置的IBM DB2和Microsoft SQL Server [23,36] [^vi]: 在撰寫本文時,唯一在讀已提交隔離級別使用讀鎖的主流資料庫是使用`read_committed_snapshot = off`配置的IBM DB2和Microsoft SQL Server 【23,36】
### 快照隔離和可重複讀 ### 快照隔離和可重複讀

View File

@ -1,4 +1,4 @@
# 術語表 【DRAFT】 # 術語表
> 請注意,本術語表中的定義簡短而簡單,旨在傳達核心思想,而不是術語的完整細微之處。 有關更多詳細資訊,請參閱正文中的參考資料。 > 請注意,本術語表中的定義簡短而簡單,旨在傳達核心思想,而不是術語的完整細微之處。 有關更多詳細資訊,請參閱正文中的參考資料。