免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5767 | 回复: 8
打印 上一主题 下一主题

关于Informix 行锁,求解决方法 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-02-23 10:23 |只看该作者 |倒序浏览
20可用积分
在数据库里建一表 bepsszfxh ,建表语句如下:
[leshy@leshy ~]$ oncheck -pt leshydb1:bepsszfxh



TBLspace Report for leshydb1:leshy.bepsszfxh

    Physical Address               1:12986
    Creation date                  02/18/2009 05:24:22
    TBLspace Flags                 802        Row Locking
                                              TBLspace use 4 bit bit-maps
    Maximum row size               36        
    Number of special columns      0         
    Number of keys                 0         
    Number of extents              1         
    Current serial value           1         
    First extent size              16        
    Next extent size               16        
    Number of pages allocated      16        
    Number of pages used           2         
    Number of data pages           1         
    Number of rows                 30        
    Partition partnum              1049008   
    Partition lockid               1049008   

    Extents                       
         Logical Page     Physical Page        Size
                    0           1:13219          16

[leshy@leshy ~]$ cat bepsszfxh.sql
{ TABLE "leshy".bepsszfxh row size = 36 number of columns = 4 index size = 0 }
create table "leshy".bepsszfxh
  (
    zl char(2) not null ,
    jgm char(10) not null ,
    xh integer not null ,
    memo char(20) not null
  )  extent size 32 next size 32 lock mode row;
revoke all on "leshy".bepsszfxh from "public";
[leshy@leshy ~]$



从以上两点可以看出来它是行锁的。然后我写程序如下:
[leshy@leshy test]$ cat locktest.ec
#include    <stdio.h>

char grs_errmsg[128];

main( argc, argv )
int    argc;
char    *argv[];
{
    EXEC SQL BEGIN DECLARE SECTION;
        char    lds_dbname[20];
        long    ldl_count;
    EXEC SQL  END  DECLARE SECTION;
    int lri_ret=0;
    perror("开始");

    memset(lds_dbname , 0 , sizeof(lds_dbname) );
    memset(grs_errmsg , 0 , sizeof(grs_errmsg) );

    strcpy(lds_dbname,"leshydb1");


    EXEC SQL DATABASE :lds_dbname;
    EXEC SQL BEGIN WORK;

    perror("开始事务!");
    EXEC SQL SET LOCK MODE TO WAIT 4;
   
    EXEC SQL select xh INTO :ldl_count from bepsszfxh where zl = 21;
    printf("EXEC SQL select xh from bepsszfxh where zl = 21;result[%d]",ldl_count);

    EXEC SQL LOCK TABLE bepsszfxh IN EXCLUSIVE MODE ;
    perror("EXEC SQL LOCK TABLE bepsszfxh IN EXCLUSIVE MODE ;");
   
    EXEC SQL UPDATE bepsszfxh SET xh=xh+1 where zl = 21;
    perror("EXEC SQL UPDATE bepsszfxh SET xh=xh+1 where zl = 21;");


    EXEC SQL UNLOCK TABLE bepsszfxh;
    perror("EXEC SQL UNLOCK TABLE bepszsfzh");

    perror("这里没有提交事务,看有没有把表释放");
   
    sleep(1000);

    EXEC SQL COMMIT WORK;
    EXEC SQL CLOSE DATABASE ;
    return 0;

}
[leshy@leshy test]$


测试如下。执行生成的 locktest程序
[leshy@leshy test]$ locktest 开始: Success 开始事务!: Success
EXEC SQL LOCK TABLE bepsszfxh IN EXCLUSIVE MODE ;: Success
EXEC SQL UPDATE bepsszfxh SET xh=xh+1 where zl = 21;: Success
EXEC SQL UNLOCK TABLE bepszsfzh: Success
这里没有提交事务,看有没有把表释放: Illegal seek



然后改一个窗口打开dbaccess 去查询这个表的其它行:
  1. select * from bepsszfxh where zl=22;
复制代码
执行结果提示

   244: Could not do a physical-order read to fetch next row.  
   113: ISAM error:  the file is locked.  


我不知道是不是还有什么需要设置的。我用的Informix版本是
IBM Informix Dynamic Server Version 9.40.UC8     -- On-Line -- Up 00:11:48 -- 29416 Kbytes

操作系统是
Red Hat Enterprise Linux AS release 4 (Nahant Update 7)

同样的程序我在 AIX 5.2 + Informix 7.3下试也不行。

不知道这个该怎么解决了。还请高手指教。

论坛徽章:
0
2 [报告]
发表于 2009-02-23 14:14 |只看该作者
找了一中午,终于找到解决方法了。
应该在写代码的时候将
EXEC SQL LOCK TABLE bepsszfxh IN EXCLUSIVE MODE ;
这一句去掉,同样能在事务中锁定相应的记录不被更新。

再在相应的字段增加索引
create index bepszfxh_idx on bepsszfxh(zl);

更新表
update statistics for table bepsszfxh;


如果还不行的话。那就设置进程隔离级为
Set isolation to Committed Read

这个问题算是解决了。。。

附的为隔离级别的资料:
Informix 进程隔离级(isolation level)
   
    隔离级是指并发执行相同操作的进程相互隔离的程度。OnLine通过设定进程在读操作时上锁的不同规则而提供了四种隔离级:Dirty Read(脏读)隔离、Committed Read(提交后读)隔离、Cursor Stability(游标固定)隔离和Repeatable Read(可重复读)隔离具体说明如下:
    1、Dirty Read(脏读)隔离
    Dirty Read是最简单的隔离级,类同于无隔离级当进程在读数据据时并不对所读的数据上锁,也不管其他进程上没上锁或在做什么。
    2、Committed Read(提交后读)隔离
    当进程请求Committed Read隔离级时,OnLine保证进程得到的数据不是数据库未提交的数据即此时没有其他进程在对这些数据做修改。
    3、Cursor Stability(游标固定)隔离
    当进程使用Cursor Stability隔离级时,OnLine对进程最后获取的一行数据上锁,对普通的游标上一个共享锁,而对修改游标一个升级锁(更新锁)。
    4、Repeatable Read(可重复读)隔离
    Repeatable Read隔离级请求数据库服务器对进程读到的每一行数据都加锁为普通的游标加上共享锁而为修改游标上更新锁这些锁直到游标关闭或事务结束时才释放。Repeatable Read允许用户使用滚动游标对所选择的数据多次读取并保证这些数据没有被修改或被删除。用户设置隔离级的方法是用“Set Isolation To isolationlevel”SQL语句,其中isolationlevel是Dirty Read、Committed Read、Cursor Stability和Repeatable Read之一。在Informix-4gl、ESQL/C、SQL中均可以使用。

[ 本帖最后由 leshy 于 2009-2-23 14:27 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2009-02-23 14:17 |只看该作者
多谢分享!

论坛徽章:
0
4 [报告]
发表于 2009-02-23 14:24 |只看该作者
哦。刚才少加了一条,还需要在相应要查询的字段上加上索引,这样才能解决


create index bepszfxh_idx on bepsszfxh(zl);

论坛徽章:
0
5 [报告]
发表于 2009-02-23 14:33 |只看该作者
建议修改
  extent size 32 next size 32
扩展块太多,会对服务器效率有影响

论坛徽章:
11
金牛座
日期:2015-03-19 16:56:22数据库技术版块每日发帖之星
日期:2016-08-02 06:20:00数据库技术版块每日发帖之星
日期:2016-04-24 06:20:00数据库技术版块每日发帖之星
日期:2016-04-13 06:20:00IT运维版块每日发帖之星
日期:2016-04-13 06:20:00数据库技术版块每日发帖之星
日期:2016-02-03 06:20:00数据库技术版块每日发帖之星
日期:2015-08-06 06:20:00季节之章:春
日期:2015-03-27 15:54:57羊年新春福章
日期:2015-03-27 15:54:37戌狗
日期:2015-03-19 16:56:41数据库技术版块每日发帖之星
日期:2016-08-18 06:20:00
6 [报告]
发表于 2009-02-23 14:50 |只看该作者
不会用esql,帮路过~~

论坛徽章:
0
7 [报告]
发表于 2009-02-23 15:08 |只看该作者

回复 #6 liaosnet 的帖子

我们公司都是用esql
不过我基本上不会。

论坛徽章:
0
8 [报告]
发表于 2009-02-23 16:23 |只看该作者

回复 #5 我是DBA 的帖子

这个是系统自己生成的。这个也只是测试用。其实我对你说的概念不是很理解。呵呵,有空再学学。。。

论坛徽章:
0
9 [报告]
发表于 2009-02-23 16:24 |只看该作者

回复 #8 leshy 的帖子

生产机就要注意,测试机没关系
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP