Berkeley DB事务篇
目录
Berkeley DB的事务处理入门
法律声明
此文件是一个开源许可证下发布的。您可以查看本license的条款:http://www.oracle.com/technology/software/products/berkeley-db/htdocs/oslicensing.html
Oracle, Berkeley DB, and Sleepycat是Oracle公司的商标或注册商标。对这些商标的所有权利均予以保留。允许任何第三方使用未经明确的事先书面同意甲骨文公司。要取得这个文件的原始源代码的副本,请提交请求到Oracle技术网络论坛:http://forums.oracle.com/forums/forum.jspa?forumID=271
前言
本文档介绍了Berkeley DB的应用程序如何使用事务。它的目的是描述如何使用事务保护您的应用程序的数据。执行程序的API,可用于此处所描述的,因为是事务性应用程序所需要的环境基础设施和管理任务。这本书还介绍了多线程和多进程DB应用程序和要求,他们有死锁检测。
这本书的目的是负责编写事务DB应用程序软件工程师。
这本书假定您已经阅读并理解入门Berkeley DB的指南中包含的概念。
在这本书中使用的约定
在本手册内使用下列印刷惯例:
等宽字体表示类名,方法名。例如:“DbEnv::开放()是DbEnv的类的方法。”
变量或者非字面的文本以斜体表示。例如:“去您的DB_INSTALL目录”。
程序示例显示阴影背景等宽字体。例如:
typedef struct vendor {
char name[MAXFIELD]; // Vendor name
char street[MAXFIELD]; // Street name and number
char city[MAXFIELD]; // City
char state[3]; // Two-digit US state code
char zipcode[6]; // US zipcode
char phone_number[13]; // Vendor phone number
} VENDOR;
在某些情况下,编程实例更新一章。当这种情况发生时,新的代码是在等宽字体加粗。例如:
typedef struct vendor {
char name[MAXFIELD]; // Vendor name
char street[MAXFIELD]; // Street name and number
char city[MAXFIELD]; // City
char state[3]; // Two-digit US state code
char zipcode[6]; // US zipcode
char phone_number[13]; // Vendor phone number
char sales_rep[MAXFIELD]; //Name of sales representative
charsales_rep_phone[MAXFIELD]; // Salesrep's phone number
} VENDOR;
注意
最后,特别感兴趣的票据表示使用像这样的注释块。
欲了解更多信息
除了本手册中,您也可以找到以下有用的信息来源时,建设一个事务DB应用程序:
· Getting Started with Berkeley DB for C++
· Berkeley DB Getting Started with Replicated Applications for C++
· Berkeley DB Programmer's Reference Guide
1. 介绍
这本书提供了全面的介绍和讨论BerkeleyDB(DB)事务的使用。提供的一般事务的概述,他们提供的担保,和一般的应用程序所需的基础环境,以获得完整的事务,保护您的数据。
这本书还提供了详细的例子,关于如何编写事务性的应用程序。单线程和多线程(以及多进程应用程序)也进行了讨论。本手册中包含的各种备份和恢复策略的详细描述,讨论事务的在程序应用的性能问题。
通过入门Berkeley DB的指导,在读这本书之前,你应该明白一些基本的概念。
1.1.事务优势
事务为应用程序的应用程序或系统故障提供数据保护。也就是说,DB事务为你的应用程序提供了完整的ACID支持:
l 原子(Atomicity):多个数据库的操作被视为一个单一的工作单元。整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。。
需要注意的是DB的事务可以跨越一个或多个数据库句柄。
l 一致性(Consistency):你的数据库将永远不会出现部分完成的事务。这是有保证的,即使你的应用程序失败时,正在进行的事务操作。如果应用程序或系统失败,那么所有对数据库的修改要么同时提交,要么同时失败。
l 隔离(Isolation):隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据。
l 持久性(Durability):在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚,即使在应用程序或系统故障。需要注意的是,像隔离,持久性保证可以放宽。有关更多信息,请参见Non-DurableTransactions。
1.1.1. 系统故障注记
本手册中经常提到,在系统或应用程序故障时,事务保护您的数据。在一定程度上,这是真实的。然而,并非所有的失败都被平等对待,没有数据保护机制,可以保护你对每一种可以想象到方计算失败。
一般来说,当这本书谈论故障保护,这意味着事务提供保护,防止可能的系统和应用程序崩溃。只要您的数据修改已经提交到磁盘,这些修改应持久化,即使您的应用程序或操作系统随后失败。应用程序或操作系统出现故障,即使在事务的中间(或中止),磁盘上的数据应该是处于一致的状态,还是应该有足够的数据,可以把你的数据库确保一致的状态(通过在恢复过程中,例如)。然而,数据提交失败时您可能失任何数据,但你的数据库将不受影响。
当然,如果你的磁盘失败,那么这本书中介绍的事务优势都不如你采取备份。数据和日志文件写到不同的磁盘上,可以最大限度地减少磁盘故障造成的数据丢失的风险,但即使在这种情况下,也是有风险的(例如:机房火灾),所以你必须进备份保护。
最后,在这本书中的编程实例,你可以写你的事务,保护您的数据,及使你的代码崩溃。然而,没有任何一保编程API可以保护你的逻辑故障代码,事务无法保护你的数据库从简单的写了错误。
1.1.2. 应用需求
为了使用事务,你的应用程序相对出非事务性保护的应用程序有一些特定的要求。它们分别是
l 环境
非事务性应用程序,环境是可选的,但他们是事务性应用程序所需要的。
l 事务子系统
为了使用事务,您的应用程序必须明确地启用事务子系统,而这必须在您的环境第一次被创建完成。
l 日志子系统
恢复性需要日志子系统,但其用法也意味着你的应用程序比不用日志子系统时消耗更多的性能,因为他需要更多的数据操作。
l DbTxn句柄
为了获得的原子事务子系统(即多个操作组合在一个单一的工作单元)保证,您的应用程序必须使用事务手柄。这些手柄是从您的DbEnv对象。他们通常是短暂的,它们的用法相当简单。完成事务并保存它执行的工作,你可以调用它的commit()方法。为了完成事务,并放弃其工作,调用其abort()方法。
此外,它也可以使用自动提交,如果你想的事务保护单一写操作。自动提交允许一个事务使用无需获得一个明确事务手柄。
l 打开数据库的条件
除了使用环境和正确的子系统初始化,如果要后续事务保护操作数据库,您的应用程序必须以事务保护方式打开数据库,以及任何辅助索引库。自动提交是打开数据库和二级索库常用的事务保护。
l 死锁检测
程序使用多线访问数据库程是典型的事务性应用。多个线程上使用一个单一的资源,任何时候可能出现锁争用。反过来,锁争用可能导致死锁。
因此,事务性应用程序必须经常包括死锁检测和响应代码。注意,这个不是特定的事务要求 - 你当然可以编写并发的非事务性的DB应用程序。此外,并非每个应用程序并发使用事务,因此不是每个程序应用必须管理事务死锁处理。尽管如此,在事务性应用程序死锁管理是如此频繁,我们在这本书中讨论的一个特点。
1.1.3. 多线程和多进程应用
DB的设计,支持多线程和多进程的应用程序,但他们的使用意味着你必须特别注意的并发问题。事务帮助你的应用程序对并发控制线程提供不同的隔离级别。另外,DB提供检测和响应死锁(但严格来说,这不局限于只是事务性应用程序)机制。
隔离是指由一个事务对数据库的修改,读者从另一个事务将不能正常看到,直到第一个提交其变化。不同的线程使用不同的事务手柄,所以通常用来提供这种机制是由不同的线程中执行数据库操作之间的隔离。
需要注意的是DB支持不同的隔离级别。例如,您可以配置应用程序,看到未读,这意味着一个事务可以看到已被其他事务修改但尚未提交的数据。否则,这可能意味着您的事务读取另一个事务的“脏”数据,但随后可能会改变之前,其它事务提交其变化。另一方面,降低您的隔离要求意味着减少锁争用,应用程序可以体验提高吞吐量来。
1.2.可恢复
DB的事务担保的一个重要组成部分,是持久性。持久性是指一旦一个事务一直致力于在其保护下的数据库进行的修改,将不会被因系统故障而丢失。
为了提供事务的持久性保证,DB使用预写的日志系统。你的数据库上进行操作之前,在日志中描述每一个数据库操作。这样做是为了确保在一个不合时宜的应用程序或系统故障的情况下的操作可以恢复。
除了记录,持久的另一个重要方面是可恢复性。也就是说,备份和恢复。只要您的应用程序后第一次打开启动时使用环境,通过日志文件集,DB支持正常数据恢复。DB也支持存档的备份和灾难性故障情况下的恢复,如物理磁盘驱动器的损失。
这本书介绍了几种不同的备份,你可以用它来保护你的磁盘上的数据。这些程序的范围从简单的脱机备份策略,以热故障切换。热故障切换不但提供了备份机制,但也是一种致命的硬件故障恢复。
这本书还介绍了恢复过程,你应该使用每个备份策略。
1.3. 性能优化
从性能的角度来看,使用的事务不是免费的。根据您如何配置它们,您的应用程序事务提交通常需要执行磁盘I/ O,非事务性应用程序不执行。此外,对于多线程和多进程的应用程序,由于事务隔离担保驱动额外的锁定要求,使用的事务可能导致锁竟争。
因此事务性应用程序的性能优化组件,并不适用于非事务性应用程序(虽然确实存在一些调整,考虑不是你的应用程序是否使用事务)。在适当的情况下,这些调整考虑在下面的章节介绍。然而,对于一个更完整的说明,请参阅事务调整和事务吞吐量部分Berkeley DB的程序员参考指南。