咨询一个取最大值涉及到死锁的问题

searoom 2015-12-14 11:23:11
系统中,由于要取某个业务表中字段的最大值(字符字段),但又担心并发时产生重复值,我设计了一个表来保存最后取到的最大值,同时保存该取值的时间。 写了一个存储过程来取值,首先从该表中取的最大值和时间,如果是当前时间的5秒以前,则重新从业务表中取最大值,然后重新保存到该表中。这样就可以避免并发时取重复了。 现在出现一个严重的问题,由于这个取值的存储过程可能会处于某个事务中,造成该存储过程对最大值表的写入操作产生的锁会被延续导整个外部事务中。这是如果另外的并发如果也启动了一个事务来运行该存储过程,并且也需要写入最大值表,这时产生了阻塞(死锁) 系统这两天很容易卡死,用户都受不了了,我也快崩溃了!
...全文
135 点赞 收藏 11
写回复
11 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
等不到来世 2015-12-15
如果要保持单号的连续性,这种阻塞是没有办法的事,只有想办法把事务尽量简化; 如果只要保证不重复,不需要连续性,那就把sp提到事务外面来做。
回复
Tiger_Zhao 2015-12-15
1)字段上建索引,
2)取最大值的 SELECT 语句中加上 WITH(NOLOCK)。
就这么简单。
回复
唐诗三百首 2015-12-15
取某个业务表中字段的最大值(字符字段) --> 在该字段上建个倒序索引即可,这样取最大值"max([字段])"时速度最快, 无需另外建表,尽量不要把问题复杂化喔.
回复
薛定谔的DBA 2015-12-15
类似去每个客户的最大单据号问题吧,参考下:http://blog.csdn.net/kk185800961/article/details/45040489
回复
yooq_csdn 2015-12-15
取最大值的存储会同时运行多次?想解决这个?
回复
Yole 2015-12-15
取最大值更新最大值表的动作也只有在插入数据的时候进行。您这中间是不是还有什么其他得操作呢? 可以把事务拆开来写,插入的部分单独写进事务。
回复
等不到来世 2015-12-15
引用 7 楼 searoom 的回复:
[quote=引用 6 楼 szx1999 的回复:] 如果要保持单号的连续性,这种阻塞是没有办法的事,只有想办法把事务尽量简化; 如果只要保证不重复,不需要连续性,那就把sp提到事务外面来做。
不强求连续性了,只为了避免单号重复的问题。 如果只是简单取业务表最大值,然后+1再存储,如果没事务,只是简单地保存记录,有重复冲突的可能性确实比较低(偶尔有),但是,我需要在保存完后,还做些其他可能的处理,所以需要用事务把所有的处理包含进来,造成了如果事务时间较久,最大值重复的概率就增加了,所以想另外建个存储最大值的表,用来防止重复取到同一个最大值(如果短时间内已经有人取过,则直接在他取出的最大值后递增,不用再取业务表),结果,这个做法由于去存取这个表,造成了更严重的死锁![/quote] 之所以存取单号表造成死锁,是因为你把取号过程放到事务之中的缘故。建议你把取号过程抽出来放到事务之外。 比如,取号1+事务1,取号2+事务2. 这样一个并发,由于取号1本身是个小事务,很快能释放资源,所以不会阻塞取号2. 如果事务1失败了,号1直接丢弃。事务1和事务2都不涉及单号表,如果这两个事务还有死锁,那就不关取号的事情了。
回复
有几个办法。 你可以在找max的时候用更新锁,锁住最大值,这样你在处理就不会导致重复问题
回复
xdashewan 2015-12-15
“我需要在保存完后,还做些其他可能的处理”你的错误就在这里,你建立一张新表去维护最大值的做法是对的,这种做法是为了最小限度锁住一张数量量很小的表,使得锁住和释放的速度极快,至于你后面的处理那是另外一个事务,如果出错回滚无非就是丢弃一个业务编号。
回复
Tiger_Zhao 2015-12-15
WITH(NOLOCK)是最适合的。
根本不用维护一个最大值,只要直接脏读取最大值+1就行。
回复
searoom 2015-12-15
引用 6 楼 szx1999 的回复:
如果要保持单号的连续性,这种阻塞是没有办法的事,只有想办法把事务尽量简化; 如果只要保证不重复,不需要连续性,那就把sp提到事务外面来做。
不强求连续性了,只为了避免单号重复的问题。 如果只是简单取业务表最大值,然后+1再存储,如果没事务,只是简单地保存记录,有重复冲突的可能性确实比较低(偶尔有),但是,我需要在保存完后,还做些其他可能的处理,所以需要用事务把所有的处理包含进来,造成了如果事务时间较久,最大值重复的概率就增加了,所以想另外建个存储最大值的表,用来防止重复取到同一个最大值(如果短时间内已经有人取过,则直接在他取出的最大值后递增,不用再取业务表),结果,这个做法由于去存取这个表,造成了更严重的死锁!
回复
相关推荐
发帖
疑难问题
创建于2007-09-28

2.1w+

社区成员

MS-SQL Server 疑难问题
申请成为版主
帖子事件
创建了帖子
2015-12-14 11:23
社区公告
暂无公告