中断处理在任何大型的系统(数据库或者操作系统)中都有着十分重要的作用。一个数据库系统的应用程序可能有很多 SQL 语句组成,这些语句包括 DDL (Data Definition Language, 数据描述语言 ) 和 DML (Data Management Language, 数据管理语言 ), 用户在执行这些语句的时候会遇到各种各样的问题,以至于语句无法完整或者正确的执行,在某些特殊的情况下,用户会考虑中断一些正在执行过程中的语句,这些情况大致包括:
- 语句执行时间过长,或者用户等待了很长时间并且没有等待到预期的结果。
- 用户已经看到自己满意的结果,并不需要相应的语句完整的执行下去。
- 一些比较特殊的原因诸如数据库发生死锁,内存泄漏导致的内存不足等。
传统的数据库系统都需要支持中断处理,其处理过程一般分成以下几个过程,执行具体的请求前注册特定的中断处理函数或者程序,然后接受并且执行相应的请求,接下来当中断请求被处理的时候,执行已经注册的函数或程序,最后回到之前的请求继续执行。这种简单的中断模型并不适应于复杂的分布式联邦数据库语句。
联邦数据库的语句执行模型有别于传统的数据库系统,客户端把语句执行请求通过特定的协议发给引擎端,引擎端通过数据库的编译系统把得到的语句分成两个部分,一部分将运行在引擎端,另外一部分将会在数据源端进行执行,当且仅当数据源端执行完毕并且把相应的结果集返回时,引擎端才能进一步进行处理。同时,这两部分可能会在完全两个不同的进程中执行。因此,这种不同的执行模型需要另外一种基于数据源的中断模型去处理整个语句中断过程。
本文所描述的联邦数据库的语句中断处理(本文以下特指 DB2 LUW 数据源),它是一种基于多进程的,多阶段执行的,分布式的数据库中断处理方法,它具备以下特性和优点:
- 处理多阶段执行的语句,对于联邦数据库的语句执行模型有着完备的支持。
- 处理多进程,不同进程会处理不同的请求,对于多进程中断的支持使得每个进程都可以保证中断的连续性。
- 支持各种不同的 DML 语句,其中包括查询,插入删除或者更改,存储过程等。
- 支持不同的中断级别,包括语句级别和事务级别。(下文会详细描述)
图 1. 联邦数据库中断的工作流程
DB2(本文提到的 DB2 均指 DB2 LUW)的中断处理是一种基于 Breathing Point(中断检查点)的中断处理。所谓 Breathing Point 是指在程序实现过程中,在一些已知的函数或者过程当中加入一些检查点,通过在程序执行过程中动态检查一些中断状态标志位的变化去捕获中断并且调用相应的中断处理函数,以达到中断程序执行的目的。对于 Breathing Point 的实现有很多种,但是其本质上要求相关函数或者过程有适当的机会去做检查。对于 IFS 上的语句,由于其执行过程的重要一部分是在远程数据源上,这就意味着如果语句的执行在远端是没有办法返回并且去做相应的检查的,由此看出在 IFS 上使用 Breathing Point 的方式去实现中断是不可能的。
另外,传统的操作系统应用程序中断是基于操作系统的中断回调函数的,其过程是利用操作系统提供的中断号,注册相应的中断回调函数,当中断发生时由操作系统本身对中断进行响应,调用注册的回调函数完成中断,其中断的捕获依赖操作系统的实现。这种方式的最大缺点是其不可控制性,原因是操作系统中断回调函数的执行是应用程序不可控制的,尤其是执行的 Timestamp(时间点)。对于 IFS 上使用这种方式可能会给系统带来极大的负面效果,因为第三方库提供的程序接口的实现是不可控制的。下面是一个例子:
假设数据源语句执行的接口是 Stat_Execute,中断借口是 Stat_Break,实现如下:
void Stat_Execute ()
{
grab_mutex(thread_lock);
... do some initial processing release_mutex(thread_lock);
... do actual request processing
(block on remote server until request completes)
}
void Stat_Break ()
{
grab_mutex(thread_lock);
... do some initial processing release_mutex(thread_lock);
... do cancel processing (send request to remote server)
}
|
这里,一种如下的执行过程将会导致数据源端遇到死锁的情况:
- 在线程执行之前通过操作系统接口注册了中断回调函数,也就是代码里面的 Stat_Break。
- 执行的线程调用了 Stat_Execute并且已经通过 Grab_mutex得到了锁资源,此时该线程在执行一些初始化的工作。
- 这时候,中断发生,操作系统中断回调函数也就是 Stat_Break被执行(请注意操作系统中断回调函数随时都可以被调用)。该执行线程又再次希望去获得之前的锁资源。
- 但是该线程之前并没有机会释放锁资源, 这就相当于在一个线程当中连续申请两次同一个锁资源,这样死锁就发生了。
上述的例子可以直观的让读者明白操作系统的中断处理在 IFS这种多阶段分布式语句处理系统中是不适用的。对于 IFS上,语句中断的捕获是通过不同的线程来实现,它使用一种我们称为 Statement Handler(语句处理函数)来触发,其实现的方式和操作系统的回调函数有一定的相似性,但是在 IFS中我们能够更方便的控制和处理它。大致的过程如下:
- 在线程把语句发送到远端数据源之前,把 Statement Handler注册到相应的线程控制结构中,这样每个线程都会有其对应的 Statement Handler链表,而实际上这些 Statement Handler就是数据源提供的中断处理函数接口。
- 线程开始执行远端数据源上的语句,用户的中断请求从客户端发出被引擎端接受。
- 引擎端接受到中断请求,通过另外一个线程去获取当前执行线程的 Statement Handler,并且执行它去实现中断。
需要注意的是,这里我们并不需要重新获得数据库的连接信息,因为执行中断和被中断的线程同属于一个进程,所以数据库的连接信息是可以被重用的。当然,在某些特殊的第三方客户端并不适用,这取决于客户端是否是 Threaded Safe(线程安全)的。
这一节我们主要介绍联邦数据库中断的架构。 IFS 由于其语句执行的特殊性使得其中断主要分成以下几个重要的方面:
- 中断连续性:
Select t1.c2, n1.c1 from t1, n1 where t1.c1 = n1.c2 |
之前我们已经描述过,对于一条 IFS 下的 DML 语句,我们可以把它分成引擎端和数据源端两个部分。数据源端的执行是针对远程的结果集部分,而引擎端则是针对近程的结果集。下面是一个例子:
对于这样一条 JOIN 语句,其中 t1 代表的是 DB2 的一个近程表,而 n1 代表的是 DB2 LUW 远端数据源上的一个 nickname(别名),对这样一条语句来说,获取 n1 的信息就属于数据源端的部分,而获取 t1 并且进行数据的集合操作就属于引擎端的。
那么,中断这样的语句就需要对两个部分作不同的处理,如果语句的执行停留在数据源端,那么必须通过先中断远程部分使得远程语句返回,来达到中断整个语句的目的。
- 分布式中断:
Select n1.c1, n2.c1 n3.c1 from n1, n2, n3 Where n1.c2 = n2.c2 and n1.c3 = n3.c3 and n2.c4 = n3.c4 |
在一个 IFS 的分布式引擎上可能会连接一个或者更多的数据源,那么一条 DML 语句可能牵涉不同的数据源。这样,一条语句可能会变得十分复杂。
上面这条 DML 语句包含了三个不同的 nickname,对于三个不同数据源上的表,这条语句的中断就比较复杂,因为其包含了三条远端的语句,那么,每条语句都要求在中断过程中被分别处理。
- 不同模式下的中断:
这里提到也是联邦数据中断的核心过程,在这之前有必要提及 IFS 上语句运行的模式,Trusted(可信赖模式)和 Fenced(保护模式)。在包括 v9.5 后的 DB2 版本里 db2agent 已经由进程改为线程,即每一个数据库连接由一个线程去完成。那么,在 IFS 上 Trusted 和 Fenced 两种模式的区别主要区别在于上面提到的引擎端和数据源端语句的执行是否在一个进程中,即在 Trusted 模式下,近端和远端的执行都在一个线程中完成,就是 db2agent,而在 Fenced 模式下,远端部分由 db2fmp 进程下的一个线程去完成。那么对于两种不同的模式,其中断的架构如下:
1、Trusted 模式下的中断架构
图 2. Trust 模式下的联邦数据库中断处理
对于 Trusted 模式,其中断的过程分为以下几个步骤:
- 客户端应用程序把语句执行请求发送给引擎端。引擎端使用一个 db2agent 处理相应的请求。
- 在语句请求的远端被发送到数据源上执行之前,对这个 db2agent 设置 statement handler 也就是语句处理函数。
- 客户端因为某种原因发出中断请求。引擎端得到了这个中断请求,初始化另外一个 db2agent 去处理中断。
- 处理中断的 db2agent 将会去调用之前设置好的语句处理函数,这样,远程语句就会被顺利的中断并且返回。
- IFS 将会按照相应的逻辑进行中断的后续处理工作,接下来控制权将返回给客户端。
2、Fenced 模式下的中断架构
对于 Fenced 模式,其中断的过程分为以下几个步骤:
- 基本逻辑和 Trusted 模式下是相似的。处理中断和被中断的 db2agent 还是会分别执行中断和运行的功能。
- 最主要的区别是数据源的语句试运行在另外一个叫做 db2fmp 进程里的一个线程中,因而,负责中断的 db2agent 将不可能直接中断远程语句,相应的,它会通过 IPC(Inter Process Communication,进程间通信)的方法给 db2fmp 发送一个中断请求。
- 相比于 Trusted 模式,真正执行数据源端语句运行和中断的是两个在 db2fmp 进程下的线程,而原先的 db2agent 只负责和 db2fmp 进行通信。
- 同样,IFS 还需要分别对被中断的线程进行一些类似于清理的后续工作。
图 3. Fenced 模式下联邦数据库的中断处理
对于大型的数据库管理系统来说,数据的连续性是极其重要的。最常用的维护数据连续性的方式就是事件。用户可以根据应用程序的上下文选择提交或者回滚,以次方式来控制应用程序对数据库内容的修改。
这里我们所谓的中断级别,就是指在中断过程中在合适的时机利用 IFS 自身的事件回滚和连接的中断来维护中断过程中的数据连续性。在这里我们可以先明确一下两个概念。
- Inbound connection(内连接),图 1 是 IFS 的中断架构,也是其语句执行的基本架构,从中我们看到的从客户端到 IFS 引擎端的连接,称为内连接。
- Outbound connection(外连接),还是图 1,从 IFS 引擎到数据源端的连接,称为外连接。
对于 IFS 的中断处理,我们提供了两个中断级别,相应的就是两种不同的中断方式:
- 事件级别:在这个级别中,中断处理使得当前应用程序的事件回滚,同时内连接和外连接都相应的断开,最后整个应用程序都停止,处理当前应用程序的线程都被回收。这个级别适用于用户中断的目的是整个应用程序,比如在数据源出现死锁,内存泄漏导致的程序失败,这个时候程序执行的结果已经不可靠的情况。在中断结束以后,任何之前没有被提交的数据库更改都不会起任何作用。
- 语句级别:在这个级别中,中断处理的目标只是当前的语句,内连接和外连接都不会被断开。应用程序仍旧可以继续执行下去,相应处理程序的线程也仍旧处于可运行的状态。这个级别适用于用户中断的目的是语句,换句话说,用户只是期望当前的语句不用执行,比如执行实践过长,或者已经得到足够的执行信息(这种情况通常发生在 SELECT 语句中)。那么,在中断结束后,事件也没有被回滚,用户可以根据接下来程序执行的状况决定提交或者回滚。
对于上述两个中断级别,中断的方式也是不同的。对于事件级别,可以使用 DB2 提供的“ force application ”方式进行中断,其命令格式为:
>>-FORCE APPLICATION--+-ALL--------------------------+---------->
| .-,------------------. |
| V | |
'-(----application-handle-+--)-'
>--+------------+----------------------------------------------><
'-MODE ASYNC-'
|
那么对于语句级别,就可以使用在操作系统上一般的中断方式在控制台使用键盘敲入“ Ctrl-C ”来进行。当然不是所有的控制台都可以接受“ Ctrl-C ”,在这样的情况下,我们推荐使用操作系统的“ kill ”命令,具体的:
Kill -2 db2_process_id Db2_process_id就是DB2 前端进程的ID。 |
我们将在下面一节给出一些具体的实例。
本节将给出联邦数据库中断的一些用户实例,我们这里假设用户已经按照标准定义了 IFS 中的一些实体,这些实体包括 Wrapper, Server, Nickname, FSTP (Federated Stored Procedure) 。
- 实例一:用“force application”作联邦数据库的中断
db2 => connect to test db2 => select * from n1 |
首先在系统中我们连接至数据库并且执行 SELECT 语句,目的是从 n1(一个 DRDA 数据源上的别名)中获取表里面的数据。我们使用如下命令:
这个时候,在获取数据时因为某些特殊原因,在一段时间内并没有得到结果,接下来我们可以使用“ list application ”命令来查看应用程序的执行状况。
db2 list applications show detail CONNECT Auth Id Application Name Appl. Application Id Seq# Number of Coordinating DB Coordinator Status Status Change Time DB Name DB Path Handle Agents partition number pid/thread --------- -------- ------ ---- ------ -------- -------------------- IIDEV11 db2stmm 13 *LOCAL.DB2.090615225225 00001 1 0 10539 Connect Completed Not Collected TEST /home/iidev11/iidev11/NODE0000/SQL00003/ IIDEV11 db2fw3 19 *LOCAL.DB2.090615225231 00001 1 0 8740 Connect Completed Not Collected TEST /home/iidev11/iidev11/NODE0000/SQL00003/ IIDEV11 db2bp 7 *LOCAL.iidev11.090615225221 00002 1 0 2829 Federated request pending Not Collected TEST /home/iidev11/iidev11/NODE0000/SQL00003/ IIDEV11 db2fw2 18 *LOCAL.DB2.090615225230 00001 1 0 9768 Connect Completed Not Collected TEST /home/iidev11/iidev11/NODE0000/SQL00003/ IIDEV11 db2fw1 17 *LOCAL.DB2.090615225229 00001 1 0 10025 Connect Completed Not Collected TEST /home/iidev11/iidev11/NODE0000/SQL00003/ IIDEV11 db2fw0 16 *LOCAL.DB2.090615225228 00001 1 0 10282 Connect Completed Not Collected TEST /home/iidev11/iidev11/NODE0000/SQL00003/ IIDEV11 db2wlmd 15 *LOCAL.DB2.090615225227 00001 1 0 9511 Connect Completed Not Collected TEST /home/iidev11/iidev11/NODE0000/SQL00003/ IIDEV11 db2taskd 14 *LOCAL.DB2.090615225226 00001 1 0 10796 Connect Completed Not Collected TEST /home/iidev11/iidev11/NODE0000/SQL00003/ IIDEV11 db2evml_DB2DETAILDEA 20 *LOCAL.DB2.090615225232 00001 1 0 9254 Connect Completed Not Collected TEST /home/iidev11/iidev11/NODE0000/SQL00003/ |
从中可看出,ID 为 7 的应用程序正在被编号为 2829 的 db2agent 处理,同时应用程序处于“ Federated request pending ”的状态,这个状态告诉我们语句的执行在远端没有返回结果。你也可以使用如下命令观察相应的 db2agent 的状态,可以看出这个 db2agent 正连接到相应的数据库实例中(部分输出)。
db2pd –edus EDU ID TID Kernel TID EDU Name USR (s) SYS (s) 。。。。。。 2829 2829 717403 db2agent (TEST) 3.476331 0.096430 |
接下来,用户就可以使用下面的命令中断应用程序。
Force application (7) |
当执行完以后,整个应用程序都会被终止,而且 2829 号 db2agent 会处于空闲的状态,可以使用之前的命令,用户会得到以下结果(部分输出)。
如果此时系统上运行其他的应用程序,对当前的应用程序进行中断将不会影响其他程序的执行,那么上面运行“ db2 list applications show detail ”的结果将会包括其他的应用程序。
- 实例二:用“Ctrl-C”或者“kill -2”作联邦数据库的中断
和上面的例子有一定的相似,这里我们使用“ Ctrl-C ”或者“ kill -2 ”的方式,让我们看一下和上面的区别,当中断前,我们使用“ psdb2 ”命令察看当前应用程序的 db2(db2 前端处理进程,属于 db2 客户端)进程。
psdb2: 532906 db2 311330 db2acd 107068 db2sysc 516442 /home/iidev11/sqllib/bin/db2bp 405606A5011 5 A 471538 /home/iidev11/sqllib/bin/db2bp 598686A5011 5 A |
由于当前系统只有一个应用程序,我们可以看出进程号为 532096 的 db2 进程就是处理当前应用程序客户端的前端进程。于是我们可以使用
Kill -2 532906 |
或者,在之前执行 SELECT 语句的终端上使用“ Ctrl-C ”来对语句进行中断,中断的结果和上面的“ force application ”是不一样的。具体的“ db2pd -edus ”的部分输出
db2pd –edus EDU ID TID Kernel TID EDU Name USR (s) SYS (s) 。。。。。。 2829 2829 717403 db2agent (TEST) 3.476331 0.096430 |
以及“ list applications ”的部分输出
db2 list applications show detail CONNECT Auth Id Application Name Appl. Application Id Seq# Number of Coordinating DB Coordinator Status Status Change Time DB Name DB Path Handle Agents partition number pid/thread 。。。。。。 db2bp 7 *LOCAL.iidev11.090615225221 00002 1 0 2829 UOW_WAITING Not Collected TEST 。。。。。。 |
我们不妨看出,相应的 db2agent 仍旧连接在数据库上,同时整个应用程序还是存在,它的状态由其接下来运行的结果所决定。
Fetch Statement (SELECT) IUD Statement (Insert, Update, Delete) FSTP Statement (Federated Stored Procedure) Statement Under Passthru Mode |
下面列出的是联邦数据库中断可以支持的语句:
1、目前联邦数据库的语句中断处理仅限于 DB2 LUW 数据源,在以后的版本上会陆续支持其它数据源。
2、对于 Fenced ATQ (Asynchronous Table Queue) 被设置的情况下,联邦数据库的语句中断不能够正常执行。关于 ATQ,请参考以下链接。 http://www.ibm.com/developerworks/db2/library/techarticle/dm-0611norwood/
学习
- 通过 “联邦数据库技术”,了解联邦数据的概念和相关技术。
- 通过访问 InfoSphere Federation Server 产品专题,了解更多有关 InfoSphere Federation Server 的更多产品和技术资源。
- 参考“IBM DB2 V9.7 信息中心(联合)”,了解更多 DB2 V9.7 及 InfoSphere Federation Server 安装、升级、管理和诊断的相关内容。
- 通过 developerWorks Information Management 专区:在这里可以学到更多关于 Information Management 的知识。还可以找到技术文档、how-to 文章、培训、下载、产品信息等。
- 访问 InfoSphere 产品专题,阅读文章和教程并连接到其他参考资料,从而提高您的 InfoSphere 技能。
获得产品和技术
- 下载 IBM 软件试用版,体验强大的 DB2®,Lotus®,Rational®,Tivoli®和 WebSphere®软件。
-
下载 DB2 9 for Linux, UNIX, and Windows 的免费试用版。
-
现在可以免费使用 DB2。下载 DB2 Express-C,这是为社区提供的 DB2 Express Edition 的免费版本,它提供了与 DB2 Express Edition 相同的核心数据特性,为构建和部署应用程序奠定了坚实的基础。
讨论