首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

数据库并发有关问题,CSDN无大神

2013-04-21 
数据库并发问题,CSDN无大神?求助个问题,流程如下事务开始:查询一最大值(数字)插入一条数据,同一字段值设置

数据库并发问题,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)
提交事务

[解决办法]
引用:
引用:
上面代码只是示意, 并没有严谨的写, 只表达意思。


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

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



要想不重复必然需要加锁,也就是牺牲效率,我想,不重复是功能需求,效率是性能需求,性能需要首先服从功能。
合并成一个语句并不能保证不重复(你的并发足够的情况下会出现重复)
自己加版本更不可行,自己写的效率不如内部的锁机制效率
遇到数据已经加锁只是等待,超时才会报错,大部分情况下并不引起失败,总比直接引起失败的方案好
[解决办法]
很简单啊,
你自己不都已经说了嘛,如果是C的话,你会用LOCK来控制,T-SQL当然也可以啊,
1,模拟C,自己建个全局临时表##TABLE2 ,或者用户表 ,专门用来做LOCK的锁定对象,
相当于LOCK(##TABLE2 ){}


2,通过一下方式就可以了,
Begin tran 
select count(*) from ##TABLE2 (XLOCK )

DECLARE @I INT 
Select @I=count(*)+1 from TABLEXXX  
INSERT INTO . VALUES (@I)

Commit tran
[解决办法]
整个中国、世界、宇宙也没大神。。无神论者言
[解决办法]
方法一:把产品名和版本号合起来作为主键(不知道你为什么不愿意这样做),其中一个Insert必定出错,提醒用户重做或者自动重做加1。

方法二:乐观锁定(一般与你这个过程正好相反,你这个太例外了,这时不能设置这两个字段为主键)
(1)增加一列,加上为t,数据类型为timestamp,就是时间戳,它会自动填写,不用你管,Insert或Update时它都会自动更新,也不用你管。
(2)Insert版本号为-1的
(3)Select @t=t From XXTable Where 产品名=A and 版本号=-1
这句就是取时间戳的值,即使插入了n条版本号为-1的也无所谓,取第一条就可以了。
(4)Update XXTable Set 版本号=3 where 产品名=A and 版本号=-1 and t=@t
这时已经完成了,如果要知道哪个用户执行的失败了,查最后一条更新语句影响的行数即可,为0的就是失败的那个用户。
[解决办法]
根本不是一个级别的东西,有什么可比的。

对于你这个问题
如果数据库在并发上的处理属于具体问题的话,  那么框架在这里就是相对宏观的。


[解决办法]
select max(a)+1 from b
[解决办法]
交给sql会自动处理
[解决办法]
1. 如果多个会话调用的是同一段语句的话,可以在select时加个updlock,这样就不会同时select到了

事务开始:
    --查询一最大值(数字)
    select max(ID) from table_name with(updlock)
    插入一条数据,同一字段值设置为(第一步最大值 + 1)
提交事务

2. 如果select来自不同的语句,那可以按上面的写法,update的同时取值,并且+1




[解决办法]
数据库并发有关问题,CSDN无大神都是高手啊 何必呢 一个事物就可以了 如果担心事物尽量短点的话 并发的几率不会太高 而且也不可能出现错误的 或者直接锁住哪一行也行啊
[解决办法]
select * from xxx for update,这个是上锁的;
[解决办法]
观摩大神解决方案
[解决办法]
数据库并发有关问题,CSDN无大神
[解决办法]
引用:
引用:
引用:
引用:
上面代码只是示意, 并没有严谨的写, 只表达意思。

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

你这一句代码,就已经确保数据不会重复了。因为两个线程同时执行到这句时,一个事务没有提交,另一个是改不动的,……

参照最后一句,“遇到数据已经加锁只是等待,超时才会报错,大部分情况下并不引起失败,总比直接引起失败的方案好 ”
自己增加版本或者使用时间戳,都会引起同时读取的另一线程的重新查询、重新插入,那样第一次查询就是浪费的了,总体效率在高并发情况下就是大问题

解决问题的方案不应该是越复杂越好

------解决方案--------------------


怕并发就上 设置隔离级别为串行化吧- -
一般不会有问题。
若你实在怕存在问题,就把所有插入做成SP 。都调用SP进行插入动作,在SP里做try catch + while。插入发生错误做重试,重试超过次数再条出报错就行了啊。

[解决办法]
应该根据实际的并发数和服务器能力做出对应的解决办法吧。
--mark
[解决办法]


[解决办法]
事务的特性:原子性(Atomicity),  一致性(Consistency),  隔离性(Isolation),  持久性(Durability).这些特性简称ACID

一致性和隔离性 就会保证lz说的情况不存在,你用脏数据计算后提交数据库会报错回滚事务。

当然,这个也取决与事务的级别。 lz如果有疑问可以去找些资料好好看看。 
[解决办法]
你这个明显是 transaction isolation的问题
用repeatable read或者serializable
4个transaction isolation level是ANSI/ISO标准制定的,和vendor无关。SQL Server默认是用locking来实现,Oracle则是row versioning。不管哪个都解决问题。

还有,SQL Sever也有Sequence object,不过需要2012版。


[解决办法]


数据库并发有关问题,CSDN无大神
数据库并发有关问题,CSDN无大神
把以上大神的方法整理一下,回头我也做个12306去卖票。

说来说去,不就是说的事务吗。事务有好几个级别,非要有需要把数据库级别设置高些。相应的效率会降低。

热点排行