progress的数据库访问--事务

来源:互联网 发布:中国金融数据 编辑:程序博客网 时间:2024/05/29 13:17
progress的数据库访问--事务

关键字:progress 4GL 数据库 事务 transaction database

什么是事务,我想就不用再多说了.这里只说一下在progress里事务在什么地方开始,什么地方结束.
首先要说的是,在progress种,一个当前会话同时最多只能拥有一个事务.当然可以在一个事务结束之后启动另外一个新的事务.

progress怎样知道一个事务是从什么地方开始,并且在什么地方结束呢? 这都是由事务块儿定义的.
如果当前会话没有事务,则以下语句块儿开始一个事务:
1.任何使用了关键字transaction的语句块儿,do,for each或者repeat
2.一个直接改变了数据库值的语句块儿,或者在读书数据库的时候使用了exclusive-lock锁.这样的语句块儿包括过程块儿,事件块儿,以及do on error,for each,repeat的每一次迭代.

直接改变数据库的值意味着该语句块儿至少包含一句代码可以改变数据库内容. 比如create,delete,update语句.
如果find或者for each语句指定了exclusive-lock,并且至少有一个不是嵌入在别的事物内部,则该语句块儿会使用exclusive-lock来读取数据.

要注意的是do语句块并不会自动的拥有事务属性,不过你可以显示的使用transaction属性.

小提示:有一个函数transaction可以返回当前所在处是否有一个活动的事务.注意该函数调用不需要括号.

下面的代码给出了演示:

/*trans-test.p*/

MESSAGE "the procedure block" skip transaction
    VIEW-AS ALERT-BOX INFO BUTTONS OK.
repeat :
    MESSAGE "repeat outer" skip transaction
        VIEW-AS ALERT-BOX INFO BUTTONS OK.
    insert order.
    repeat:
        MESSAGE "repeat inner" skip transaction
            VIEW-AS ALERT-BOX INFO BUTTONS OK.
        create customer.
        assign customer.customer = "custaaaa"
                   customer.name = "progress".
        disp customer.
        leave.

    end.
    leave.
end.

MESSAGE "the procedure block2" skip transaction
    VIEW-AS ALERT-BOX INFO BUTTONS OK.

for each order:
    MESSAGE "for" skip transaction
        VIEW-AS ALERT-BOX INFO BUTTONS OK.
    disp order.
    update quantity.
    leave.
end.

MESSAGE "the procedure block3" skip transaction
    VIEW-AS ALERT-BOX INFO BUTTONS OK.

/* do:                                           */
/*     find first order exclusive-lock no-error. */
/*     MESSAGE "do" skip transaction             */
/*         VIEW-AS ALERT-BOX INFO BUTTONS OK.    */
/* end.                                          */

MESSAGE "the procedure block4" skip transaction
    VIEW-AS ALERT-BOX INFO BUTTONS OK.

do transaction:
    MESSAGE "do trans" skip transaction
        VIEW-AS ALERT-BOX INFO BUTTONS OK.
    leave.
end.

注意的是,以上的代码必然是在一个p文件中,所以整个文件本身也是一个语句块儿.
以上的代码结果是:
the procedure block     
no
repeat outer
yes
repeat inner
yes
the procedure block2
no
for
yes
the procedure block3
no
the procedure block4
no
do trans
yes

如果去掉do语句的注释,则结果是整个procedure会处于一个事务中.由此可见do语句并不是一个单独的模块,而就是普通的语句.
但是加上transaction属性就不一样了.

接着对上面的文件作了一些修改:

/*trans-test.p*/

MESSAGE "the procedure block" skip transaction
    VIEW-AS ALERT-BOX INFO BUTTONS OK.
repeat :
    MESSAGE "repeat outer" skip transaction
        VIEW-AS ALERT-BOX INFO BUTTONS OK.
    
    repeat:
        MESSAGE "repeat inner" skip transaction
            VIEW-AS ALERT-BOX INFO BUTTONS OK.
        create customer.
        assign customer.customer = "custaaaa"
                   customer.name = "progress".
        disp customer.
        leave.

    end.
    leave.
end.

MESSAGE "the procedure block2" skip transaction
    VIEW-AS ALERT-BOX INFO BUTTONS OK.

for each order:
    MESSAGE "for" skip transaction
        VIEW-AS ALERT-BOX INFO BUTTONS OK.
    disp order.
 
    leave.
end.

MESSAGE "the procedure block3" skip transaction
    VIEW-AS ALERT-BOX INFO BUTTONS OK.

/* do:                                           */
/*     find first order exclusive-lock no-error. */
/*     MESSAGE "do" skip transaction             */
/*         VIEW-AS ALERT-BOX INFO BUTTONS OK.    */
/* end.                                          */

MESSAGE "the procedure block4" skip transaction
    VIEW-AS ALERT-BOX INFO BUTTONS OK.

do transaction:
    MESSAGE "do trans" skip transaction
        VIEW-AS ALERT-BOX INFO BUTTONS OK.
    leave.
end.

结果变成了:
the procedure block     
no
repeat outer
no
repeat inner
yes
the procedure block2
no
for
no
the procedure block3
no
the procedure block4
no
do trans
yes

要注意的是,对于for,repea这样的迭代语句,每一次循环就是一个事务.循环十次就意味着先后有十个事务.比如:
for each order:
   update quantity.
end.

如果一个订单的量修改完毕,则事务结束并且结果提交到数据库. 如果是最后一个订单发生错误而导致回滚,则只有最后一个订单的更新数据丢失.

由此可以知道你可以自己控制一个事务块的大小.这里就不举例了.

所以说,如果碰到了一个可以启动一个事务的语句块儿,首先要看当前又没有活动的事务.如果没有,则启动一个新事务,不然的话,这整个语句块都是已有事务的一部分.
这一规则可以运用到其他地方,比如事件处理,子程序调用,文件读取.特别是对于文件读取,一旦失败,所有的操作都会回滚,因此最好的办法是,每读取一行,创建一个事务,同时记录当前行号.
有兴趣的话,自己可以使用transaction函数来测试一下.




原创粉丝点击