免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 10442 | 回复: 35

一个并发问题。 [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2008-09-06 11:49 |显示全部楼层
数据结构:

  1. table   a (
  2.        code             char(12)      primary  key not null,
  3.        amt              decimal(18,2)                       ,
  4.        enableflag    smallint                     not null
  5. )


  6. table b (
  7.        code            char(12)      primary  key not null,
  8.        amt             decimal(18,2)
  9. )
复制代码


动作流程:

动作1:
        从 table a 中以 a.code = ? 检索出  满足条件的纪录,经过一定的运算后修改 amt 的值。
       从 table b 中以条件 b.code = ? 检索出满足条件的纪录,如果存在,修改 amt 的值,不存在就插入一条纪录。

动作2:
      修改 table a 表中 amt 的值,修改条件是 a.code = ? 也是需要经过运算后修改。


这是两个不同的操作,有可能在间距很短的时间内发生。正确的结果应该是,在进行动作 1 时,动作 2 对 table a 表中满足条件的那条纪录不可读,对 table b 表中满足条件的纪录也同样不可读。只有当动作 1 完全结束后,动作 2 才允许以动作 1 完成后的 amt 的值作为运算的初始值进行运算,并再次修改 amt 的值。

可实际情况是 ASE 好像做不到这个,不知道有什么解决方案没有?

论坛徽章:
0
发表于 2008-09-06 14:02 |显示全部楼层

回复 #1 snow888 的帖子

应该是做的到的!

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2008-09-06 14:05 |显示全部楼层
原帖由 wangledahai 于 2008-9-6 14:02 发表
应该是做的到的!

咋个做呢?

论坛徽章:
0
发表于 2008-09-06 14:51 |显示全部楼层
没看出哪里会有问题!能够说说具体那个地方有疑问?
首先,从这个案例来看,table b对于所描述的两个动作没有任何影响
二,动作1,2都对table a的同样记录作update,第一个session已经加锁,第二个非要等待第一个session完成才能得到锁。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2008-09-06 17:07 |显示全部楼层
原帖由 chenfeng825 于 2008-9-6 14:51 发表
没看出哪里会有问题!能够说说具体那个地方有疑问?
首先,从这个案例来看,table b对于所描述的两个动作没有任何影响
二,动作1,2都对table a的同样记录作update,第一个session已经加锁,第二个非要等待第 ...



晕!

不知道是不是我没有描叙清楚。
感觉斑竹关注点不对啊。

第一个动作对 table a 做了读操作,然后经过一个复杂的运算,在运算的过程中,第二个动作有可能读 table a 的同一条纪录,并且也需要以读取的这条纪录的 amt 字段的内容为基础进行运算,当第二个动作读取完成,运算进行中的时候,第一个动作回写了数据,因此 amt 字段的内容发生了改变,然后是第二个动作完成运算,回写数据库。这时产生了并发问题。

比如

有一条纪录如下:

a.code = 123456
a.amt = 5000.00
a.enableflag = 1

动作一:

检索满足条件的纪录 a.code = '123456' and a.enableflag = 1 ,取出纪录 a.amt = 5000.00
运算公式为 a.amt = a.amt + 20000.00 - 2000.00 = 23000.00

此时:动作二:

从数据库中检索满足条件的纪录 a.code = '123456' and a.enableflag = 1 ,取出纪录 a.amt = 5000.00 (注意:此时动作一还没有开始回写,还在运算中)
动作二开始运算,运算公式为 a.amt =  a.amt + 5000.00 = 10000.00

动作一开始回写数据,此时数据库中 a.code = '123456' 的这条纪录的 a.amt = 23000.00

动作一回写完成,动作二开始回写,回写后的 a.code = '123456' 的 a.amt = 10000.00

这时,table a 中的 a.code = '123456' 的 a.amt 的最终余额变成了 10000.00 , 但实际上,正确的1余额应该是 a.code = '123456' 的 a.amt 的余额应该是 28000.00
即:第二次修改的动作初始值应该是 a.amt = 23000.00 , 两次正确修改后的值应该是 a.amt = a.amt+5000.00 = 23000.00 + 5000.00 = 28000.00

我所问的就是在 Sybase ASE 中,这个问题如何避免?

Oracle 可以有行级加锁,ASE 中是否有相同的手段来实现。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2008-09-06 17:09 |显示全部楼层
PS:不要钻牛角尖,我举的例子简单,只是为了说明问题,不代表说这个运算过程可以通过一句话来完成,也不代表说参与运算的数据仅仅从一个表中取得。

同时想说明的是,这是一个高并发环境下需要解决的问题,不是在非大量并发的情况下考虑。

论坛徽章:
0
发表于 2008-09-06 17:40 |显示全部楼层
[quote]原帖由 snow888 于 2008-9-6 17:09 发表
PS:不要钻牛角尖,我举的例子简单,只是为了说明问题,不代表说这个运算过程可以通过一句话来完成,也不代表说参与运算的数据仅仅从一个表中取得。
。。。。。。。。


回PS
这是所有RDBMS都面临的相同问题,不光是ASE,这都属于业务范畴,和锁粒度无关(这里这么说其实也不太妥当,但对这个业务可以这么说)!


这里所需要做的一件事情就是阻塞session 2读取到session a"可能"修改的数据。例如可以在选择之前(共享锁,对应update之前的运算而言)将对应数据行加上排他所,update table a set amt=amt+0 where ...

论坛徽章:
0
发表于 2008-09-06 18:32 |显示全部楼层
行级锁并不能解决楼主所说的,你现在是需要一条记录将要被处理时锁定这条记录不被读取,在sybase与oracle中都可以在读数据时采用
select * from a for update来解决这个问题。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2008-09-08 09:17 |显示全部楼层
原帖由 tyrone.dev 于 2008-9-6 18:32 发表
行级锁并不能解决楼主所说的,你现在是需要一条记录将要被处理时锁定这条记录不被读取,在sybase与oracle中都可以在读数据时采用
select * from a for update来解决这个问题。


sybase ase 中能使用 select * from a for update 这样处理吗?

我感觉只有 oracle 才具有这样的功能啊。

论坛徽章:
0
发表于 2008-09-08 17:30 |显示全部楼层
Chapter 23
Commands: select -  setuser
select
Description
Retrieves rows from database objects.
Syntax
select  ::=
     select   [ all | distinct ] select_list
     [into_clause ]
     [from_clause ]
     [where_clause ]
     [group_by_clause]
     [having_clause ]
     [order_by_clause ]
     [compute_clause ]
     [read_only_clause ]
     [isolation_clause ]
     [browse_clause ]
     [plan_clause ]
select_list ::=
For details on select_list, see the parameters description.
into_clause ::=
     into [[database.]owner.]table_name
     [  lock {datarows | datapages | allpages } ]
     [ with into_ option [, into_ option] ...]
      into_option ::=
           | max_rows_per_page = num_rows
           | exp_row_size = num_bytes
           | reservepagegap = num_pages           | identity_gap = gap
           [existing table table_name]
           [[external type] at "path_name"
          [column delimiter delimiter]]
from_clause ::=
     from table_reference [,table_reference]...
     table_reference ::=           table_view_name | ANSI_join
         table_view_name ::=
               [[database.]owner.] {{table_name | view_name}
               [as] [correlation_name]
               [index {index_name | table_name }]
               [parallel [degree_of_parallelism]]
               [prefetch size ][lru | mru]}
          [holdlock | noholdlock]
          [readpast]
           [shared]
          ANSI_join ::=
               table_reference join_type join table_reference join_conditions                    join_type
::= inner | left [outer] | right [outer]                      join_conditions ::= on search_conditions
where_clause ::=
     where search_conditions
group_by_clause ::=
     group by [all] aggregate_free_expression
          [, aggregate_free_expression]...
having_clause ::=
     having search_conditions
order_by_clause ::=
     order by sort_clause [, sort_clause]...
     sort_clause ::=
          { [[[database.]owner.]{table_name.|view_name.}]column_name
          | select_list_number
          | expression
}
          [asc | desc]
compute_clause ::=
     compute row_aggregate(column_name)
          [, row_aggregate(column_name)]...
     [by column_name [, column_name]...]
read_only_clause ::=
     for {read only | update [of column_name_list]}
isolation_clause ::=
     at isolation
          { read uncommitted | 0 }
          | { read committed | 1 }
          | { repeatable read | 2  }
          | { serializable | 3  }
browse_clause ::=
     for browse
plan_clause ::=
     plan "abstract plan"
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP