update config t set t.value =1 where t.key='DB_ KEY'

select * from config t where t.key='DB_KEY' for update

这个update会试图为where条件指定的那些数据加上行级锁,但如果此时这些数据已经被其他事务加锁了,则会一直等待,直到锁被释放,然后再去竞争这些数据的锁。

问题是,我不想让它一直等待,如果加不上锁就立即返回失败信息。对于select ... for update语句,可以用如下方式:

select ... for update nowait (加锁失败则立即报错)

select ... for update wait 3 (最多等待3秒)

但仅限于select ... for update语句,update语句没有这个功能。而且,这是Oracle数据库所特有的功能。

我在设计多服务器、多线程数据库同步操作时,最开始是采用的如下方式:

// 如果更新成功了,则i=1,否则i=0

int i = "update config t set t.flag =1 where t.key='DB_KEY' and t.flag=0" ;

// 当i=1时才允许去做查询和更新数据

if (i== 1 ) do query & update DATA;

// 查询完之后将DB_KEY的flag改回原来的值

update config t set t.flag = 0 where t.key= 'DB_KEY' and t.flag= 1

从中可见,t.key='DB_KEY'这条数据就好似一把锁,谁成功的将flag置为1就意味着谁打开了这把锁,只有打开了锁才能操作真正的数据,避免了多服务器、多线程查询出同样的数据。

但是啊, 上面的方法有个致命的缺点:如果一个线程将锁打开了,而因为意外死亡(停机、重启等原因)未能将锁锁上,那么这意味着什么?意味着这把锁永远处于打开状态,其他线程都没有机会再次获取它了 。所以我想到了利用事务来控制,起初开启事务,然后再update KEY,如果成功了,再query & update DATA,然后再update KEY归还钥匙。 如果线程意外停止了,那么未提交的事务会立即回滚,锁回归未使用状态

我是这样做的,设置事务的超时时间:开启事务——update——doSomething比如query——关闭事务。 事务超时时间设置为5秒 。如果update等待超过这个时间,则会抛出异常,报错终止。

为什么要设置一个超时时间呢,因为完整的这一套事务控制需要一定时间,比如4秒,如果DB_KEY已经被加锁,则其他update KEY将会处于等待状态,等待多久,这个时间是不可控的,所以我想要自己来控制这个等待的timeout时间。

但是我测试时发现的是,超时后,update处没有报错,后面的query依然执行,query时才报错(事务超时异常)。这是个比较难看透的问题,我想了很久才想通,原因是update时可能已经等待了4.99秒,然后update成功了,接着执行query,但是此时时间已经超过5秒了,所以query报事务超时异常(正所谓,好不容易等到update成功了,但是却没有足够的时间留给后面的query)。因此,update和query的时间差不能太大,否则的话有可能update成功了而query失败(从设计上讲,我不太希望有这种情况出现,当然,即使出现了,也只是浪费了一次事务罢了)。

分析清楚了这个问题之后,现在有两种合理的设计方案:

1)不用事务,直接走update KEY——query & update DATA——update KEY路线,但是在update KEY时要 记录update date,并启动一个线程循环不断的去检查KEY是否处于flag=1且now - update date > 30秒的状态,如果处于这种状态 ,则占用KEY的时间过长,因而断定获取KEY的那个线程出现了异常,没有能力将KEY还原,此时这个Check线程就帮忙把KEY重置为未使用状态。

2)使用事务,为update KEY——query & update DATA——update KEY期间加上事务控制,如果线程挂掉,则事务回滚。也可以设置一个超时时间,但是有可能会因为timeout限制而误杀正常的流程。因此超时时间不能太短——越短,误杀正常流程的几率越大。

用了VPN上网,Maven报错如下:Connection to http://107.2.10.22:8081 refused: Connection timed out: connect最终查到原因是由于,VPN做了权限限制,只允许HTTP协议,导致ping不通,Maven也连接超时。将VPN权限放开,设置为允许 HTTP、ICMP、UDP等协议就行了。...
找到% ORACLE _HOME%/network/admin/sqlnet.ora文件 最后一样 添加参数SQLNET.EXPIRE_TIME = 2 但为是分钟 默认不要 设置 的太大 容易引起 session过多 添加后重启 oracle 服务 转载于:https://www.cnblogs.com/liaomin416100569/a...
一、 update 表吗? 1.不带索引 运行命令:begin;开启 事务 ,然后运行命令: update tb_user set phone=11 where name=”c1”;修改,先别commit 事务 。 再开一个窗口,直接运行命令: update tb_user set phone=22 where name=”c2”;会发现命令卡住了,但是当前面一个 事务 通过commit提交了,命令就会正常运行结
因为 oracle 执行更新、插入操作都是需要提交 事务 (commit)的,而非正常的中断会话会导致 oracle 定该条进程:解决办法: 首先查询确定哪些进程被 定:  SELECT vs.sid, vs.serial#   FROM v$locked_object vlo, dba_objects do, v$session vs   WHERE do.object_id = vlo.obje
alter table project add project_grade number(2); ORA-04021:等待 定对象时发生 超时 select * from dba_ddl_locks where name= 'PROJECT'; alter system kill session 'sid,serial#'; 如果session无法kill,则kill