CREATE TABLE "TEST6" ( "ID" VARCHAR2(30), "NAME" VARCHAR2(30), "AGE" NUMBER(2,0), "SEX" VARCHAR2(2), "ENAME" VARCHAR2(30), "ADDTIME" DATE ) insert into TEST6 (id, name, age, sex, ename, addtime) values ('1', '張三', 18, null, 'zhangsan', to_date('14-03-2017 00:00:09', 'dd-mm-yyyy hh24:mi:ss')); insert into TEST6 (id, name, age, sex, ename, addtime) values ('2', '李四', null, '1', 'Lisi', to_date('01-03-2017 02:00:00', 'dd-mm-yyyy hh24:mi:ss')); insert into TEST6 (id, name, age, sex, ename, addtime) values ('3', '王五', 20, '0', 'wangwu', to_date('09-01-2017 08:55:00', 'dd-mm-yyyy hh24:mi:ss')); insert into TEST6 (id, name, age, sex, ename, addtime) values ('4', '趙六', 23, '0', 'zhaoliu', to_date('03-03-2016 04:00:00', 'dd-mm-yyyy hh24:mi:ss')); insert into TEST6 (id, name, age, sex, ename, addtime) values ('5', '馮七', 22, null, 'fengqi', to_date('08-03-2017 12:00:01', 'dd-mm-yyyy hh24:mi:ss'));
本文主要介紹Oracle中的TM鎖,了解當我們通過sql語句訪問數據庫中的同一表對象時,此時如果多個用戶對同一表對象進行操作的話,可能會產生數據不一致,關於數據不一致,請參考數據庫事務的一致性和原子性淺析,oracle解決事務在多線程情況下的數據不一致問題,主要是通過兩種鎖,一種是悲觀鎖,也就是我接下來要說的,另一種是樂觀鎖,關於這兩種鎖的介紹同樣也請參考數據庫事務的一致性和原子性淺析。
TM鎖和TX鎖就是悲觀鎖的一部分,那么oracle是怎么通過TM鎖TX鎖來解決多用戶訪問同一對象,保證數據一致的問題的。
下面通過表格和文字來介紹所有的oracle TM鎖
表1 Oracle的TM鎖類型 |
|||
鎖模式 |
鎖描述 |
解釋 |
SQL操作 |
0 |
none |
||
1 |
NULL |
空 |
Select |
2 |
SS(Row-S) |
行級共享鎖,其他對象只能查詢這些數據行 |
Select for update、Lock for update、Lock row share |
3 |
SX(Row-X) |
行級排它鎖,在提交前不允許做DML操作 |
Insert、Update、Delete、Lock row share |
4 |
S(Share) |
共享鎖 |
Create index、Lock share |
5 |
SSX(S/Row-X) |
共享行級排它鎖 |
Lock share row exclusive |
6 |
X(Exclusive) |
排它鎖 |
Alter table、Drop able、Drop index、Truncate table 、Lock exclusive
|
1、SQL操作為:Select
當多用戶進行Select 操作時,oracle不會進行任何加鎖的,也就意味這,當有其他的用戶在訪問或者修改當前Select正在操作的結果集中的一行或多行數據時,是不會有任何影響的,Oracle會返回當前時刻的結果集。所以Select操作,不會進行任何加鎖操作。
2、SQL操作為:Select for update
請參考select for update和select for update wait和select for update nowait的區別,使用了select for update會給結果集加上一個行級共享鎖,其他的會話只能進行查詢操作(上面說了Select操作,不會對數據集進行加鎖)。
3、SQL操作為:Insert、Update、Delete
oracle在當前操作Commit之前會給相關數據行加上行級排它鎖,其他會話不能對當前數據行進行DML操作,代碼如下:
新建SQL窗口(相當於新建一個會話),執行以下代碼:
update test6 set NAME='zc' where ID=1
此時,不執行Commot操作,那么當前行(ID=1的數據行)將被加鎖
接着新建一個SQL窗口(相當於新建一個會話),執行以下代碼:
update test6 set NAME='zc1' where ID=1
結果顯示,會話二因為會話一對ID=1的數據行進行了加鎖,所以會話二會一直等待,知道會話一釋放鎖;
這里,Insert和Delete就不做實例代碼了,過程差不多,可以自行驗證。
4、SQL操作為:Create