《ALTIBASE应用开发手册V(完整版).doc》由会员分享,可在线阅读,更多相关《ALTIBASE应用开发手册V(完整版).doc(105页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、ALTIBASE应用开发手册V(完整版)(文档可以直接使用,也可根据实际需要修改使用,可编辑 欢迎下载)ALTIBASE应用开发手册For Version 天津南大通用数据技术目录第一部分 基础篇51.ALTIBASE 介绍51.1 ALTIBASE是什么51.2 ALTIBASE基础82.ALTIBASE 特性162.1 存储管理162.2 锁182.3 并发控制222.4 事务管理282.5 数据安全性332.6 ALTIBASE性能指标373.SQL 优化413.1 优化要素413.2 INDEX413.3 Join optimization433.4 Limit Stop key433
2、.5 Subquery Optimization443.6 INSERT / UPDATE /DELETE Optimization443.7 确认执行计划45第二部分 安装篇464.系统要求464.1 AIX464.2 HP484.3 DB DISK 结构505.安装步骤515.1 安装515.2 环境变量515.3 数据库参数525.4 创建数据库555.5 启动 / 关闭数据库556.常见安装问题55AB-INSTALL-001:License 问题55AB-INSTALL-002:posix_aio0 问题57AB-INSTALL-003:C+ 编译器问题57第三部分 应用开发篇597
3、.开发基础597.1 怎样开发成功的ALTIBASE应用系统597.2 实现最佳性能647.3 提高稳定性687.4 常见问题69第四部分 部署篇748.复制748.1 简介748.2 复制数据冲突和解决方法758.3 如何进行复制778.4 三种复制方式788.5 快速并行同步798.6 监控复制运行情况808.7 常见问题809.备份和恢复869.1 简介869.2 备份和检查点889.3 逻辑备份(Logic Backup)备份和恢复899.4 在线备份(Online Backup)899.5 介质恢复(Media Recover)909.6 常见问题9310.高可用性9410.1 什么
4、是可用性9410.2 停工的原因9410.3 ALTIBASE的HA方案9510.4 常用的部署方案96第五部分 常见问题解答9811.CPU 使用高的问题9811.1 基本内容9811.2 常见问题9912.Memory 使用高的问题10012.1 基本内容10012.2 常见问题10013.Disk I/O 瓶颈10113.1 基本内容10113.2 常见问题10214.网络问题10314.1 基本内容10314.2 常见问题103第一部分 基础篇1. ALTIBASE 介绍1.1 ALTIBASE是什么 概述ALTIBASE是一个具备了通用关系数据库功能和特点的混合型的内存数据库。具备微
5、秒级的事务处理性能和十倍于磁盘数据库的极高的吞吐量。具备完整的事务ACID特性,特别是其优秀的事务持久性能力,有效的保证了生产数据的安全。提供了符合工业标准的各种接口(ODBC、JDBC、E/SQL),完全支持SQL92标准,支持存储过程、触发器、视图等功能。ALTIBASE的高性能、高安全性、高通用性特点,非常适用于电信、网上银行、证券、交通、能源等实时应用和嵌入式系统领域。 内存数据库的发展背景1.1.3 ALTIBASE发展路线图ALTIBASE从2000年发展至今,已经发展到了V5版本,产品从简单、追求极高性能的基础发展到了今天的具备高性能、高安全性、通用性等特点的混合型内存数据库产品
6、,并被成功应用在中国的电信、能源、交通领域。l 2000年发布了V1版本V1版本是一个实时内存数据库,主要注重产品的性能、安全性和易开发性。l 2002年发布了V2版本在V2版本中ALTIBASE实现了MVCC(多版本并发控制)技术,产品应用领域扩展到了通信设备、服务、金融、公共等实时应用领域。l 2003年发布了V3版本在V2版本的基础上,实现了对中等规模数据的有效管理,提高了对复杂SQL语句的处理能力。l 2005年发布了V4版本ALTIBASE V4版本是一个里程碑,ALTIBASE发展成为一个同时支持高性能和大容量的Hybrid MMDBMS(混合型的内存数据库管理系统)。并且开始应用
7、在中国电信领域的生产系统中。随着V4版本的不断发展和完善,到2021年,该版本已经作为核心支持产品被广泛的使用在中国移动、中国联通的计费系统、营帐系统、实时计费(OCS)系统等关键生产系统中。l V5版本即将正式发布的V5版本提供了更加完善的数据支持,更丰富的分析、管理功能和第三方数据库的同步接口。并根据当前ALTIBASE在实际项目中用户的反馈,增加了用户急需的功能。1.1.4 与文件数据库的比较图1-2:整体实现机制对比图1-3:索引访问机制对比1.1.5 ALTIBASE内存数据库有风险吗对于一个内存数据库,其风险主要来自几个方面:1:宕库风险数据平常都在内存中被操作,那么数据库服务进程
8、失效后,可能存在丢失数据的风险。2:应用异常数据库应用程序的异常,是否会导致内存数据库锁管理的内存的异常,从而导致数据的异常。3:服务器掉电数据库服务器掉电,造成数据丢失。ALTIBASE内存数据库具备独特的事务日志(REDO LOG)管理机制,能够根本上避免宕库造成的数据丢失的风险。具体的讨论请参考本篇的2.5 数据安全性章节。数据库应用程序进程与ALTIBASE数据库服务进程是物理分离的,应用程序不会直接的操作数据库服务进程所管理的内存,因此从根本上避免了应用异常造成的数据风险。事实上,ALTIBASE是目前所有的商用内存数据库产品中,唯一能够保证宕库不丢失数据的商用产品。对于ALTIBA
9、SE内存数据库,唯一的风险来自于服务器掉电。通过在系统部署中合理的使用双机复制,并合理的设计应用系统,可以有效的解决这一风险。因此,在生产系统中使用ALTIBASE数据库是不存在风险的,并且在电信的大量核心系统应用案例中得到了认可。1.2 ALTIBASE基础 基本概念线程架构ALTIBASE数据库服务采用的是多线程的架构。每个数据库实例一个进程,进程内部通过多线程来提供并发处理。一个服务器上可以创建多个ALTIBASE数据库实例来分担系统压力,以提供更高的系统扩缩能力。接口ALTIBASE支持工业标准的接口。完整的支持SQL92标准,并提供了很多扩展功能。支持的标准API接口包括ODBC、J
10、DBC。多版本并发控制(MVCC)ALTIBASE通过实现MVCC来提高并发处理的能力。通过保持记录的多个版本,避免了同时对同一条记录进行读、写的冲突。使得读、写之间不会互相阻塞,从而有效了提升查询的性能。事务处理ALTIBASE提供了自动提交和非自动提交模式的选择。提供了读提交(READ COMMITTED)、可重复读(REPEATABLE READ)和串行化隔离级别供选择,以适合不同的应用系统需求。Logging(事务日志)为了保证ALTIBASE的可靠性和事务持久性,ALTIBASE将事务日志写到磁盘上进行保存。同时,事务日志也被用于进行复制。Double Write Buffer(双写
11、缓冲)ALTIBASE数据库的页大小和文件系统的物理页大小不一样时,如果在页面写入期间操作系统崩溃了,则有可能数据不完整。为了防止这种现象,ALTIBASE 在将页面写入一个数据文件前先将他们写入到一个双写缓冲 等特定磁盘领域中,并写入与转储清除(flush)双写缓冲结束后,才将页面写入到数据文件的适当的位置。还有, ALTIBASE 重起时,将在双写缓冲中找出一个完好的副本(copy)来恢复。Fuzzy & Ping-Pong Checkpointing(模糊 & 乒乓检查点)Altibase 为了把最新的数据库状态反映到备份数据库中,执行模糊乒乓检查点。为了发生 checkpoint时,不
12、影响事务处理的性能执行模糊检查点 (fuzzy checkpoint)和乒乓检查点(ping pong checkpoint)。就是管理两份 backup database,解决一份内存脏页要往磁盘上写两次的问题,减少了 Disk I/O 并减少了事务日志持久化的开销,提高事务的性能。存储过程和存储函数存储过程是一组为了完成特定功能的 SQL 语句集,经编译后存储在数据库中。根据返回参数分为存储过程和存储函数。死锁检测死锁是事务之间无法自由释放占有资源而发生的现象。一般是通过特定的进程或线程监测死锁,但这种方法会导致事务处理的停滞。ALTIBASE 没有特殊的死锁检测线程,而是发生死锁瞬间获得
13、死锁信息,并迅速采取措施,从而防止服务中断的情况,提供稳定而持久的运行。1.2.2 系统架构图1-4:ALTIBASE系统架构ALTIBASE采用的是多线程架构。由一个主服务进程,API接口,数据存储和一组工具组成。服务进程中包含了查询处理器、存储管理器等多个线程。多线程结构的服务器消耗较少的系统资源,而且线程之间的切换成本也低得多。Altibase服务器具有多线程结构的优点。Altibase由提供数据库服务器基本功能的系统线程和执行数据库应用程序发出的数据库操作的服务线程组成。服务线程池负责管理服务线程。这种结构能通过最小化系统资源的使用提供系统可扩展性和可用性。服务器实例的线程结构如下:主
14、线程创建/退出所有线程,并管理它创建的线程。服务守护线程当客户端要求连接时,该线程连接客户端与服务线程池中的一个等待状态的服务线程。服务线程池(Service Thread Pool)数据库启动时,根据配置信息生成服务线程,并放入线程池中进行管理,服务线程是处理语句的线程。检查点线程为了减少恢复操作中的工作量,该线程周期性地或不定时地将当前数据映射到磁盘数据文件中并删除或移动已反映的日志文件。对话管理线程检查客户端/服务器之间的通信对话状态。垃圾回收线程在MVCC(多版本并发控制)中,可能对记录产生不必要的数据。该线程重新规划和优化这些数据占据的内存空间,从而最大提高系统效率。日志清理线程管理
15、数据库中所有事务产生的日志并将缓存入日志缓存区的日志数据存储到日志硬盘。备份日志文件在系统故障时用来恢复数据库。图1-5:ALTIBASE线程结构 物理结构组成ALTIBASE数据库的物理结构包括log file(日志文件)、log anchor files(控制文件)和data files(数据文件)。此外,还包含了控制文件和运行状态跟踪文件。图1-6:ALTIBASE物理结构Log file(日志文件)该文件也称作REDO Log file,用于保证事务的原子性和持久性。原子性指的是当事务回滚的时候,数据能够恢复到事务开始前的状态的能力。持久性用于保证当数据库发生失效,在恢复运行后,能够通
16、过日志文件恢复到之前已经提交的事务。ALTIBASE的事务日志被存储在LOG_DIR参数指定的位置,文件是顺序增长的,每个日志文件的大小为10M字节,写满后即切换到下一个新的日志文件,而不是循环使用。因此日志文件被分成了两种:active log file(活动日志文件)和archive log file(归档日志文件)。用于记录当前事务日志的log file被称作active log file。archive log file是已经被切换(写满了)的日志文件的备份。active log file(活动日志文件)是当前正在使用的日志文件,记录当前的事务的redo信息。如果这个日志文件被破坏,整
17、个数据库都不再可用。日志文件与数据文件一起被用于恢复当前数据库状态。archive log file(归档日志文件),除了活动日志文件以外的日志文件都是archive log file(归档日志文件)。如果ALTIBASE数据库是以非归档模式运行,那么在每次发生检查点之后,所有被刷新到数据文件的归档日志文件会被删除掉。如果是以归档模式运行,在每次发生检查点之后,这些已经刷新到数据文件的归档日志文件会被转移到“ARCHIVE_DIR”参数所制定的路径下,以用于备份。Data files(数据文件)数据文件用于在磁盘上保存用户的真实数据,也是Altibase保证数据持久性机制的一部分。ALTIBA
18、ES中有以下几种数据文件:n 用户(mydb)数据文件n 系统(system)数据文件n 临时(temp)数据文件需要注意的是,由于ALTIBASE采用的是Ping-Pong Checkpointing,因此用户数据文件会有两份。log anchor files(控制日志文件)控制日志文件用于控制日志记录与数据文件和事务日志相关的重要信息,它记录了每个数据文件基于事务日志时间戳的相对时间位置。控制日志包括数据库的结构信息,如表空间、数据文件位置、检查点(Checkpoint)等。Altibase服务器启动时,由控制日志指明数据库和日志文件,在数据库恢复时也需要控制日志。所以在备份时必须和数据文
19、件一起备份。其他控制文件在ALTIBASE数据库中,还包含其他一些很有用的控制文件:属性配置文件:在conf文件夹下的altibase.properties文件状态跟踪文件:所有的跟踪文件都在trc文件夹下,比较重要的是altibase_boot.log和altibase_sm.log文件。altibase_boot.log保存着数据库启动、停止的跟踪信息。altibase_sm.log文件保存着与ALTIBASE的存储管理相关的执行状态信息,例如检查点运行的情况等。 逻辑结构ALTIBASE逻辑上划分为Table Space(表空间)、segment(段)、Extent(区或范围)、Page
20、(页)。表空间是逻辑数据库空间的最大单位。ALTIBASE 数据库由一个以上的逻辑表空间组成,表空间的数据存储在物理数据文件里。表空间由一个以上的数据文件组成,但一个数据文件只属于一个表空间。ALTIBASE的表空间可以分为四种:内存表空间(SYS_TBS_MEMORY),保存数据字典, 内存表。数据表空间,保存系统表空间(SYS_TBS_DATA)和用户表空间。Undo 表空间(SYS_TBS_UNDO),为了多版本并发控制,存储变更前的映像临时表空间,保存系统临时表空间(SYS_TBS_TEMP)和用户临时表空间。这里需要注意的是:ALTIBASE的内存表都是保存在内存表空间的,并且对于一
21、个ALTIBASE实例只能有一个内存表空间(SYS_TBS_MEMORY),所有的内存表都是在这个表空间中的。因此,在创建ALTIBASE数据库(执行server create命令创建数据库)的时候,ALTIBASE将自动创建一个内存表空间(SYS_TBS_MEMORY),其尺寸的上界是“MEM_MAX_DB_SIZE”参数指定的大小,相应的会创建两组数据文件来保存用户的数据。之后,新创建的表如果没有指定表空间,都是在这个内存表空间下。并且之后在该数据库先创建的任何表空间都是属于用户表空间,用于保存磁盘表。图1-7:表空间结构Page(页),与操作系统管理的 page block 不一样,AL
22、TIBASE的page的物理大小为 32K,是构成表空间的最小单位,也是存储记录的最小领域。因此ALTIBASE的I/O操作的最小单位是32K。Extent(区或范围),存储数据对象的单元,1个 Extent 由 8个 page 组成(256KB)。Segment(段),存储表或索引的单位。逻辑上,一个表或索引是一个段,一个段由一组Extent组成。段的种类分为四种:Table Segment,保存表的数据,一个表的所有数据属于同一个table segment。Index Segment,保存表的索引数据,一个索引的所有数据属于一个index segment。Undo Segment,保存un
23、do数据,所有的undo segment属于一个undo tablespace。TSS Segment,用于内部 TSS(Transction Status Slot)管理,属于 undo tablespace。1.2.5 ALTIBASE的组成ALTIBASE安装包中包含了执行程序、开发库、demo(演示程序)、配置文件和include头文件。ALTIBASE安装后的目录组织结构如下:图1-8:ALTIBASE目录组织结构1.2.6 ALTIBASE的Schema对象ALTIBASE的所有数据库对象分成了两种:SCHEMA对象:由一个指定的Schema管理的所有对象。非SCHEMA对象:由A
24、LTIBASE数据库管理的对象。包含Directories、Replications、Tablespaces、Users。Schema是一组对象的集合,Schema属于一个数据库用户(User),并且Schema的名字和User的名字是一样。该Schema下管理的对象都属于这一User。这些对象包括Tables、Constraints、Index、Views、Secquence、Synonyms、Stored Procedures and Functions、Triggers。1.2.7 ALTIBASE的V$视图与Oracle类似,ALTIBASE提供了一组V$视图(动态性能视图),用户可以
25、通过这些V$视图来监控运行期间的各种ALTIBASE系统数据。包括:System memory, Process status,Session and Buffer等。1.2.8 ALTIBASE的系统表(SYS_表)ALTIBASE提供了一组系统表,名字都是以SYS_开头的表,属于SYSTEM_这个Schema。这些表保存着系统和用户的元数据信息。用户可以通过SYS_来获取所有的用户、表、列等信息以及触发器、视图等对象的信息。系统表的详细说明可以参考ALTIBASE的Administrators Manual手册中的3. Data Dictionary章节。2. ALTIBASE 特性2.1
26、 存储管理ALTIBASE支持内存自动扩展。和其它数据库一样,ALTIBASE也需要创建Database,而ALTIBASE在创建Database的时候不需要去指定整个系统所需要的所有内存空间,比如账务部分需要放在内存数据库中的数据大小是50G,对应ALTIBASE来说不用在创建Database的时候就指定内存空间的大小为50G,ALTIBASE可以随着应用数据的增加自动从OS申请内存资源,其每次从OS申请的内存数量可以在参数配置文件中进行配置。对于新增加的数据,ALTIBASE首先看有没有对应大小的空闲空间,如果有则在空闲空间存放新增数据,如果没有空闲空间,则从OS申请内存空间给Databa
27、se。ALTIBASE可以使用delete、drop、truncate等语句操作数据库表。对于delete和drop语句,ALTIBASE会把删掉的记录空间交还给Table,对于Truncate语句,会把删掉的记录空间交给Database。ALTIBASE对于内存的管理是通过其后台服务线程来完成的,详见下图:垃圾回收线程将动态清理Temple space和事务完成后产生的无用的内存空间,把它们回收为可用空间,所以ALTIBASE对于内存的管理是不需要手工来干预的。ALTIBASE通过MVCC机制来控制内存表空间的并发。和单版本并发机制不同,使用MVCC时需要注意如下几个问题:1:长事务导致数据
28、库尺寸增加如果一个事务执行了很长时间没有提交,由于事务仍可能会读旧版本数据,所以垃圾回收器不能删除由其它事务(内存表空间中的旧版本和磁盘表空间的重做日志)创建的版本镜像。这会使内存表的尺寸和磁盘表的重做表空间增加。另外,日志文件也不会在事务回滚时被删除,这些日志文件会消耗掉其所在的文件系统资源。2:由于非正常并发事务导致数据库尺寸增加由MVCC创建的早期镜像会被垃圾回收器清除。如果并发事务的数量明显的大于CPU数,垃圾回收器可能来不及删除旧镜像而导致数据库尺寸持续增长。3:由于过多的旧数据导致性能降低如果有大量的旧版本数据滞留在数据库就会产生上面所说的结果,查询特定数据时的开销会增长,从而降低
29、整体性能。作为内存数据库,内存的大部分空间会分配给内存表空间。对内存表空间的使用根据段(Segment)的不同类型分为:Table space, Index space, Undo space和TSS space。其中Table space和Index space存放用户数据和索引数据,Undo和TSS属于事务信息数据,Undo段中的信息用于事务回滚,TSS是事务状态信息。事务日志缓存根据ALTIBASE设置的事务持久性级别的不同存放在不同的位置:事务持久性级别Transaction Durability Level事务日志(Redo Log)位置TRANSACTION_DURABILITY_
30、LEVEL=2TRANSACTION_DURABILITY_LEVEL=5日志存放在进程内存空间,在级别为2和5的区别在于,ALTIBASE能否保证日志会安全的反映到磁盘上。TRANSACTION_DURABILITY_LEVEL=3日志存放在系统核心区内,即使ALTIBASE进程意外中断,也能保证日志不会丢失。TRANSACTION_DURABILITY_LEVEL=4日志同时存放在进程内存空间和系统核心区内,这个级别提供了与级别2相同的性能,但介于级别2和3的性能表现。2.2 锁 什么是锁锁(lock)机制用于管理对共享资源的并发访问。ALTIBASE同样使用锁来控制对数据的并发处理。当更
31、新数据时,数据服务器会给数据加上锁直到更新被提交或回滚。提交或回滚前,其它事务都不能对已上锁的数据做修改,保证了数据完整性。2.2.2 ALTIBASE的锁类型ALTIBASE支持行级锁和表级锁。行级锁行级锁只会对一个事务所要变更的数据记录行进行锁定,而不会影响其他的记录,这样其他的事务可以并发的对其他行记录进行操作。因此,行级锁具有最好的并发性,允许并发的操作同一张表中的不同的行记录。ALTIBASE默认的锁级别为行级锁。表级锁在ALTIBASE中,可以使用lock table显式的为数据表加表级锁,直到提交或回滚事务时才会释放。关于lock table语法请参照SQL Users Manu
32、al。锁升级锁升级是将许多较细粒度的锁转换成数量更少的较粗粒度的锁的过程,这样可以减少系统开销,但却增加了并发争用的可能性。在ALTIBASE中会有锁升级发生。从应用的角度来说,除非您明确的知道,在什么时候、做哪些操作时会发生锁升级,知道锁升级会给其它并发应用带来哪些影响,而且可以接受,否则锁升级还是不发生为好。在ALTIBASE中,LOCK_ESCALATION_MEMORY_SIZE的值限制了锁升级发生的条件,默认设置是100M。就是说在事务中,当行维护锁的数据超过100M时,会引起锁升级。事务会给表加排它锁,并使用和磁盘表空间相同的in-places方式处理多版本并发。在事务中产生大量锁
33、的原因,一般来说是对大数据量的表执行了update操作。在实际应用中,对表执行udpate操作,由于数据量过大导致长时间执行,而且使维护锁的数据量超过了100M而引起锁升级,这样的操作本身对系统性能就会有很大影响。此时,由于要更新海量数据,在MVCC下也产生了大量的数据版本,在锁升级发生的前后,都可能会阻塞其它使用该表的事务提交。签于此,在电信系统中可能引起锁升级的操作,本身就可能对系统性能产生较大影响,应该避免。通过设置TRX_UPDATE_MAX_LOGSIZE,当维护锁的数据量超过这个值时,事务会失败返回错误。通常把这个值设为10M,所以事务锁不会达到100M也就不会发生锁升级。 如何使
34、用锁对于一个数据库来说,锁和并发性一直是一个矛盾的,并且在某些并发操作的场景下(非串行化隔离级别下),我们必须要了解一些由于并发造成的问题,并且要在应用的开发和设计过程中避免这些问题的发生。遗失更新问题遗失更新(lost update)是一个经典的数据库问题(在非串行化隔离级别下会发生)。实际上,所有多用户计算机环境都存在这个问题。简单地说,出现下面的情况时(按以下所列的顺序),就会发生丢失更新:(1) 会话Session1中的一个事务获取(查询)一行数据,放入本地内存,并显示给一个最终用户User1。(2) 会话Session2中的另一个事务也获取这一行,但是将数据显示给另一个最终用户Use
35、r2。(3) User1使用应用修改了这一行,让应用更新数据库并提交。(4) User2也修改这一行,让应用更新数据库并提交。会话Session2的事务现在已经执行。这个过程称为“丢失更新”,因为第(3)步所做的所有修改都会丢失。通常,解决遗失更新的方法有三种:悲观锁定、乐观锁定。悲观锁定悲观锁定是通过执行select for update这样的语句实现的。这种方式在一定程度上阻止了对同一条记录进行并发操作的情况。悲观锁定(pessimistic locking)仅用于有状态(stateful)或有连接(connected)环境,也就是说,你的应用与数据库有一条连续的连接,而且至少在事务生存期
36、中只有你一个人使用这条连接。这是客户/服务器应用中的一种流行做法。每个应用都得到数据库的一条直接连接,这条连接只能由该应用实例使用。乐观锁定乐观锁定(optimistic locking),即把所有锁定都延迟到即将执行更新之前才做。这种方式的出发点是我们认为数据不会被其他用户修改;因此,会等到最后一刻才去看我们的想法对不对。这种锁定方法在所有环境下都行得通,但是采用这种方法的话,执行更新的用户“失败”的可能性会加大。而失败的结果是:这个用户要更新他的数据行时,发现数据已经修改过,所以他必须从头再来。实现乐观锁定的方式是可以在应用中同时保留旧值和新值,然后在更新数据时使用如下的更新语句,这是乐观
37、锁定的一种流行实现:Update tableSet column1 = :new_clumn1, column2 = :new_column2, Where primary_key = :primary_key在这种情况下,如果更新语句更新了一行,那我们很幸运;这说明,在读数据和提交更新之间,数据没有改变。但是如果更新了零行,我们就会失败;另外一个人已经修改了数据,现在我们必须确定应用中下一步要做什么。是让最终用户查询这一行现在的新值,然后再重新开始事务呢(这可能会让用户很受打击,因为这一行有可能又被修改了)?还是应该根据业务规则解决更新冲突,试图合并两个更新的值(这需要大量的代码)?实际上,
38、前面的UPDATE能避免丢失更新,但是确实有可能被阻塞,在等待另一个会话执行对这一行的UPDATE时,它会挂起。如果所有应用(会话)都使用乐观锁定,那么使用直接的UPDATE一般没什么问题,因为执行更新并提交时,行只会被锁定很短的时间。不过,如果某些应用使用了悲观锁定,它会在一段相对较长的时间内持有行上的锁,你可能就会考虑使用SELECT FOR UPDATE NOWAIT,以此来验证行是否未被修改,并在即将UPDATE之前锁定来避免被另一个会话阻塞。阻塞如果一个会话持有某个资源的锁,而另一个会话在请求这个资源,就会出现阻塞(blocking)。这样一来,请求的会话会被阻塞,它会“挂起”,直至
39、持有锁的会话放弃锁定的资源。几乎在所有情况下,阻塞都是可以避免的。实际上,如果你真的发现会话在一个交互式应用中被阻塞,就说明很有可能同时存在着另一个bug,即遗失更新,只不过你可能没有意识到这一点。也就是说,你的应用逻辑有问题,这才是阻塞的根源。死锁和死锁检测如果你有两个会话,每个会话都持有另一个会话想要的资源,此时就会出现死锁(deadlock)。例如,如果数据库中有两个表A和B,每个表中都只有一行,就可以很容易地展示什么是死锁。要做的只是打开两个会话,在会话A中更新表A,并在会话B中更新表B。现在,如果想在会话B中更新表A,就会阻塞。会话A已经锁定了这一行。这不是死锁,只是阻塞而已。因为会
40、话A还有机会提交或回滚,这样会话B就能继续。如果再回到会话A,试图更新表B,就会导致一个死锁。ALTIBASE管理事务池(Transaction Pool)并通过直接访问事务池检查事务是否正在被执行。这种提前构造事务池对死锁的处理有很大的好处,可以在死锁刚刚发生的时候立即检测到,并终止造成死锁的那个事务。2.3 并发控制 什么是ACID原子性 Atomicity事务的原子性指的是,事务中包含的程序作为数据库的逻辑工作单位,它所做的对数据修改操作要么全部执行,要么完全不执行。这种特性称为原子性。ALTIBASE完整的支持事务的原子性。一致性 Consistency事务的一致性指的是在一个事务执行
41、之前和执行之后数据库都必须处于一致性状态,这种特性称为事务的一致性。例如,当数据库处于一致性状态S1时,对数据库执行一个事务,在事务执行期间假定数据库的状态是不一致的,当事务执行结束时,数据库处在一致性状态S2。拿银行转账来说,一致性要求事务的执行不应改变A、B两个账户的金额总和。如果没有这种一致性要求,转账过程中就会发生钱无中生有,或者不翼而飞的现象。事务应该把数据库从一个一致性状态转换到另外一个一致性状态。ALTIBASE完整的支持事务的一致性。隔离性 Isolation隔离性指并发的事务是相互隔离的。即一个事务内部的操作及正在操作的数据必须封锁起来,不被其它企图进行修改的事务看到。隔离性
42、是DBMS针对并发事务间的冲突提供的安全保证。DBMS可以通过加锁在并发执行的事务间提供不同级别的分离。假如并发交叉执行的事务没有任何控制,操纵相同的共享对象的多个并发事务的执行可能引起异常情况。DBMS可以在并发执行的事务间提供不同级别的分离。分离的级别和并发事务的吞吐量之间存在反比关系。较多事务的可隔离性可能会带来较高的冲突和较多的事务流产。流产的事务要消耗资源,这些资源必须要重新被访问。因此,确保高分离级别的DBMS需要更多的开销。ALTIBASE支持的隔离级别参照持久性 Durability持久性意味着当系统或介质发生故障时,确保已提交事务的更新不能丢失。即一旦一个事务提交,DBMS保
43、证它对数据库中数据的改变应该是永久性的,耐得住任何系统故障。ALTIBASE可以分别支持宕库情况下的持久性和宕机情况下的持久性。默认为宕库级别持久性。2.3.2 什么是隔离级别SQL 标准用三个必须在并行的事务之间避免的现象定义了四个级别的事务隔离。这些不希望发生的现象是: 脏读(dirty reads) 一个事务读取了另一个未提交的并行事务写的数据。 不可重复读(non-repeatable reads) 一个事务重新读取前面读取过的数据, 发现该数据已经被另一个已提交的事务修改过。 幻读(phantom read) 一个事务重新执行一个查询,返回一套符合查询条件的行, 发现这些行因为其他最
44、近提交的事务而发生了改变。标准的隔离级别的定义参见下表隔离级别脏读Dirty Read不可重复读NonRepeatableRead幻读Phantom Read读未提交Read uncommitted可能可能可能读已提交Read committed不可能可能可能可重复读Repeatable read不可能不可能可能可串行化Serializable不可能不可能不可能表2-1:隔离级别矩阵ALTIBASE完整的支持读已提交(Read Committed)、可重复读(Repeatable Read)、串行化(Serializable)隔离级别。2.3.3 为什么需要读一致性什么是读一致性:对于某个时间
45、点(point in time),查询会产生一致的结果。为了说明实现读一致性的重要性,这里需要举个典型的案例来更直观的说明。案例:查询余额这个案例将让我们看到在并发情况的读一致性是如何保证数据的准确的,反之则会有错误的统计结果出现。为了简化这个案例的模型,我们只选择了一个余额账本表,并且将表中的字段简化到只有三个字段。create table OCS_ACCT_BALANCE(ACCT_BALANCE_ID INTEGER NOT NULL,BALANCE BIGINT NOT NULL,ACCT_ID BIGINT NOT NULL,primary key(ACCT_BALANCE_ID);
46、各个字段的含义是:ACCT_BALANCE_ID:余额账本标识BALANCE:本账本中的余额ACCT_ID:账户标识对于一个账户,一般会有多个账本。也就是表中的ACCT_ID和ACCT_BALANCE_ID是一对多的关系,主键是ACCT_BALANCE_ID。在实际的余额账本表中会有几百万甚至上千万的数据记录,并且每个账户的余额是有差异的。这里为了方便说明,我们会构建一个600万记录的余额表,并且每个账本记录的余额都是100。可以通过建立一个存储过程来完成数据的初始化过程。CREATE OR REPLACE PROCEDURE proc_readconsistent_init(recordnum IN INTEGER)ASv1 INTEGER:=1;BEGIN DELETE FROM OCS_ACCT_BALANCE; FOR i IN 1 . recordnum LOOP INSERT INTO OCS_ACCT_BALANCE VALUES(v1,100,v1); v1:=v1+1; IF MOD(v1,1000)=0 THEN println(commit record : |v1); commit; END IF; END LOOP; commit;END;/然后执行该存储过程,向余