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