1、事务的概念
   事务是从实际生活中引入数据库的一个概念,即事务内的操作,要么全做,要么全不做。就像银行转账一样,当从一个帐户转出一部分钱之后,就必须在另一个帐户中存入相同数目的钱,若是转出钱之后,事务中止了,没有在另一个帐户中存钱,那么钱就不翼而飞了,这就是事务的原子性。当事务完成后,必须将其结果记录下来,不然就无从知道事务是已经发生还是尚未发生,这是事务的持久性。此外,事务还有隔离性和一致性。

2、为什么要引入日志?
   首先,我们了解一下在数据库中是如何实现一个事务的。当事务开始后,我们从磁盘中读取数据,然后对这些数据进行操作,可能是筛选、统计、更新等,还可以有一些新建数据,总之,若发生数据变化后,当数据完成后,必须将这些变化后的数据重新写入到磁盘中,这样我们就完成了一个事务。当然这是最简单的一个描述,下面我们来针对每个环节进行深入的分析。首先是从磁盘中读取数据,根据常识,我们知道,在一个应用系统中,我们可能经常会读取相同的数据,如果每次都从磁盘读取,因为磁盘IO比较慢,所以效率不高,性能不好。大家都能想得到,可以采用缓冲区机制来提高数据读取的性能。本文主要目的不是缓冲区就不多说了。接下来是对数据的操作,事务完成后,我们需要把更新后的数据写入到磁盘,这里又有同样的问题出现,磁盘IO的性能问题,那么有人说我们还可以用缓冲区机制啊?说的太好了,缓冲区确实帮我们缓解了磁盘IO性能的问题。但缓冲区机制在帮我们解决了磁盘IO性能问题的同时,又带来了一个新的问题,如果发生了故障怎么办?
    在数据库系统的设计中,数据的丢失是不可接受的,为了解决缓冲区数据写入磁盘的性能问题,引入了日志。在操作数据之前,我们先将操作记入日志,然后再修改数据,当然不修改数据的日志好象没什么意义。我们可以通过读取日志,重做丢失的数据的操作,就可以保证丢失的数据全部恢复。有人说,写日志与写缓冲区不是一样要写磁盘吗?这位同学说的太对了,真的是一样的,都要进行写磁盘操作,只是有那么一点点细微的差别,写日志是顺序写入磁盘,而缓冲区则是随机写入磁盘。虽然只是这一点点差别,但对性能的影响却是巨大的,有兴趣的同学可以自己去试试哟。此外日志的数据量也远远小于要写入的缓冲区的数据量。
    有些人提问了,为什么要先将操作记入日志,然后再执行操作修改数据呢?这是因为若是先执行操作,那么在随后写入日志之前若是系统down机,那么就会丢失此次操作,在数据库系统中称之为WAL(write ahead log)。

3、日志缓冲区的引入
   为进一步提高性能,引入了日志缓冲区,批量将日志写入到磁盘,而不再是产生一条就写一条,这样又带来一个问题,在日志缓冲区写入磁盘之前有可能会导致日志丢失,从而导致数据丢失。如何解决这个问题呢?我们需要对日志的作用进一步分析,日志是为了重做丢失的操作,若一个事务未提交之前,那么这个事务已进行的操作实际上并不重要,即使丢失也没有什么影响。就像银行转帐一样,从一个账户已经转出,此时系统故障,无法对另一个帐户转入,此事务会回滚,即系统会退回到帐户转出之前的状态,账户转出操作无效,即使账户转出的操作这条日志未被写入磁盘导致操作丢失,当我们恢复时,并不会有什么影响,可能还加速了恢复的过程,少处理了一条日志。因此日志缓冲区的磁盘写入时机可以被推迟,最晚不能晚于事务提交。实际上在日志缓冲区实现上还有一些其它的限制,如checkpoint、日志缓冲区已满等,不一定要等到事务提交时才写入磁盘。

4、lsn的由来和作用
   既然已经有了日志,就要发挥它的作用,在恢复过程中,通过读取日志来重做操作,按什么顺序来重做日志呢?记录历史操作的顺序,是非常重要的,如果操作顺序发现混乱,导致的后果也是非常严重的。比如对一个数值100先减去100,再翻倍,若是发生操作顺序逆转,先翻倍再减去100,得到的结果就大相径庭了。这里就需要一个规则,给日志编个序号,我们按日志产生的顺序给每条日志编号,然后按日志编号来重做日志,就不会发生日志重做发生混乱的情况。在实现的过程中,我们在记录日志的时候,是按日志产生的顺序依次写入磁盘的,即使是写到日志缓冲区中,也是按产生的顺序依次写到日志缓冲区,再将日志缓冲区顺序写到磁盘中。因此我们可以采用日志在日志文件中的偏移来代替这个日志编号,不仅不需要额外的磁盘开销,而且还能通过这个偏移迅速定位到这个日志,真是个神奇的想法,我们给这样的日志编号起了一个特殊的名字:lsn,这就是lsn的由来。
    但我们又发现一个新的问题,虽然我们知道了所有的历史操作和它们之间的顺序关系,但不知道这些操作的影响是否已经保存到磁盘,如果简单的重做所有操作,会不会把已经做过的操作重复进行。比如购物转账转了两次钱出去?所以在每个数据块的块头记录下最后一次修改这个数据块的操作的日志编号lsn,当重做日志时,数据块加载到缓冲区中,称之为页面,若页面的header中lsn比当前重做日志的lsn小,则说明当前日志尚未被重做; 若不比当前重做日志的lsn小,即大于或等于当前重做日志的lsn,则说明当前日志已经被重做,或不需要重做;通过这种方法,可以避免日志被重复重做,从而得到正确的恢复结果。

5、利用checkpoint加速恢复的过程
   当系统发生故障后,由于有日志的存在我们不用担心数据丢失,可以通过读取日志来恢复,但若是系统已经运行了很长时间,操作很多,日志很大的情况下,在进行日志恢复时恢复进程会十分慢长。在生产环境下,要求恢复的时间越短越好,怎么才能缩短恢复的时间呢?checkpoint就是解决这个问题的办法。在日志中,引入一种特殊的日志类型,checkpoint日志,它表示在此之前的所有“脏数据”已经写入到磁盘,那么在它之前的日志在恢复过程中就可以忽略掉,而不用再处理。虽然我们希望checkpoint是一个瞬时的过程,但在实现上却有很大的难度,我们不能瞬时将所有“脏数据”写入磁盘,如果可以做到,也就不需要日志了。因此checkpoint是一个过程,有它的起始和结束,当checkpoint开始时,我们记录当前日志的记录偏移lsn,并标记所有的“脏数据”为准备写入状态,接下来就是将具有准备写入状态的”脏数据”写入磁盘,注意:在写入的同时其它进程或线程有可能会产生新的“脏数据”,这些新产生的“脏数据”我们并不关心其是否写入磁盘。当所有已标记的“脏数据”写入磁盘之后,在日志中插入一条checkpoint日志,表示checkpoint已经完成,同时它还记录着checkpoint开始时的日志偏移,也称为REDO偏移。当进行恢复时,首先找到最后一次checkpoint日志的位置,读出checkpoint日志记录,从中获得REDO偏移,然后从REDO偏移开始恢复即可。通过调整checkpoint的间隔时间,可以得到一个可接受的故障恢复时间。

postgresql的日志实现机制的更多相关文章

  1. Java 日志缓存机制的实现--转载

    概述 日志技术为产品的质量和服务提供了重要的支撑.JDK 在 1.4 版本以后加入了日志机制,为 Java 开发人员提供了便利.但这种日志机制是基于静态日志级别的,也就是在程序运行前就需设定下来要打印 ...

  2. 桦仔 笔记7-徐 SQLSERVER日志记录机制

    1 --SQLSERVER日志记录机制 2 --日志记录事务发生的时间,但是不保证记录下发起这个事务的用户名,更不记录发起者的程序名称!!! 3 USE AdventureWorks 4 CREATE ...

  3. 数据库并发事务控制四:postgresql数据库的锁机制二:表锁 <转>

    在博文<数据库并发事务控制四:postgresql数据库的锁机制 > http://blog.csdn.net/beiigang/article/details/43302947 中后面提 ...

  4. Log4J是Apache组织的开源一个开源项目,通过Log4J,可以指定日志信息输出的目的地,如console、file等。Log4J采用日志级别机制,请按照输出级别由低到高的顺序写出日志输出级别。

    Log4J是Apache组织的开源一个开源项目,通过Log4J,可以指定日志信息输出的目的地,如console.file等.Log4J采用日志级别机制,请按照输出级别由低到高的顺序写出日志输出级别. ...

  5. PostgreSQL的日志文件介绍

    PostgreSQL的日志文件 pg_log:数据库活动日志(也就是数据库的操作日志): pg_xlog:事务日志: pg_clog:事务状态日志(pg_clog是pg_xlog的辅助日志). 现在主 ...

  6. postgresql如何实现回收站机制

         在oracle10G之后:oracle提供一种回收站的机制:即闪回技术.闪回技术通常用于快速简单恢复数据库中出现的认为误操作等逻辑错误.发展到11G之后:回收站更加完善:对在可闪回时间内:数 ...

  7. innodb二阶段日志提交机制和组提交解析

    前些天在查看关于innodb_flush_log_at_trx_commit的官网解释时产生了一些疑问,关于innodb_flush_log_at_trx_commit参数的详细解释参见官网: htt ...

  8. PostgreSQL配置文件--日志和错误

    6 错误操作和日志 ERROR REPORTING AND LOGGING 6.1 日志写到哪里 Where to Log 6.1.1 log_destination 字符串 默认: log_dest ...

  9. PostgreSQL归档日志 手动触发归档 select pg_switch_xlog()

    (转,做记录) 一 环境信息--1.1 PostgreSQL 版本 9.3.0 --1.2 postgresql.conf wal_level = hot_standbyarchive_mode = ...

随机推荐

  1. 汇编_指令_SUB

    SUB是减法运算. 比如mov ax,2mov bx,1sub ax,bx 其中sub ax,bx就是ax中的值减bx中的值,等于1,然后把结果,也就是1,放入ax中.

  2. java 文件指针复位

    BufferedReader br = new BufferedReader(new InputStreamReader( new FileInputStream("userremain.l ...

  3. java高并发总结-常用于面试复习

    定义: 独占锁是一种悲观保守的加锁策略,它避免了读/读冲突,如果某个只读线程获取锁,则其他读线程都只能等待,这种情况下就限制了不必要的并发性,因为读操作并不会影响数据的一致性. 共享锁则是一种乐观锁, ...

  4. httpclient pool帮助类

    摘自爬虫类  用于频繁请求减少网络消耗 import java.io.IOException; import java.io.InterruptedIOException; import java.i ...

  5. 设置GO环境变量

    linux的设置方法:有4个环境变量需要设置:GOROOT.GOPATH.GOBIN以及PATH.需要设置到某一个profile文件中(~/.bash_profile(单一用户)或/etc/profi ...

  6. 迷你MVVM框架 avalonjs 学习教程8、属性操作

    属性操作是DOM操作很大的一块,它包括类名操作,表单元素的value属性操作,元素固有属性的管理,元素自定义属性的管理,某些元素的一些布尔属性的操作.大多数情况下,元素属性的值是字符串类型,我们称之为 ...

  7. 迷你MVVM框架 avalonjs 0.98发布

    在本版本中,avalon侧重于对组件开发的支持,可用控件达到12个,末来将大力投入对GRID,TREE等重型UI的开发中. 添加ms-widget绑定,废弃ms-ui绑定 为ms-include添加跨 ...

  8. [ML]熵、KL散度、信息增益、互信息-学习笔记

    [ML]熵.KL散度.信息增益.互信息-学习笔记 https://segmentfault.com/a/1190000000641079

  9. css继承和层叠

    在前面介绍了如何利用文档结构和css选择器为元素应用各种丰富的样式,今天来好好聊聊css的层叠和继承,先说说概念. 继承:一个元素向其后代元素传递属性值所采用的机制,说的通俗点,就是元素的某些属性可以 ...

  10. 在VMware Workstation中安装Ubuntu Server 16.04.5图解教程

    最近要在Ubuntu中部署openstack,为了节省空间和内存,最终选择了Ubuntu服务器.看了很多前辈和大佬的安装教程,在这里记录一下我自己的Ubuntu Server 16.04.5的安装过程 ...