postgresql的日志实现机制
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的日志实现机制的更多相关文章
- Java 日志缓存机制的实现--转载
概述 日志技术为产品的质量和服务提供了重要的支撑.JDK 在 1.4 版本以后加入了日志机制,为 Java 开发人员提供了便利.但这种日志机制是基于静态日志级别的,也就是在程序运行前就需设定下来要打印 ...
- 桦仔 笔记7-徐 SQLSERVER日志记录机制
1 --SQLSERVER日志记录机制 2 --日志记录事务发生的时间,但是不保证记录下发起这个事务的用户名,更不记录发起者的程序名称!!! 3 USE AdventureWorks 4 CREATE ...
- 数据库并发事务控制四:postgresql数据库的锁机制二:表锁 <转>
在博文<数据库并发事务控制四:postgresql数据库的锁机制 > http://blog.csdn.net/beiigang/article/details/43302947 中后面提 ...
- Log4J是Apache组织的开源一个开源项目,通过Log4J,可以指定日志信息输出的目的地,如console、file等。Log4J采用日志级别机制,请按照输出级别由低到高的顺序写出日志输出级别。
Log4J是Apache组织的开源一个开源项目,通过Log4J,可以指定日志信息输出的目的地,如console.file等.Log4J采用日志级别机制,请按照输出级别由低到高的顺序写出日志输出级别. ...
- PostgreSQL的日志文件介绍
PostgreSQL的日志文件 pg_log:数据库活动日志(也就是数据库的操作日志): pg_xlog:事务日志: pg_clog:事务状态日志(pg_clog是pg_xlog的辅助日志). 现在主 ...
- postgresql如何实现回收站机制
在oracle10G之后:oracle提供一种回收站的机制:即闪回技术.闪回技术通常用于快速简单恢复数据库中出现的认为误操作等逻辑错误.发展到11G之后:回收站更加完善:对在可闪回时间内:数 ...
- innodb二阶段日志提交机制和组提交解析
前些天在查看关于innodb_flush_log_at_trx_commit的官网解释时产生了一些疑问,关于innodb_flush_log_at_trx_commit参数的详细解释参见官网: htt ...
- PostgreSQL配置文件--日志和错误
6 错误操作和日志 ERROR REPORTING AND LOGGING 6.1 日志写到哪里 Where to Log 6.1.1 log_destination 字符串 默认: log_dest ...
- PostgreSQL归档日志 手动触发归档 select pg_switch_xlog()
(转,做记录) 一 环境信息--1.1 PostgreSQL 版本 9.3.0 --1.2 postgresql.conf wal_level = hot_standbyarchive_mode = ...
随机推荐
- ThinkJava-输入和输出
1/0流的典型使用方式 1.缓冲输入文件 package com.java.io; import java.io.BufferedReader; import java.io.File; impo ...
- sysbench 参数
1)插入指定条数的数据 --events=N limit for total number of events [0] --time=N limit for total execution time ...
- postman-2get发送请求
文档地址:https://www.v2ex.com/p/7v9TEc53 第一个API请求 最热主题 相当于首页右侧的 10 大每天的内容. https://www.v2ex.com/api/topi ...
- 如何制作行政区划矢量图(shp格式)
详细图文ArcGIS10.2破解版教程地址:http://jingyan.baidu.com/article/e73e26c0cb5c1324adb6a791.html 有时候想要一张shp格式的地方 ...
- Android ListView根据项数的大小自动改变高度
第一种:按照listview的项数确定高度 ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) ...
- 生成Excel
生成Excel 需要引用MyXls.SL2.dll的类库: 下载地址:http://sourceforge.net/projects/myxls/ 命名空间using org.in2bits.MyXl ...
- Oracle 11g 新特性 -- Oracle Restart 说明(转载)
转载:http://blog.csdn.net/tianlesoftware/article/details/8435670 一. OHASD 说明 Oracle 的Restart 特性是Oracl ...
- Solr中Facet用法和Group用法
Group分组划分结果,返回的是分组结果: Facet分组统计,侧重统计,返回的是分组后的数量: 一.Group用法: //组查询基础配置params.set(GroupParams.GROUP, & ...
- MySQL转Oracle,MyBatis Mapper XML 文件修改项总结
1.对于批量插入 需要更改成 <insert id="saveAll"> insert into(a,b,c) <foreach collection=" ...
- Navicat 入门使用方法
Navicat 多重连接数据库的管理工具,支持连接到(MySQL.Oracle.PostgreSQL.SQLite .MariaDB )多类数据库,也支持多类数据库的管理和使用 1.Navicat 主 ...