1, 现在业务中有一个问题 是 从仓库中 去 捡货问题,是一个ERP系统去拣货的时候要去数据库去 货架是不是有这个商品呢,有就可以继续,否则抛异常大概意思是这样,本系统是strut2+spring开发的,由于一次捡货是15个 订单,前台自动选择15,struts2 action处理,调用业务逻辑去数据库 跑一圈 一般都要 30-60秒如果我要做成多用户同时可以 去拣货 <比如有一个人在捡15的时候,其他用户操作时如果再操作这15个就报错,或者说再去捡其他的没有 拣的订单>我的初步考虑是在strut2的action加同步锁,但是这样效率估计 不会高,请问大家有什么高见啊还有一个问题是 订单可能对应的仓库是不同商品,所以可以针对不同商品枷锁,是否效率高些呢?

解决方案 »

  1.   

    这个问题看起来比较复杂呀。比如两个用户A和B同时下订单,且A与B的订单中的商品编号有重叠,个人觉得对商品加锁好点。但是这样效率肯定会影响的。另外,我觉得这个应该在业务层去加锁吧。
      

  2.   

    是很复杂,其实15个订单包括的商品是有限的,下面的订单不一定有相同的产品,当然也可能重叠,重叠就要需要 枷锁了,貌似 这种情况下,效率不会很高,需要等待 ing
      

  3.   

    针对业务去枷锁 可能粒度小些,但是 还有n多 查询数据库的啊,对数据库操作啊, 但是貌似粒度还是很大,
    action枷锁是不可取的
      

  4.   

    给两个一拍脑袋想到的方案:
    1. 用行锁锁定你读取出来的记录
    select xxx, yyy, zz from tablea for update2. 在数据库里面增加一个捡货的状态,和捡货的时间,读取出来的时候给置上
    然后用quartz做一个线程,将超过一定时间还没有捡货的数据将其捡货状态设置成未捡货
      

  5.   

    1是肯定不行的.   除非这个表.不做其它的事..   
    2的话. 我刚刚也在想不过会加大操作数据库的次数.搞不好.时间会更久.可不可以加个static变量来存被操作的序号呢?   这样仅仅是做if而已.
      

  6.   

    给你一个建议可以不需要线程同步 不过对速度上还是有些影响不过很小很小.......条件 用户A开捡货 后用户B也来 C也过来捡货了在数据里多开一张表table 用来存放A B C在捡货的商品的标识 可以是编号只要唯一就可以......当A进来捡货前 先查询table 有没有关于自己要捡货的商品 没有就可以去捡货,并且把自己在捡货的商品存入到table中,有的话就提示用户该商品在被捡货中 稍等......当A捡货完毕,清除自己捡货的商品标识B来捡货的时候也是一样操作 不许要用同步商品或者对ACTION同步 太影响效率.......
      

  7.   


    最大限度影响速度的 可能就是 刚巧N个用户来捡货 所有的货物都被捡掉了 第N+1个用户来 查询 这次的查询是速度影响最大的...就相当于对原先货物的表来个select * 可是就一个标识的字段能有多慢呢
      

  8.   

    为什么要放内存.......根本就不需要啊 我只要 select * where 就可以 if(next()) 有必要放内存吗???
      

  9.   

    有一点你可能理解错了.   我只要存一个id进去就行了.    可以放个map之类的...     就是存成千上万个. 也就是几M大小. 怎么也比N个list 或者result小的,呵呵.      另外.map的查询速度.可是要比查数据库来的快哦.
      

  10.   

    N个用户也只用一个静态的变量.    而N个用户 查库就变成n个result  知道为什么这时候我选择牺牲内存了吧.
    当然..如果用户量非常少的时候.我这个方案就是垃圾方案了.   尴尬的说.嘿嘿
      

  11.   

    静态变量.我只用一个map  只是在map里面存了N条数据..   还是比查库快的.   不用的时候.remove掉就行了.
      

  12.   

    你不明白 对单个用户来说 每个用户都有一个SESSION ....相对单个用户的操作速度都是一样的....而你要用跨线程通知......就会用到上下文的内存空间.....这个就是影响着整个系统的速度 .....也就是说 用户越多 你这个速度就会越慢......
      

  13.   

    我遇到跟lz类似的问题,我是这么解决的:
    1.创建一个表,用于记录用户选择的数据。假设为表X
    2.用户查询数据时,要过滤掉在表X中的数据。
    3.用户在选择确认数据时,都要判断该数据是否在表X中。如存在则不允许选择。
    4.用户选择后,需要将选择的记录写入表X中。
    5.用户选择后如放弃(或者关闭当前窗口),需要在关闭事件中处理,删除表X中相应的记录。
    6.由于异常,断电等情况,无法保证表X没有垃圾,因此还可能需要定时清理。
      

  14.   

    static还真的是不行.刚刚有测试过.   根本是在 吃内存.     存储过程、锁表。  高人能否说下..另外.锁表的时候.其它查询真的没问题吗?
      

  15.   


    A在捡货过程中table 表中A在捡货的商品存在 这个时候B也要捡这个商品就会被告知这个商品在捡货中 稍等.....可以让他等待1分钟再次尝试......这个取决你A用户的执行效率....当A执行完毕后会删除表中A捡货的商品不至于 会跟别的用户起冲突....
      

  16.   


    存储过程保证事务,锁表保证对表的访问(or 行级锁时,相关行的访问)是线性的,相当于你的java的sync。
      

  17.   

    问题还需要  有进一步的idea
      

  18.   

    如果这种情况经常发生的话,那应该使用悲观锁,悲观锁需要数据库的支持,比如 oracle 的 for select,SQLServer 的 with(ROWLOCK) 等。如果这种情况只是偶尔会发生,那应该使用乐观锁,在数据表中加一个额外的版本号字段。
      

  19.   

    这里有个关于乐观锁、悲观锁的帖子,有兴趣的话可以去看一下:http://topic.csdn.net/u/20100429/11/ee45610b-d18d-4451-8e78-567899e4232d.html大多数的 ORM 工具都支持乐观锁,比如 JPA 的 @Version
      

  20.   

    ibatis 貌似不支持悲观锁啊
    在sqlmap写select for update也不知道 支持不 明天 测试下 
      

  21.   

    ibatis 貌似不支持悲观锁啊
    各位 有 遇到 这个问题的 说说啊 谢谢先。
      

  22.   

    POJOs in Action 上有介绍。这本书非常好,如果想了解在企业级应用中处理数据库的问题,这本书是首选。CSDN 读书频道上有部分章节,跟“锁”相关的地址:http://book.csdn.net/bookfiles/367/10036714018.shtml
      

  23.   

    http://topic.csdn.net/u/20100527/11/ba5bdac5-0244-4e10-90a5-2d85e798d48d.html?seed=219327445&r=65757501#r_65757501谁帮忙回一条, 没有创小号号,谢谢啦一个用户只允许连续回复3次。
      

  24.   

    将这段逻辑用Locked 不就行了,在同一时刻,只允许一个用户去检证,也可以用线程中的同步方法来实现。
      

  25.   

    我前几天遇到的数据库并发取记录的问题,感觉与你这个需求很相似
    内容太长,贴个链接,楼主自己去看看,希望能解决你的问题如何并发每次取前100条不同记录:
    http://blog.csdn.net/zhaohuihua/archive/2010/05/24/5619076.aspx具体到你这个问题,为避免出现:
    订单被某用户拣了却没有处理,则该订单将永远无法被其他用户处理了
    标志字段应设置为时间类型,如[HandleTime]
    假定10分钟超时,则取记录只取[HandleTime]在10分钟以前的记录
    用户提交订单,应判断[HandleTime]在10分钟以内,否则提示超时失败
      

  26.   

    对了,《如何并发每次取前100条不同记录》的实现是依赖于Oracle数据库的
    而且,不能按先后顺序取记录,只是保证每次取的记录不同
      

  27.   

    首先,检货过程时间太长,说明,数据库结构还存在优化余地。尝试分表处理,或者优化查询字段(比如,只含数字的字段,不采用char型数据进行存储;创建索引;等等)。
    其次,若实现报错功能,可在相关记录的表中,添加检货状态字段。通过该字段进行校验报错。只针对记录加锁,貌似无法实现报错功能。
    第三,如果整个检货过程所形成的数据库事物的隔离级别很高的话,坚决赞同使用悲观锁。
    第四,由于数据库查询耗时很长,所以,通常要想办法限定同时检货的人数。同时检货的人越多,大家等待的时间会指数倍的增加,而且还会影响其他也没的访问。
    第五,一般不考虑在Struts2的Action上面添加同步锁,绝大多数问题,都能在数据库层,逻辑层解决。以上意见仅供参考。