如何解决不同线程对同一个表的INSERT和UPDATE操作的死锁

07-02-06 blueravine
在ORACLE中遇到一个问题是有两个不同的线程(呵,其实不了解到底能不能称之为线程),一个是对一个表进行INSERT操作,另一个是对同一个表进行UPDATE操作,两个线程会同时进行,也就是INSERT与UPDATE同时对一个表进行操作,我该如何解决他们的死锁问题,很急的问题,请提供方法:)

litdong
2007-02-06 15:44
这种操作缺省是事物性的,都是独占锁,都会锁行或者锁表,你把问题描述清楚一点,在什么环境下写的库

[该贴被litdong于2007年02月06日 15:48修改过]

[该贴被litdong于2007年02月06日 15:50修改过]

wellsl
2007-02-06 16:20
对数据库的操作跟环境有关系吗

blueravine
2007-02-06 17:15
我们提供了2个公共方法分别做insert和update 他们被n个线程调用

其实想想,一个线程在做INSERT时,肯定是锁表的,那另一个线程跑到对同一个表UPDATE时肯定得不到控制权,但是不希望UPDATE总等着INSERT做完毕才开始执行,希望INSERT 和UPDATE能像时间片轮转一样不要总等着对方。

to litdong
不太明白你的意思,“在什么环境下写的库”?我们是用C#写的方法,分别对同一表进行INSERT 和 UPDATE,而这两个方法可能由不同线程调用

to wellsl
我想数据库应该只有ORACLE和SQL SERVER 等等不同工具的区别吧,我们用的是ORALCE

Coolyu0916
2007-02-07 17:27
ORACLE 的锁是行级别的
不会出现你说的情况
除非同时update同一条记录
同时的update由数据库负责,简单的update是不会死锁的

blueravine
2007-02-08 10:00
UPDATE有WHERE子句的话确实是行锁定,但这里的问题是INSERT与UPDATE的同时进行,INSERT是对表锁定的,在一个线程对表进行INSERT时,另一个线程对表UPDATE时,若此时表还被之前的INSERT锁住时,UPDATE就没办法进行

zdbj2ee
2007-02-08 12:49
注意一下表的修改须序,在不同的事务操作中保持对表有一定须序的访问.

trans1
start tx
update table1
insert table2
commit tx

trans2
start tx
delete table1
update table2
commit tx

注意这样才是正确的,不要一会在这个事务中的访问须序是table1然后table2,而在另一个事务中则先是table2然后再table1,这样特别易出现死锁.


blueravine
2007-02-09 10:37
我的情况是
trans1:
insert table1

trans2:
update table1

问题是对同一表的操作,trans1的INSERT操作可能还没做完, trans2就已经被调用

Coolyu0916
2007-02-09 14:00
如果insert的跟update的不是同一row的数据不会有任何问题
如果是同一数据,线程二需要重新写先select测试,然后再update

banq
2007-02-09 16:26
在J2EE中,依靠Hibernate或CMP之类提供的乐观锁+版本校验来实现性能更好select fo update等并发机制,参考相关资料。

chabulier
2007-02-09 19:27
注意事务中最好不要使用锁定(类似select for update);
否则粒度太大很容易出现lockwaitTimeOut

Coolyu0916
2007-02-09 23:34
乐观锁+版本校验并不一定比select for update更好
特别是比较大的系统,比如证券交易、银行系统
使用乐观锁很容易死锁或者出现长等待的问题
而且效率很低,如果只是小系统可以先让线程二sleep,然后notify()就可以了