Oracle中利用SELECT的FOR UPDATE子句实现给记录加锁conn system/manager--创建实验用户 grant connect,resource to test identified by test;conn test/test--创建实验表1 create table a(a number); insert into a values(1); commit;select * from a for update; 或 select * from a for update of a.a;(a表的a列)--新打开一个SQL*Plus窗口 conn test/test(test用户上的第二个会话) delete from a;此时,系统停顿状态,等待解锁, 只要在第一个窗口发出roll;或commit;命令,即可解除锁定状态。
-------------------------------------------------------------------------
在网络上,无法确保没有第二个人执行同样的操作,第一个人的操作出错啊。我也想给数据库加锁,确保第一个人操作成功,第二个人在操作前就提示错误。 问题是锁该怎么加????
-------------------------------------------------------------------------
引用:修改->请求->计时->超时重发->N次提示出错
-------------------------------------------------------------------------
在数据fill进dataset后,在updata之前,如果有另一个进程修改数据,那么updata一定不成功。 重试100次,结果仍然是不成功啊
-------------------------------------------------------------------------谢谢大家的关注,希望能有解决的办法。 等。。
2、修改->请求->计时->超时重发->N次提示出错
-------------------------------------------------------------------------
在数据fill进dataset后,在updata之前,如果有另一个进程修改数据,那么updata一定不成功。 重试100次,结果仍然是不成功啊
-------------------------------------------------------------------------
这个是在加锁的前提下,如果有进程操作就要上锁的
方法2:建立一个表identity,set autocommit off,该表有两个字段,第一个字段表示当前能得到的最大的可用id,第二个字段为表名。
每次想向表中插入记录时从identity表中得到id(select);将identity表id+1(update);commit;
然后用得到的id插入你想要插的表
grant connect,resource to test identified by test;conn test/test--创建实验表1
create table a(a number);
insert into a values(1);
commit;select * from a for update;
或
select * from a for update of a.a;(a表的a列)--新打开一个SQL*Plus窗口
conn test/test(test用户上的第二个会话)
delete from a;此时,系统停顿状态,等待解锁,
只要在第一个窗口发出roll;或commit;命令,即可解除锁定状态。
http://www.chinaitlab.com/www/news/article_show.asp?id=6123
1、把对dataset比较耗时间的操作放在事务之外;
2、设计数据库表的关键字段(可以为自增一;或自定义一个存储过程之类的在修改dataset时就先把字段值存入数据库中,防止多人抢号);
3、最后以事务提交dataset,失败了不必重置dataset,多提交几次就成。
1、如果最终本问题无解,我会使用ExecuteNonQuery()方法来解决。2、设计数据库表关键字段的方法,感觉不是百分之百的安全。 如果一个进程在锁定记录后,进程出现异常关闭(机率小,但是很难杜绝),则又是一个麻烦事。3、不必重置dataset,多提交几次就成。 我已经试过了,如果在fill和updata之间,数据库被改变了,则不管updata多少次,结果都是一定不成功
谢谢大家的关注,继续研究这个问题。 希望能有解,毕竟,用dataset来updata,比用一大堆ExecuteNonQuery()要直观一些,用起来也要爽一些。现在并未实际做程序,只是先对操作数据库的各种方法,做一个比较全面的了解。谢谢大家了
cm.CommandText="select * from aTable";
cm.Transaction=trans;
OleDbDataAdapter ad=new OleDbDataAdapter(cm);
OleDbCommandBuilder builder = new OleDbCommandBuilder(ad);
DataSet ds=new DataSet();修改后的代码:
OleDbCommand cm=conn.CreateCommand();
cm.Transaction=trans;
try
{
cm.CommandText="update aTable set f3=f3"; //一个不影响数据库数据的updata操作
cm.ExecuteNonQuery();
}
catch(Exception ee)
{
trans.Rollback();
cm.Dispose();
conn.Dispose();
return;
}
cm.CommandText="select * from aTable";
OleDbDataAdapter ad=new OleDbDataAdapter(cm);
OleDbCommandBuilder builder = new OleDbCommandBuilder(ad);
DataSet ds=new DataSet();这种方法,多了一个对表的ExecuteNonQuery()操作,效率上应该不会有太大的影响。但是,在多进程情况下,应该可以确保安全。以上代码,已经测试通过。问一下DX们,这种解决方式如何??? 有没有缺陷或不合理的地方?????谢谢
1、A读取完数据,并在dataset中做修改操作
2、B在A进行修改的时候,申修改A正在dataset中作修改操作的数据。由于A未加锁,申请成功,并修改
3、A用户通过adapter将dataset的数据回写到数据库中的时候,报错。在这种情况下,必须做异常处理,也就是说要把数据修改重新做一次。
4、在A处理异常,重新作修改的时候,在极端情况下有可能用户B再次修改数据,则再次回到第3步。如果A用户锁定记录,执行效果如下:
1、A读取完数据,并在dataset中做修改操作
2、B在A进行修改的时候,申修改A正在dataset中作修改操作的数据。由于A加锁,则B自动进行等待
3、A通过adapter将dataset的数据回写到数据库,成功。 并同时解除锁定
4、B在A解除锁定后(等2秒),自动完成了修改操作。整个执行过程中,没有异常情况二: A用户修改数据要花费10分钟如果A用户不锁定记录,执行效果如下:
1、A读取完数据,并在dataset中做修改操作
2、B在A进行修改的时候,申修改A正在dataset中作修改操作的数据。由于A未加锁,申请成功,并修改
3、A用户通过adapter将dataset的数据回写到数据库中的时候,报错。在这种情况下,A花费10分钟做的工作,已经报废了。如果让A用户重新作这个花费10分钟的操作,A用户只能骂人如果A用户锁定记录,执行效果如下:
1、A读取完数据,并在dataset中做修改操作
2、B在A进行修改的时候,申修改A正在dataset中作修改操作的数据。由于A加锁,则B自动进行等待
3、由于A锁定时间太长,B用户等待超时,报错(通知B用户有人正在对数据库做全盘调整,请稍后再试)
4、10分钟后,A用户通过adapter将dataset的数据回写到数据库中的时候,成功
5、10分钟后,B用户再次申请修改数据,成功(注:B用户可能会在10分钟以内做多次尝试)回蜀人:
为个问题,还没有做个实验,可以探讨一下
假设修改10000条记录。
方法一:执行10000次updatacommand操作,完成修改
方法二:将10000条记录,查询入dataset,修改完成后,再一次性updata写回数据库两种方法,哪种效率更高???? 在效率上会不会有N倍以上的差异????