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子系统,等等)。]
请记住,配置数据库不只是速度。一致性至少和速度同样重要,因此,您应该仔细考虑您是否要用潜在的数据丢失来和速度交换。
因此,完全理解本章中所述的这些一致性相关的主题是非常重要的。当涉及到您的集群架构,数据安全将是一个重要的组成部分,能够判断是否特定架构对您数据有意义是非常可取的。毕竟,数据库的工作就是保护数据。您的耐久性要求的意识绝对是一个大的好处。
PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(3)的更多相关文章
- PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(4)
2.4 调整检查点和XLOG 目前为止,这一章已经提供深入洞察PostgreSQL如何写入数据,一般来说,XLOG是用来干什么的.考虑到这方面的知识,我们现在可以继续并学习我们能做些什么来使我们的数据 ...
- PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(1)
在前面的章节中,我们已经理解了各种复制概念.这不仅仅是一个为了接下来将要介绍的东西而增强您的意识的理论概述,还将为您介绍大体的主题. 在本章,我们将更加接近实际的解决方案,并了解PostgreSQL内 ...
- PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(5)
2.5 XLOG的内部结构 我们将使用事务贯穿本书,并让您在技术层面上更深地洞察事情是如果工作的,我们已经增加了这部分专门处理XLOG的内部工作机制.我们会尽量避免前往下降到C级,因为这将超出本书的范 ...
- PostgreSQL Replication之第二章 理解PostgreSQL的事务日志(2)
2.2 XLOG和复制 在本章中,您已经了解到PostgreSQL的事务日志已经对数据库做了所有的更改.事务日志本身被打包为易用的16MB段. 使用这种更改集来复制数据的想法是不牵强的.事实上,这是在 ...
- PostgreSQL Replication之第一章 理解复制概念(1)
PostgreSQL Replication系列翻译自PostgreSQL Replication一书 在本章中,将会介绍不同的复制概念,您会了解哪些类型的复制对哪一种实用场景是最合适的. 在本章的最 ...
- PostgreSQL Replication之第一章 理解复制概念(3)
1.3 使用分片和数据分配 本节您将了解基本可扩展性技术,例如数据库分片.分片被广泛应用于高端系统并提供一个简单而且可靠的扩展设置方式来向外扩展.近年来,分片已经成为一种扩大专业系统规模的标准方式. ...
- PostgreSQL Replication之第一章 理解复制概念(2)
1.2不同类型的复制 现在,您已经完全地理解了物理和理论的局限性,可以开始学习不同类型的复制了. 1.2.1 同步和异步复制 我们可以做的第一个区分是同步复制和异步复制的区别. 这是什么意思呢?假设我 ...
- PostgreSQL Replication之第九章 与pgpool一起工作(6)
9.6 运行pgpool和流复制 pgpool也可以和除了语句级别的复制之外的流复制一起使用.一个完美的方案是使用PostgreSQL的板载复制和仅仅使用pgpool的负载均衡与连接池. 实际上,这样 ...
- PostgreSQL Replication之第九章 与pgpool一起工作(7)
9.7 处理故障转移和高可用 可以使用pgpool来解决的一些明显的问题是高可用性和故障转移.一般来讲,有使用pgpool或者不使用pgpool可以用来处理这些问题的各种方法. 9.7.1 使用Pos ...
随机推荐
- iOS知识点汇总
1.怎样追踪app崩溃率.怎样解决线上闪退 当iOS设备上的App应用闪退时.操作系统会生成一个crash日志.保存在设备上.crash日志上有非常多实用的信息,比方每个正在运行线程的完整堆栈跟踪信息 ...
- 嵌入式外部中断控制编程方法论—比較CC2541(51核)和S5PV210(ARM核)
这是一篇阐述怎样对嵌入式SOC外部中断进行控制编程的方法论文章.希望读者理解本篇文章后.能够具备对市场上全部已经面世和将来面世的嵌入式芯片的外部中断进行控制编程的能力. 笔者原创的技术分享一直都恪守下 ...
- HD-ACM算法专攻系列(4)——A == B ?
题目描述: 源码: /**/ #include"iostream" #include"string" using namespace std; string S ...
- setUserVisibleHint的使用.执行顺序和viewPager.setOffscreenPageLimit(0)不管用还是默认会加载第二个fragment
处理问题一:viewPager.setOffscreenPageLimit(0)不管用还是默认会加载第二个fragment的原因(源码解读); 处理问题二:setUserVisibleHint的使用场 ...
- java 获取线程id
如何获取正在运行的线程的ID? 解决方法 下面的示例演示如何使用getThreadId() 方法一个正在运行线程的ID. public class Main extends Object implem ...
- HDU 1285 确定比赛名次【拓扑排序】
题意:中文的题目-----这道题让我终于明白了那个break的作用---因为题目中有这一句“符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前”@_@ #include<iostrea ...
- win10关闭更新
计算机--管理: 找到windows update 服务关闭:
- php时间差方法
/** * 时间差计算 * * @param Timestamp $time * @return String Time Elapsed */ function time2Units ($time,$ ...
- maven使用技巧
转:MAVEN常用命令 Maven库: http://repo2.maven.org/maven2/ Maven依赖查询: http://mvnrepository.com/ Maven常用命令: 1 ...
- 越努力越幸运--3-日常bug修复
提供一个so给PYTHON调用,后端发现业务处理流程不是按照方法传入的参数来跑. 查看c的代码,看了客户端没看出什么问题,查看服务端为什么会出现这样的情况,有些字段明显不是入参带过来的,跟踪服务端解析 ...