PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(3)

2.3 理解一致性和数据丢失

挖掘PostgreSQL事务日志而不考虑一致性是不可能的。在本章的第一部分,我们已经大体上解释了事务日志的基本思想。您已经知道,无需事先的日志改变的能力,使数据处于一种好的形状是很难甚至是不可能的。

到现在为止,我们大多都在讨论崩溃的问题。因为数据文件中的条目的损坏而丢失文件是绝对不好的。但是,崩溃不是您要关心的唯一问题。另外两个重要的主题是:

• 性能

• 数据丢失

虽然这可能是一个重要的主题的明显的选择,我们有这样的感觉,这两个主题都不好理解,是受尊敬的,并因此需要考虑。

在我们的日常业务为PostgreSQL咨询专家和培训师,我们通常会看到那些只专注于性能的人。

Performance is everything, we want to be fast; tell us how to be fast…

潜在的数据丢失,或者甚至是一个来处理它的概念的意识。对许多人来说,这看起来是新东西。我们这样看:如果数据丢失甚至更快有什么好处呢?这样做的关键不是性能不重要;性能是非常重要的。然而,我们只是想指出性能不是全局中唯一的组成部分。

2.3.1 到磁盘的路径

要了解关于数据丢失和一致性的问题,我们要看看一个数据块是如何被送到磁盘的。下图说明了这是如何工作的:

当PostgreSQL要读取或者写入一个块是,它通常要经过几个层次。当一个块被写入,它将被发送到操作系统。操作系统将缓存数据并对数据执行写操作。在有些时候,操作系统将决定把数据传到一些低层次。这可能是磁盘控制器。磁盘控制器将缓存,重新排序,在数据最终到真实的物理存储设备之前,可能还有一个缓存层。

在我们的例子中,我们使用了四层。在许多企业级系统中,甚至可能有更多的层次。试想一个虚拟机,存储通过网络挂载,例如,SAN,NAS,NFS,ATA-over_Ethernet,iSCSI,等等。许多抽象层都会有数据通过,并且每层都将尝试做自己那部分的优化。

从内存到内存

当PostgreSQL给操作系统传递一个8K的块时,发生了什么?这个问题唯一正确的答案可能是:“有事情”。当一个到文件的写被执行时,绝对不能保证数据被实际送到磁盘。

在现实中,写入文件无非就是从PostgreSQL内存的复制操作到一些系统内存。这两个内存区域都在内存中,因此,在崩溃的情况下,东西可能丢失。从实践上来说,如果整个内存由于故障而不能工作,谁丢失了数据没有什么区别。

下面的代码片段说明了我们所面临的基本问题:

test=# \d t_test

Table "public.t_test"

Column | Type | Modifiers

--------+---------+-----------

id | integer |

test=# BEGIN;

BEGIN

test=# INSERT INTO t_test VALUES (1);

INSERT 0 1

test=# COMMIT;

COMMIT

就像在前面章节中,我们使用只有一列的表。目标是运行一个插入一行的事务。

如果在提交不久之后,发生了崩溃,没有数据会处于危险之中,因为什么都没有发生。如果崩溃在一个INSERT语句之后,但在COMMIT之前,没有什么会发生。用户还没有发出COMMIT,因此该事务是众所周知的要运行,但没有完成。如果发生崩溃,应用程序将注意到事情是不成功的,并(希望)做出相应的反应。

然而,情况是完全不同的,如果用户已经发出了COMMIT语句,它已经成功返回。无论发生什么,用户将期望提交的数据是可用的。

[用户期望成功的写入在意外重新启动后是可用的。所谓的ACID标准也要求持久性。在计算机科学中,ACID(原子性,一致性,隔离性,耐久性)是一组属性,这些属性保证数据库事务可靠地处理。]

从内存到磁盘

要确保内核将数据从内存传递到磁盘,PostgreSQL必须采取一些预防措施。在 COMMIT,系统调用将被发起,它强制数据到事务日志中。

[在这一点上,PostgreSQL没有必要强制数据到数据文件,因为我们总能从XLOG修复坏的数据文件。如果数据被安全地存储在XLOG中,事务可以被认为是安全。]

必要的强制数据到磁盘的系统调用是fsync()。一些列表是从BSD手册页复制过来的。在我们看来,这是所写过的处理这个主题的最好的手册页之一:

FSYNC(2) BSD System Calls Manual FSYNC(2)

NAME

fsync -- synchronize a file‘s in-core state with

that on disk

SYNOPSIS

#include <unistd.h>

int fsync(intfildes);

DESCRIPTION

Fsync() causes all modified data and attributes of fildes to be moved to a permanent storage device.This normally results in all in-core modified

copies of buffers for the associated file to be written to a disk.

Note that while fsync() will flush all data from the host to the drive (i.e. the "permanent storage device"), the drive itself may not physically

write the data to the platters for quite some time and it may be written in an out-of-order sequence.Specifically, if the drive loses power or the OS

crashes, the application may find that only some or none of their data was written. The disk drive may also re-order the data so that later writes

may be present, while earlier writes are not.This is not a theoretical edge case. This scenario is easily reproduced with real world workloads

and drive power failures.

它本质上说,内核试图使它在内存中文件的映像与磁盘上的文件映像一致。它通过所有的改变到存储设备来实现。它也清楚地指出,我们在这里不是在谈论一个理论场景,刷回磁盘是一个非常重要的话题。

在COMMIT没有磁盘刷新,您根本无法确保您的数据安全,这意味着,在非常麻烦的情况下,您实际上会丢失数据。

而且,本质上重要的是速度和一致性;它们实际上是相对立的工作。刷回改变到磁盘尤其昂贵,因为这涉及到真实的硬件。我们的开销并不是5%,而是多了很多。随着SSD的引进,开销已经大幅下降,但是它仍然是可观的。

关于电池的一句话

大多数生产服务器将使用RAID控制器来管理磁盘。这里重要的一点是,磁盘刷新和性能通常和RAID控制器关系较紧密。如果RAID控制器没有电池,这是通常的情况,那么它需要长时间疯狂地刷新。RAID控制器必须等待最慢的磁盘的返回。然而,如果电池是可用的话,RAID控制器可以假定一个功率损耗,不会阻止一旦电被恢复的话一个公认的磁盘写完成。这样控制器可以缓存写和简单地伪装刷新。因此,一个简单的电池可以很容易地将性能提高十倍。

[请记住,我们在本节所阐述的是一般的问题。但是,每个硬件都是不同的。我们强烈推荐您检查和了解您的硬件以及RAID配置,看看刷新是如何处理的。]

超越 fsync()

fsync()不是唯一把数据刷新到磁盘的系统调用。根据您正在使用的操作系统,不同的刷新调用都是可用的。在PostgreSQL中您可以通过改变wal_sync_method来决定您首选的刷新系统。同样,这个改变可以通过调整postgresql.conf来进行。

可用的方法是 open_datasync, fdatasync, fsync, fsync_writethrough, 以及 open_sync。

[如果您要改变这些值,我们强烈建议您查看您正在使用的操作系统的手册页,以确保您已经做了正确的选择。]

2.3.2 PostgreSQL的一致性级别

确保一致性和防止数据丢失是昂贵的;每个磁盘刷新都是昂贵的,在刷新到磁盘之前,我们应该三思而后行。为了给用户选择,PostgreSQL提供了多种级别的数据保护。这些不同的选择由两个重要的参数代表,这可以在postgresql.conf中找到:

1. fsync

2. synchronous_commit
如果fsync被使用的话,fsync参数将控制数据丢失。在缺省配置中,PostgreSQL将始终刷新提交到磁盘。如果fsync处于关闭状态,然而,不能保证COMMIT会幸免于崩溃。数据会丢失,甚至可能会有数据损坏。要保护您的数据,保持fsync处于打开的状态是必须的。如果您能承受失去一部分或者全部数据,您可以放松刷新标准。

synchronous_commit
和XLOG-writing 相关。通常情况下, PostgreSQL 将等待,直到数据已完全被写入到XLOG。尤其是短事务可以承受的相当多,因此,提供了各种不同的选择:

• on: PostgreSQL将一直等到 XLOG 已经完全成功地写入。 如果您要存储信用卡数据,您要确保金融事务部丢失。在这种情况下,刷新到磁盘是必不可少的。

• off: 在给客户报告成功和安全地写入磁盘之间有一个时间差。在这样的情况下,可以有损坏。让我们假设一个存储在一个网站上当前谁在线的数据库。假设您的系统崩溃了,20分钟后又恢复了。您真的在乎您的数据吗?20分钟后,每个人都有可能再次来回登录。这不值得牺牲性能来保护在几分钟后就过时的数据。

• local:在复制数据库实例的情况下,我们将只等待本地实例刷新到磁盘。这里的好处是,您有一个高级别的保护,因为您刷新到一个磁盘;然而,我们可以放心地假设不会有两台服务器同时崩溃,因此我们可以就可以放松一点slave 上的标准。

• remote_write: PostgreSQL 将一直等到同步备用服务器为给定的事务报告成功。

在协议中设置fsync 为 off,改变 synchronous_commit 为 off 将不会导致崩溃。然而,在崩溃的情况下,我们可能会丢失一些事务,它们已经被成功提交了。 潜在的数据丢失的数量由一个额外的 postgresql.conf 中叫 wal_writer_delay管理。在把synchronous_commit 设置为off的情况下, 我们失去的永远都不会比在wal_writer_delayconfig变量中定义的多。

[更改synchronous_commit 可能看起来像一个小的性能调整;然而,在现实中,当运行次小的写事务时,更改 sync 行为是主导因素之一,增益可能不只有几个百分点,但是,如果您幸运的话,它可能是十倍或者甚至更多(取决于硬件,工作负载,I/O子系统,等等)。]

请记住,配置数据库不只是速度。一致性至少和速度同样重要,因此,您应该仔细考虑您是否要用潜在的数据丢失来和速度交换。

因此,完全理解本章中所述的这些一致性相关的主题是非常重要的。当涉及到您的集群架构,数据安全将是一个重要的组成部分,能够判断是否特定架构对您数据有意义是非常可取的。毕竟,数据库的工作就是保护数据。您的耐久性要求的意识绝对是一个大的好处。

原文地址:http://www.cnblogs.com/songyuejie/p/4743332.html

时间: 2024-10-08 19:35:09

PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(3)的相关文章

PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(4)

2.4 调整检查点和XLOG 目前为止,这一章已经提供深入洞察PostgreSQL如何写入数据,一般来说,XLOG是用来干什么的.考虑到这方面的知识,我们现在可以继续并学习我们能做些什么来使我们的数据库在复制和单台服务器运行的两种情况更加有效的工作. 2.4.1 理解检查点 在本章中,我们已经看到在数据可能到其它地方之前,它已经被写入到了XLOG.问题是,如果XLOG从未被删除,显然,在没有填满磁盘的同一时间,我们不会永远写到XLOG中. 要解决这个问题,XLOG必须在某一时刻被删除.这个过程就

PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(1)

在前面的章节中,我们已经理解了各种复制概念.这不仅仅是一个为了接下来将要介绍的东西而增强您的意识的理论概述,还将为您介绍大体的主题. 在本章,我们将更加接近实际的解决方案,并了解PostgreSQL内部是如何工作的,复制意味着什么.我们将看到所谓的事务日志(XLOG)做什么,以及它是如何运作的.XLOG在PostgreSQL复制机制中起着主要作用.理解这部分是如何工作的是必要的. 2.1 PostgreSQL如何写入数据 PostgreSQL的复制完全是关于写入数据的.因此,PostgreSQL

PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(5)

2.5 XLOG的内部结构 我们将使用事务贯穿本书,并让您在技术层面上更深地洞察事情是如果工作的,我们已经增加了这部分专门处理XLOG的内部工作机制.我们会尽量避免前往下降到C级,因为这将超出本书的范围,但我们会为您提供希望足够深的见解. 2.5.1 理解XLOG记录 对XLOG所做的更改是基于记录的.这意味着什么?让我们假设您在给一个表添加一行数据: test=# INSERT INTO t_test VALUES (1, 'hans'); INSERT 0 1 在这个例子中,我们正在插入一个

PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(2)

2.2 XLOG和复制 在本章中,您已经了解到PostgreSQL的事务日志已经对数据库做了所有的更改.事务日志本身被打包为易用的16MB段. 使用这种更改集来复制数据的想法是不牵强的.事实上,这是在每个关系(或者甚至非关系)数据库系统的发展的一个逻辑步骤.本书的其它部分,您将在许多方面看到PostgreSQL事务日志可以如何以许多不同的方法被使用,获取,存储,复制,和分析. 在大多数的复制系统中,PostgreSQL事务日志是整个体系结构(用于同步复制和异步复制)的的骨干.

PostgreSQL Replication之第一章 理解复制概念(1)

PostgreSQL Replication系列翻译自PostgreSQL Replication一书 在本章中,将会介绍不同的复制概念,您会了解哪些类型的复制对哪一种实用场景是最合适的. 在本章的最后,您将能够判断某个概念在各种情况下是否是可行的. 我们在本章将介绍以下主题: • CAP理论 •复制的物理限制 •为什么延迟有影响 •同步和异步复制 •拆分和复制 在我们使用PostgreSQL实际工作之前,我们将引导您完成一些非常基本的与复制相关想法和事实. 1.1 CAP理论和物理限制 您可能

PostgreSQL Replication之第一章 理解复制概念(3)

1.3 使用分片和数据分配 本节您将了解基本可扩展性技术,例如数据库分片.分片被广泛应用于高端系统并提供一个简单而且可靠的扩展设置方式来向外扩展.近年来,分片已经成为一种扩大专业系统规模的标准方式. 1.3.1 理解分片的目的 如果您的数据量增长超过一台机器的处理能力将会发生什么事情?如果您要运行这么多的事务,一台服务器根本跟不上怎么办?我们假设您有百万级的用户,上万用户想在同一时间执行特定的任务. 显然,某些时候,您再也不能通过购买能够处理无限大的负载的足够大的服务器来解决问题.显然在单个服务

PostgreSQL Replication之第一章 理解复制概念(2)

1.2不同类型的复制 现在,您已经完全地理解了物理和理论的局限性,可以开始学习不同类型的复制了. 1.2.1 同步和异步复制 我们可以做的第一个区分是同步复制和异步复制的区别. 这是什么意思呢?假设我们有两台服务器,希望从一台服务器(the master)复制数据到第二台服务器(the slave).下图说明了同步和异步复制的概念: 我们可以使用一个简单的事务如下所示: BEGIN: INSERT INTO foo VALUES ('bar'); COMMIT; 在异步复制的情况下,事务被提交到

疯狂JAVA——第二章 理解面向对象

面向对象的三大特征:继承.封装和多态 面向对象的方式实际上由OOA(面向对象分析).OOD(面向对象设计)和OOP(面相对象编程)三个部分组成,其中OOA和OOD的结构需要用一个描述方式来描述并记录,目前业界统一采用UML(统一建模语言)来描述并记录OOA和OOD的结果. 面向对象和基于对象的区别:基于对象也是用了对象,但无法利用现有的对象模板产生新的对象类型,也就是说,基于对象没有继承和多态.JavaScript就是基于对象的. java语言中,除了8个基本数据类型以外,一切都是对象. 一般-

第二章.理解面向对象

面向对象语言的三个基本特征:封装(Encapsulation).继承(Inheritance).多态(Polymorphism) 封装:将对象的实现细节隐藏起来,然后通过一些公用方法来暴露该对象的功能 继承:实现软件复用的手段,当子类继承父类后,子类作为一种特殊的父类,将直接获得父类的属性和方法 多态:子类对象可以直接赋给父类变量,但运行时依然表现出子类的行为特征,意味着同一个类型的对象在执行同一个方法时,可能表现出多种行为特征. 抽象:忽略一个主题中与当前目标无关的那些方面,抽象并不打算了解全