日期:2014-05-17  浏览次数:20708 次

数据库并发问题,CSDN无大神?
求助个问题,流程如下
事务开始:
    查询一最大值(数字)
    插入一条数据,同一字段值设置为(第一步最大值 + 1)
提交事务
_____________________________
这会有个线程同步问题,比如线程1,2同时查到最大值为10,则可能同时 INSERT 11
而我不能把字段配置成“unique", 因为业务的原因
求助诸位,先谢谢
C语言我知道可以弄LOCK锁函数,但是我想以数据库的方式,不知道有没有解决办法。比如,有没有办法让事务一开始,自动锁定,其他线程进入事务只能等待

如果描述不清,我还是举例算了,表有 产品和 版本两字段
产品,版本
——————————————————————
产品A,1
产品A,2
产品XX,1
产品YY,1
产品YY,2
产品YY,3

如果两个事务同时查到产品A的最大版本2,则同时INSERT (产品A,3)明显就有问题。

(如果你想回答“弄成一个语句,类似insert into xxx values (select max ....)" 就算了,我不需要这样的答案)
insert 数据库 SQL 同步 并发

------解决方案--------------------
查完即update +1
即先update 再insert
用提交读。

如果可以降低并发性能可以应用更高的隔离级别,如可重复读。


个见。
------解决方案--------------------
我假定:

ta
id  tb_name max_n
1   tb       23
2   tc       55

tb
id  ....

你从ta表中读取tb对应的max_n  然后插入记录到tb ,max_n +1 作为新记录的 id





那么

begin tran

declare @id int 
update ta set max_n=max_n + 1 where tb_name = 'tb'
select @id = max_n from ta
if @error....
   commit tran

insert tb ...

如果插入不成功, 在这个进程下max_n +1 的结果(对tb表来说)将被丢弃, 从而行成断号。


如果你的表是这样的设计的话 ta表的记录是非常少的,那么update的操作速度将非常快, 在解决你所说的问题的同时并有效的提高并发量。
------解决方案--------------------
上面代码只是示意, 并没有严谨的写, 只表达意思。
------解决方案--------------------
我的习惯是,先select出最大值,再加1,再insert。为了防止重复,用主键或是唯一索引。这样,如果重复了,数据库会返回错误。
------解决方案--------------------
用事务的话,在当前事务没有提交的情况下,表不能做其他更新操作的吧.事务就是防止并发产生脏数据。所以产生你说的那个情况,不过相应的效率就降低了
------解决方案--------------------
引用:
引用:上面代码只是示意, 并没有严谨的写, 只表达意思。

update ta set max_n=max_n + 1 where tb_name = 'tb'

你这一句代码,就已经确保数据不会重复了。因为两个线程同时执行到这句时,一个事务没有提交,另一个是改不动的,会等待前一个事务提交后,才能执行。  
但是我并不需要这样的答……


呵呵, 最后一句肯定是看到了的。
本质的区别很大的。

不想重复,又不想等待(哪怕是理论上微秒纳秒级的), 你的要求无解。
------解决方案--------------------
1, 既然你自己都说了,另一个进程失败了, 那何谈并发。
2,不要用max
------解决方案--------------------
我觉得insert into xx(..., Num) values (..., select max(..))这个方案就不错
不过多并发环境的话可能效率就低了点
------解决方案--------------------
流程如下修改就可以了


事务开始:
    查询一最大值(数字),同时加排它锁
    插入一条数据,同一字段值设置为(第一步最大值 + 1)
提交事务

------解决方案--------------------
引用:
引用:
上面代码只是示意, 并没有严谨的写, 只表达意思。