我申请这个blog是为了督促自己,把自己平时的一些想法和思考结果保留下来。 本博客所有内容均为原创,如有转载请注明作者和出处

在Oracle中如何实现读锁(一)

上一篇 / 下一篇  2008-05-26 23:58:27 / 个人分类:ORACLE

写这个题目是由于看到论坛里面的一个帖子:http://www.itpub.net/thread-992141-1-1.html

虽然不清楚楼主的具体目的是什么,但是楼主提出的问题确实有点意思。因为Oracle中根本没有读锁,楼主的要求和Oracle尽可能提高并发的目的是截然相反的。

写这篇文章的目的并不是说这个需求有什么普遍性,而是为了说明在Oracle中其实没有什么是做不到的,即使这个需求和Oracle的设计本意相违背,另外希望这篇文章中的一些思路能起到抛砖引玉的作用。

 

 

楼主提出的问题是“怎么样让一个表,一个时间只能一个人读”,简单概括一下就是建立起读锁的机制。而且这个读锁还不能是共享锁,而必须是有个独占锁。

考虑到Oracle中根本不存在读锁,那么必须将思路进行转化。

最先想到的是,将查询转化为DML,这样就可以获取到锁,避免其他用户对改对象同时进行访问。

最简单的实现方式莫过于建立一个存储过程,在存储过程中首先LOCK TABLE,然后进行查询,将查询的结果返回。

简单实现如下:

SQL> CREATE TABLE TITPUB个人空间9ms,D rv4r2D
  2  (
2_HP&jN1qj0  3   ID NUMBER PRIMARY KEY,
#ks~s K7I'Y0  4   NAME VARCHAR2(30)
:`kr6s9Z$W,a D0  5  );

表已创建。

SQL> INSERT INTO T SELECT ROWNUM, TNAME FROM TAB;

已创建23行。

SQL> COMMIT;

提交完成。

下面构建函数:

SQL> CREATE OR REPLACE FUNCTION F_QUERY_T RETURN SYS_REFCURSOR ASITPUB个人空间j#S:X Y GMMn"\
  2   V_CURSOR SYS_REFCURSOR;
P0~qp"Y.M8?%oTN0  3  BEGINITPUB个人空间4Ug-L0J}3g-^
  4   LOCK TABLE T IN EXCLUSIVE MODE;ITPUB个人空间 i{Ui8t#IF9|~
  5   OPEN V_CURSOR FOR 'SELECT * FROM T';
;XP |(JR VP2\)Q)QWB0  6   RETURN V_CURSOR;ITPUB个人空间]Q:IOF#A%[;y
  7  END;ITPUB个人空间6N5Pm7V&ODKNd
  8  /

函数已创建。

SQL> SELECT F_QUERY_T FROM DUAL;

F_QUERY_T
J)f-Nl+a`/j.wG1z0--------------------ITPUB个人空间`s;@.C hB;t9Z*Y}-W.T
CURSOR STATEMENT : 1

CURSOR STATEMENT : 1

        ID NAME
5d&Yx EfUb-IO!J0---------- ------------------------------
$cg|.`k$BG7{#]0         1 CHAINED_ROWSITPUB个人空间-k}6Rb t Lbf
         2 DEPTITPUB个人空间(C@rb5kl
         3 EMPITPUB个人空间!P](f*U+Av Z,U_`
         4 BONUSITPUB个人空间5vP7Ya b#a){n g
         5 SALGRADE
8C W.| khD0         6 DUMMY
{JMLp4` rT6k0         7 T_PKITPUB个人空间4l+T~2dv&J3U.E
         8 S_T
x g~9_2l)K`,KX0         9 MV_CAPABILITIES_TABLEITPUB个人空间R0l*}'QQ0WcJD2f
        10 TB_OBJECT_1136
E*`#C:|y1uF0        11 MLOG$_TB_OBJECT_1136
-N&jTs:go%m%ta2c0        12 RUPD$_TB_OBJECT_1136ITPUB个人空间bn4m lY
        13 MV_TB_OBJECT_1136ITPUB个人空间#XS)b^t%{_rP
        14 ORD_ORDER
O;t$~[`{H3R0        15 TT
!XZU/uV#aN/p9`K0        16 MV_T
a$`:D#@:@lPw0        17 T_PRIMARY
:FXcnc]Kj+q0        18 T_UPDATEITPUB个人空间vd!Wz6S([#lgB
        19 TITPUB个人空间;T+C3af5_!?8A"^
        20 INF_PRODUCTITPUB个人空间*}NnW O iO
        21 INF_DRUG
b;`s R(U8H5U!r+B0        22 T_OLDITPUB个人空间;OFn0fk
        23 INF_PRODUCT_PROPERTY

已选择23行。

下面在另外一个会话登陆,仍然通过函数来访问:

SQL> SET SQLP 'SQL2> '
m.C Fg:G e_0g7J0SQL2> SELECT F_QUERY_T FROM DUAL;

会话被锁定,只有会话1提交或回滚,会话2才能继续查询:

SQL> COMMIT;

提交完成。

这时会话2解锁:


,t{2a ~6i(f7a6Z ]\0F_QUERY_TITPUB个人空间kKD!Bf+_dHr
--------------------
7Bo;~$Wm)H _~f0CURSOR STATEMENT : 1

CURSOR STATEMENT : 1

        ID NAMEITPUB个人空间O~6hox'D!G P-W h3l
---------- ------------------------------ITPUB个人空间hG\ g%O}a4jh
         1 CHAINED_ROWSITPUB个人空间w0Z3^OE5?
         2 DEPTITPUB个人空间-aU?*]ax\ z'z
         3 EMPITPUB个人空间 l XY4|`a
         4 BONUSITPUB个人空间s-v9SS.| ~
         5 SALGRADEITPUB个人空间%F;M1naK
         6 DUMMYITPUB个人空间CWAc"rr7^/o
         7 T_PKITPUB个人空间'R"ZL7I:N&e6W w'X1Rv;K
         8 S_TITPUB个人空间,rGP7}e|iw
         9 MV_CAPABILITIES_TABLE
(U-iDQO0j#s0        10 TB_OBJECT_1136ITPUB个人空间6r C[\@t.y-Q
        11 MLOG$_TB_OBJECT_1136ITPUB个人空间&Li XU [6O'H }
        12 RUPD$_TB_OBJECT_1136ITPUB个人空间5XUJ!i+uo*]Y1zYgD
        13 MV_TB_OBJECT_1136ITPUB个人空间S+K-Mx2HO1~
        14 ORD_ORDER
;k&jt'XBE v,q0        15 TT
[(S7kq3I{0        16 MV_T
v Pe+|+c'U0        17 T_PRIMARY
4lo%i|Ws&y5m*v0        18 T_UPDATEITPUB个人空间 Z*xHvS ~%S
        19 T
Y2mE4O$\0        20 INF_PRODUCT
+Q }9}|1xQ a$x0        21 INF_DRUGITPUB个人空间J^(l QM/z W OXU4o
        22 T_OLD
8WRgu!O b0M z6c0        23 INF_PRODUCT_PROPERTY

已选择23行。


T1C1R~)S9?5h a~0SQL2> ROLLBACK;

回退已完成。

通过这种方法,简单的实现了读锁的功能,不过这种方法的缺点也很明显,要求用户必须通过函数的方式访问,而直接通过SQL方式访问是可以绕过锁机制的。

 


TAG:

成长的记忆 引用 删除 i168t   /   2008-06-03 09:07:36
高手就是能从不同的角度思考问题。
yangtingkun的个人空间 引用 删除 yangtingkun   /   2008-06-01 23:56:38
select for update无法满足要求,只能确保其他会话不修改数据,而无法保证其他会话不查询数据
引用 删除 xuxuwangzi   /   2008-06-01 14:23:21
引用 删除 krost1986   /   2008-05-31 19:33:17
select for update
引用 删除 smxzgh   /   2008-05-30 15:16:06
 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

Open Toolbar