我们大家都知道DB2 V9.7 数据库,其引入了一系列新的特性,这些新的特征的出现会使客户可以更轻松地节省 IT 成本。起具体的特性包括压缩增强、pureXML 增强、易用性增强、监控增强、工作负载管理增强。
安全性提高、性能提高、应用开发提高、SQL PL 语言支持、SQL 兼容性提高和高可用、备份、日志、弹性、恢复提高等。
本文的重点是介绍“当前已落实”新特性,该新特性的显著特点是在游标稳定性隔离级别时可以明显减少锁等待的出现,以及死锁的出现频率。通过使用“当前已落实”的 CS 隔离级别,可以有效提升高吞吐量事务处理环境下的数据库性能。
从 DB2 V9.7 开始,DB2 通过采用完全锁定避免技术,当能够明确获得数据或者页的“已落实”版本时,允许扫描避免使用行级锁。当无法获知索引或行记录是否已落实时,扫描将改用使用传统的锁定方式。未提交的插入行在行级锁中是直接被标识的,允许“当前已落实”扫描直接忽略或跳过该行。
简介
从 IBM DB2 V9.7 开始,DB2 引入了一系列新特性,使客户可以更轻松地节省 IT 成本。具体包括压缩增强(通过对 XML 数据、临时表、索引、数据复制源表的压缩支持,进一步减少了对存储的需求,提高了 I/O 的效率,提高了对磁盘数据的快速访问)、pureXML 增强(通过对 pureXML 功能的进一步增强,使得数据仓库中可以部署和分析 XML 数据;
现在 XML 可以在表分区、MDC 表、临时表、用户函数、分区数据库环境中使用)、易用性增强(通过对易用性的增强,减少了总体拥有成本 TCO,减少了执行系统管理任务对系统的影响,扩展了以前版本发布的自治特性)、监控增强(可以更灵活、更高粒度的监控 DB2 环境)、工作负载管理增强(新增调配正在进行的活动的优先级、与 Linux 工作负载管理 WLM 集成、对服务类提高缓冲池中 I/O 优先级控制等。
新增了 AGGSQLTEMPSPACE、CPUTIME、CPUTIMEINSC、SQLROWSREAD、SQLROWSREADINSC 等阈值,改进了基于时间的阈值 ACTIVITYTOTALTIME、CONNECTIONIDLETIME 的粒度)、安全性提高(可以对敏感数据进行更好的保护)、性能提高(通过在游标稳定性隔离级别下引入“当前已落实”、扫描共享、在表分区上创建分区索引、在表中存储内嵌 LOB 文件等提高了对数据的访问速度,增加了数据的并发性;
DB2 优化器通过访问计划重用、Statement concentrator 支持等增强了 DB2 的性能)、应用开发提高(通过“使用 ALTER TABLE 重命名列名”等简化了数据库对象的管理,通过引入 TRUNCATE 语句、创建临时表、公共同义词等很多新的功能提高了 SQL 编程、存储过程开发得到了简化和提高等)、SQL PL 语言支持、SQL 兼容性提高(可以从诸如 ORACLE 应用程序等更容易的迁移到 DB2 环境中)和高可用、备份、日志、弹性、恢复提高等。
本文的重点是介绍“当前已落实”(currently committed semantics,以后会简称 CC)新特性,该新特性的显著特点是在游标稳定性(Cursor stability,以后会简称 CS)隔离级别时可以明显减少锁等待的出现,以及死锁的出现频率。
在 DB2 V9.7 之前的版本中,当我们使用游标稳定性隔离级别(默认的隔离级别)时,一般只锁定事务声明并打开的游标当前引用的行,也就是说该事务一般只锁定当前行,对当前行以外的记录不做锁定;对其所获取的锁一直有效,直到游标重定位或事务终止为止 。如果游标重定位,原来行上的锁就被释放,并获得游标现在引用的行上的锁 。
如果事务修改了它检索到的任何行,那么在事务终止之前,其他事务不能更新或删除该行,即使游标不再位于被更新或删除的行 。需要注意:如果只检索的话,一般只锁定当前行;如果对检索的行还进行了更新或删除的话,则对修改的行也进行了锁定,即便指针移向了其他行,对修改行的锁定还是存在。而对修改行的锁定会阻止其他应用程序读取该行,直到对修改行的锁定解除后(对该修改落实后),其他应用才能读取该行。
我们首先来看一下 ORACLE 在 Snapshot 隔离级别下读操作与写操作堵塞的情况,具体如表格 1 所示,当读操作遇上读操作、读操作遇上写操作和写操作遇上读操作都不会发生堵塞,而写操作遇上写操作时则会发生堵塞:
ORACLE Snapshot 隔离级别情况下的的堵塞情况
先出现的工作负载 \ 后出现的工作负载 读工作负载 写工作负载
读工作负载 否(不堵塞) 否(不堵塞)
写工作负载 否(不堵塞) 是(堵塞)
下面我们看一下在 DB2 V9.7 之前的版本中使用游标稳定性隔离级别时读操作与写操作堵塞的情况,具体如表格 2 所示,当读操作遇上读操作时不会发生堵塞;当读操作遇上写操作时可能会发生堵塞(FOR READ ONLY 的读操作不会堵塞写操作,而 FOR UPDATE 的读操作由于其行上有 U 锁,会堵塞写操作);当写操作遇上读操作时一定会发生堵塞,而当写操作遇上写操作时同样会发生堵塞。
DB2 V9.7 之前的版本中使用 CS 隔离级别情况下的堵塞情况
先出现的工作负载 \ 后出现的工作负载 读工作负载 写工作负载
读工作负载 否(不堵塞) 可能
写工作负载 是(堵塞) 是(堵塞)
再看一下在 DB2 V9.7 中,启用“当前已落实”的游标稳定性隔离级别时的读操作与写操作堵塞的情况,具体如表格 3 所示,可以看到比 DB2 之前的版本有了明显的改进,当读操作遇上读操作、读操作遇上写操作和写操作遇上读操作都不会发生堵塞,只有写操作遇上写操作时才会发生堵塞:
DB2 V9.7 中启用“当前已落实”的 CS 隔离级别情况下的堵塞情况
先出现的工作负载 \ 后出现的工作负载 读工作负载 写工作负载
读工作负载 否(不堵塞) 否(不堵塞)
写工作负载 否(不堵塞) 是(堵塞)
在 DB2 V9.7 中,在游标稳定性隔离级别下,通过启用“当前已落实”新特性,一个读操作已经不需要再等待该变更落实后再返回值,而是直接返回该行未变更前的值(也就是当前已落实的结果值,忽略任何可能发生的未落实操作)。不过需要注意的是在可更新游标中存在例外的情况:如果某行基于它自己之前的内容被更新过,当前已落实结果无法立即返回。
在游标稳定性隔离级别使用行级锁的情况(没有启用“当前已落实”)下,可能会出现锁定超时和死锁,特别是那些没有为防止这些问题进行特殊设计的应用程序。某些高吞吐量数据库应用程序不能容忍事物处理过程中的锁等待,某些应用不能容忍处理未提交的数据,但仍然需要不堵塞读操作事务。
通过在 CS 隔离级别下启用“当前已落实”,可以有效提高高吞吐量事务处理环境下的数据库性能。在这些环境中,过多的锁等待是不能容忍的,通过启用“当前已落实”的 CS 隔离级别,可以有效的减少 timeout 和 deadlocks 。在“当前已落实”启用的情况下,只有落实的数据才会被返回,就像之前的例子,现在读操作不需要再等待更新操作释放行级锁了,读操作将直接返回“当前已落实”版本的数据(也就是首次写操作之前的值)。
由于“当前已落实”是 DB2 V9.7 的新特性,很多客户不知道该如何使用,本文将重点介绍 DB2 V9.7 关于“当前已落实”新特性以及相关的概念,并结合实际的例子帮助大家理解和提高。
当前已落实(Currently Committed) 工作原理
从 DB2 V9.7 开始,DB2 通过采用完全锁定避免(full lock avoidance techniques)技术,当能够明确获得数据或者页的“已落实”版本时,允许扫描避免使用行级锁。当无法获知索引或行记录是否已落实时,扫描将改为使用传统的锁定方式。 DB2 通过在行级锁定中增加新的反馈机制,来标识哪些“日志记录”描述了该行的首次修改(从该行的首次修改,就可以获得修改前的数据值,也就是该行的已落实版本),当发生一个锁冲突时锁管理器将使用该反馈机制直接返回这些日志记录编号。
一个当前已落实扫描将用使用该反馈结果,用来从日志(日志缓冲区中或者活动日志文件中)访问该行的“当前已落实”版本(也就是首次更新之前的结果值)。未提交的插入行在行级锁中是直接被标识的,允许“当前已落实”扫描直接忽略或跳过该行。
具体如图 1 所示,emp 表有 5 条记录,其中第二行和第四行插入操作已经完成,描述该插入操作的日志记录已经存储在使用 TSM 归档的带库中,具体如图 1 中右下方红色部分所示;第三行正处于更新状态(还没落实),记录该行的日志记录处于磁盘中的活动日志文件中,该日志记录描述了第三行的首次更改情况,具体如图 1 右边中间黄色部分所示;
第五行正处于插入状态(还没落实),记录该行的日志记录处于磁盘中的活动日志文件中,该日志记录描述了第五行的首次插入情况,具体如图 1 右边中间黄色部分所示;第一行正处于删除状态(还没落实),记录该行的日志记录处于日志缓冲区中,该日志记录描述了第一行的首次更改情况,
具体如图 1 右边上方绿色部分所示;图 1 中间的 Locklist 部分表示锁管理器,在锁管理器中描述了第一行、第三行、第五行处于 X 锁状态,与这些行对应的日志记录也在该锁管理器中,这就是 DB2 V9.7 对行级锁定新增的反馈机制,来标识哪些“日志记录”描述了该行的首次修改。
当发生一个锁冲突时锁管理器将使用该反馈机制直接返回这些日志记录编号,如黑色箭头所示。当其他应用试图读取第一行或第三行时,将会直接从日志缓冲区或日志文件中返回该行的“已落实”版本数据。而对未提交的第五行,扫描将直接忽略或跳过该行。
【编辑推荐】