pb transaction使用完后忘记disconnect的严重后果

来源:互联网 发布:道路算量用什么软件 编辑:程序博客网 时间:2024/06/11 22:02

        很多人都明白,transaction使用完后忘记disconnect的话,数据库服务端的session连接不会释放,从而浪费了服务器资源。其实这只是一部分后果。如果粗心大意,还会造成更大的影响。

        先来做个测试,我新建了一个窗口w_test。在窗口上放置两个按钮cb_1和cb_2。

        cb_1的clicked事件下面定义transaction sqlca1,故意漏掉了disconnect,代码如下:

                   long ll_count
                   transaction sqlca1
                  sqlca1= create transaction
                  sqlca1.DBMS = "MSS Microsoft SQL Server"
                  sqlca1.Database = "his2015"
                  sqlca1.LogPass = "sasasa"
                  sqlca1.ServerName = "."
                  sqlca1.LogId = "sa"
                  sqlca1.AutoCommit = False
                  sqlca1.DBParm = ""
                  connect using sqlca1;
                  messagebox('',string(sqlca1.sqlcode) +sqlca1.sqlerrtext)
                 destroy sqlca1

       定义long ll_count的目的是为了和cb_2的变量一样,这样才能保证sqlca1和sqlca2使用到相同的内存

      cb_2的clicked事件下面定义一个transaction sqlca2,故意漏掉connect,代码如下:

             transaction sqlca2
             long ll_count
             sqlca2 = create transaction
             select count(*) into :ll_count from AAAA using sqlca2;
             messagebox('',string(sqlca2.sqlcode)+sqlca2.sqlerrtext)
             messagebox('',ll_count)

        很多人可能都会说,cb_2的clicked事件下面的sqlca2没有连接到数据库,select不可能查询到数据,但是通过先点击cb_1再点击cb_2,程序运行的结果是查询到了数据。

         下面我将解释一下原理:

         cb_1被点击完之后,sqlca1对象占据了系统内存,但是随着cb_1的clicked事件执行完毕,sqlca1被销毁。相对应的内存也将会被重新使用。

         cb_2被点击完之后,系统会给sqlca2对象分配内存。两个按钮先后被点击,中间没有执行过别的操作。所以sqlca2被分配的内存刚好使用了sqlca1原先使用的那部分内存。而数据库的连接信息是保存在内存中的。所以即便sqlca2没有执行连接到数据库的操作,使用的时候也能够连接到sqlca1所连接的那个数据库。

       为了进一步验证我分析的是正确的。我将cb_1的clicked事件修改如下:

             long i
             transaction sqlca1,sqlca2
             sqlca1= create transaction
             sqlca1.DBMS = "MSS Microsoft SQL Server"
             sqlca1.Database = "his2015"
             sqlca1.LogPass = "sasasa"
             sqlca1.ServerName = "."
             sqlca1.LogId = "sa"
             sqlca1.AutoCommit = False
             sqlca1.DBParm = ""
             connect using sqlca1;
             messagebox('',string(sqlca1.sqlcode) +sqlca1.sqlerrtext)
            destroy sqlca1

            sqlca2= create transaction
            sqlca2.DBMS = "O84 Oracle8/8i (8.x.4+)"
            sqlca2.LogPass = "bsoft"
            sqlca2.ServerName = "GM"
            sqlca2.LogId = "portal_his"
            sqlca2.AutoCommit = False
            sqlca2.DBParm = "PBCatalogOwner='portal_his',CommitOnDisconnect='No'"
            connect using sqlca2;
            messagebox('',string(sqlca2.sqlcode) +sqlca2.sqlerrtext)

            disconnect using sqlca2;

            destroy sqlca2

        当执行到connect using sqlca2;的时候,系统返回的错误是transaction already connected。这也充分验证了sqlca1和sqlca2 使用了相同的内存,并且数据库的连接信息是保存在内存中的。这样的后果就是由于sqlca1忘记 了disconnect,即便sqlca2写的很正确,也无法连接到oracle数据库了,而且connect using sqlca2如果不判断是否成功直接使用的话,感觉在操作oracle数据库,其实是操作了sqlserver数据库。pb的帮助文档里面也提到了无论是connect 还是 disconnect都要判断是否执行成功。而很多程序员都不会去判断的,所以程序的严谨性是很重要的。

3 0