怎么再Oracle中进行读锁(一)
写这个题目是由于看到论坛里面的一个帖子:http://www.itpub.net/thread-992141-1-1.html。
虽然不清楚楼主的具体目的是什么,但是楼主提出的问题确实有点意思。因为Oracle中根本没有读锁,楼主的要求和Oracle尽可能提高并发的目的是截然相反的。
写这篇文章的目的并不是说这个需求有什么普遍性,而是为了说明在Oracle中其实没有什么是做不到的,即使这个需求和Oracle的设计本意相违背,另外希望这篇文章中的一些思路能起到抛砖引玉的作用。
楼主提出的问题是“怎么样让一个表,一个时间只能一个人读”,简单概括一下就是建立起读锁的机制。而且这个读锁还不能是共享锁,而必须是有个独占锁。
考虑到Oracle中根本不存在读锁,那么必须将思路进行转化。
最先想到的是,将查询转化为DML,这样就可以获取到锁,避免其他用户对改对象同时进行访问。
最简单的实现方式莫过于建立一个存储过程,在存储过程中首先LOCK TABLE,然后进行查询,将查询的结果返回。
简单实现如下:
SQLCREATETABLET 2( 3IDNUMBERPRIMARYKEY, 4NAMEVARCHAR2(30) 5);
表已创建。
SQL INSERT INTO T SELECT ROWNUM, TNAME FROM TAB;
已创建23行。
SQL COMMIT;
提交完成。
下面构建函数:
SQLCREATEORREPLACEFUNCTIONF_QUERY_TRETURNSYS_REFCURSORAS 2V_CURSORSYS_REFCURSOR; 3BEGIN 4LOCKTABLETINEXCLUSIVEMODE; 5OPENV_CURSORFOR‘SELECT*FROMT‘; 6RETURNV_CURSOR; 7END; 8/
函数已创建。
SQLSELECTF_QUERY_TFROMDUAL; F_QUERY_T -------------------- CURSORSTATEMENT:1 CURSORSTATEMENT:1 IDNAME ---------------------------------------- 1CHAINED_ROWS 2DEPT 3EMP 4BONUS 5SALGRADE 6DUMMY 7T_PK 8S_T 9MV_CAPABILITIES_TABLE 10TB_OBJECT_1136 11MLOG$_TB_OBJECT_1136 12RUPD$_TB_OBJECT_1136 13MV_TB_OBJECT_1136 14ORD_ORDER 15TT 16MV_T 17T_PRIMARY 18T_UPDATE 19T 20INF_PRODUCT 21INF_DRUG 22T_OLD 23INF_PRODUCT_PROPERTY
下面在另外一个会话登陆,仍然通过函数来访问:
SQLSETSQLP‘SQL2‘ SQL2SELECTF_QUERY_TFROMDUAL;
会话被锁定,只有会话1提交或回滚,会话2才能继续查询:
SQL COMMIT;
提交完成。
这时会话2解锁:
F_QUERY_T -------------------- CURSORSTATEMENT:1 CURSORSTATEMENT:1 IDNAME ---------------------------------------- 1CHAINED_ROWS 2DEPT 3EMP 4BONUS 5SALGRADE 6DUMMY 7T_PK 8S_T 9MV_CAPABILITIES_TABLE 10TB_OBJECT_1136 11MLOG$_TB_OBJECT_1136 12RUPD$_TB_OBJECT_1136 13MV_TB_OBJECT_1136 14ORD_ORDER 15TT 16MV_T 17T_PRIMARY 18T_UPDATE 19T 20INF_PRODUCT 21INF_DRUG 22T_OLD 23INF_PRODUCT_PROPERTY
SQL2 ROLLBACK;
回退已完成。
通过这种方法,简单的实现了读锁的功能,不过这种方法的缺点也很明显,要求用户必须通过函数的方式访问,而直接通过SQL方式访问是可以绕过锁机制的。
| 广告合作:400-664-0084 全国热线:400-664-0084 Copyright 2010 - 2017 www.my8848.com 珠峰网 粤ICP备15066211号 珠峰网 版权所有 All Rights Reserved
|