UPDATE GJZB SET KEYWORD=(SELECT LPAD(TO_CHAR(To_NUMBER(KEYWORD)+1),KEYLONG,'0') FROM GJZB WHERE UPPER(TABLENAME)=UPPER(STR_TABLENAME)) WHERE UPPER(TABLENAME)=UPPER(STR_TABLENAME);
UPDATE GJZB SET KEYWORD=(SELECT LPAD(TO_CHAR(To_NUMBER(KEYWORD)+1),KEYLONG,'0') FROM GJZB WHERE UPPER(TABLENAME)=UPPER(STR_TABLENAME)) AND UPPER(TABLENAME)=UPPER(STR_TABLENAME);问题不在这儿,而是表GJZB的tab_rsda_jcxx这一行被锁住,用其他的数据库操作软件都不能进行update这一行的数据了,但其他行可以!
SELECT KEYWORD,KEYLONG INTO STR_OLDKEY,KEYLENGTH FROM GJZB WHERE UPPER(TABLENAME)=UPPER(STR_TABLENAME) for update;
to: leecooper0918(帮助别人,其实也是在帮助自己)请教一下,对于我这个存储过程,应该加什么进行防止并发情况的出现?谢谢了!
SELECT KEYWORD,KEYLONG INTO STR_OLDKEY,KEYLENGTH FROM GJZB WHERE UPPER(TABLENAME)=UPPER(STR_TABLENAME) for update; ... ... ... commit;-------------------------------- 这样就自动枷锁自动解锁了,当然如果出现异常,建议通过dbms_transaction包做事务处理; dbms_transaction.savepoint; dbms_transaction.commit; dbms_transaction.rollback;
select * from tablename for update;//for update 是行级加锁lock table tablename in exclusive MODE;//lock 是表级加锁,in exclusive mode表明加锁机制是独占方式
你的功能无非是通过参数表取得流水号,首先一个语法就是取得该参数值并对其所在行加锁,那么 select xxx in v_xxx from tablename for update; 就是这个意思。然后你就可以根据你所取得的值进行其他操作,操作全部完成后就可以commit;提交之后,oracle会自动地对您所加锁的对象解锁。------------- 至于dbms_transaction包,主要是在单独处理存储过程中使用,如果你本身是通过程序调用的,那么只要在你的储存调用过程中使用事务处理即可。
看来你还不太了解oracle 的锁定机制 ... 并发操作时,存储过程中必须加行锁,操作完成后尽快提交事务。
...
...
...
commit;--------------------------------
这样就自动枷锁自动解锁了,当然如果出现异常,建议通过dbms_transaction包做事务处理;
dbms_transaction.savepoint;
dbms_transaction.commit;
dbms_transaction.rollback;
问题不在这儿,而是表GJZB的tab_rsda_jcxx这一行被锁住,用其他的数据库操作软件都不能进行update这一行的数据了,但其他行可以!
--------------------------------------
这就是oracle的锁定机制,以防止多个会话同时修改表中的同一行。 基本概念:
修改操作时,Oracle 引发行锁定, 它不会升级为块锁定,表锁定; 不会为了读取数据而使用锁定, 简单的读操作不会引发行锁定 ;
数据写不会阻碍数据读。让我再重复一次: 数据读不会被数据写
阻碍。在这点上Oracle 与其他大多数数据库存在根本差异;
只有在数据行已经被其他写操作锁定时,才会阻碍另一个数据写
操作。
你的意思就是在我根据参数tablename读取keyword时的sql语句后加:FOR UPDATE即可以实现自动加锁和自动解锁?请详细说明一下,俺对oracle还处于不是很了解的状态,谢谢~~
dbms_transaction.savepoint;
dbms_transaction.commit;
dbms_transaction.rollback;
上面这三行可以直接加到我的存储过程中去吗?
select xxx in v_xxx from tablename for update;
就是这个意思。然后你就可以根据你所取得的值进行其他操作,操作全部完成后就可以commit;提交之后,oracle会自动地对您所加锁的对象解锁。-------------
至于dbms_transaction包,主要是在单独处理存储过程中使用,如果你本身是通过程序调用的,那么只要在你的储存调用过程中使用事务处理即可。