- 論壇徽章:
- 0
|
INFORMIX鎖機(jī)制及如何分析其鎖沖突(第一部分)
本文講述INFORMIX數(shù)據(jù)庫(kù)鎖的基本原理,由2部分組成。IDS是OLTP應(yīng)用及內(nèi)嵌式系統(tǒng)的最佳解決方案。通過本文可以幫助你理解數(shù)據(jù)
庫(kù)鎖的使用方法,便于你及時(shí)處理、分析鎖沖突。
介紹
在多用戶數(shù)據(jù)庫(kù)系統(tǒng)中擁有成千上萬(wàn)的并發(fā)用戶在同時(shí)訪問數(shù)據(jù),因此我們需要有某種機(jī)制來(lái)保護(hù)數(shù)據(jù)以維護(hù)其數(shù)據(jù)一致性。除了事
物日志機(jī)制外,鎖機(jī)制就是我們采用的另一個(gè)主要手段。
然而,鎖機(jī)制經(jīng)常會(huì)導(dǎo)致沖突及等待現(xiàn)象的發(fā)生。這通常是一個(gè)DBA在日常管理工作中會(huì)碰到的一個(gè)普遍問題。如果缺乏一些適當(dāng)?shù)哪_
本或手段,往往會(huì)導(dǎo)致在分析鎖問題時(shí)變得越來(lái)越復(fù)雜并出現(xiàn)錯(cuò)誤。
本文將闡述IDS的鎖機(jī)制,幫助你分析出現(xiàn)的鎖沖突及鎖等待的情況。以下的示例基于數(shù)據(jù)庫(kù)stores_demo,該數(shù)據(jù)庫(kù)可通過以下命令
創(chuàng)建:
dbaccessdemo stores_demo -log
鎖類型
IDS包含幾種不同的鎖。通常有:
共享鎖
共享鎖可以被放置在沒有設(shè)置排他鎖的記錄上。其他用戶可以在相同的記錄上放置共享鎖或更新鎖,但是不能再放置排他鎖。
更新鎖
更新鎖是一種在使用更新游標(biāo)時(shí)產(chǎn)生的特殊類型的鎖。更新鎖只能被放置在當(dāng)前沒有設(shè)置更新鎖或排他鎖的記錄上。一旦記錄被加上
更新鎖,它的數(shù)據(jù)在被修改的同時(shí)就會(huì)立刻升級(jí)為排他鎖。
排他鎖
排他鎖只能被放置在沒有任何鎖的記錄上。一旦排他鎖被放置在該記錄上,則其他鎖也就不能在增加到該記錄了。該記錄將被被會(huì)話
獨(dú)占使用。
內(nèi)部鎖
內(nèi)部鎖包含多種特殊類型的鎖。舉個(gè)例子,當(dāng)一條記錄被修改時(shí),該記錄上被放置一個(gè)排他鎖,同時(shí)所涉及的數(shù)據(jù)庫(kù)表上也被放置一
個(gè)排他的內(nèi)部鎖。這是為了確保當(dāng)該表的數(shù)據(jù)在排他使用時(shí)其他的會(huì)話不能在該表上再設(shè)置共享或排他鎖。
鎖粒度
IDS允許應(yīng)用開發(fā)人員在不同的對(duì)象上放置鎖。有以下對(duì)象。
數(shù)據(jù)庫(kù)鎖
數(shù)據(jù)庫(kù)可以以排他或共享的方式被鎖住。在排他的情況下將防止其他任何人再訪問該數(shù)據(jù)庫(kù)。在共享的情況下允許并發(fā)用戶讀取或修
改該數(shù)據(jù)庫(kù)的數(shù)據(jù),但是不允許在該數(shù)據(jù)庫(kù)上再放置排他鎖。
數(shù)據(jù)庫(kù)共享鎖:
數(shù)據(jù)庫(kù)共享鎖在你打開數(shù)據(jù)庫(kù)的同時(shí)將被自動(dòng)設(shè)置。這將防止沒有其他用戶可以在該數(shù)據(jù)庫(kù)上再放置排他鎖或刪除數(shù)據(jù)庫(kù)。一些數(shù)據(jù)
庫(kù)工具:onunload也會(huì)在數(shù)據(jù)庫(kù)上放置共享鎖
SQL語(yǔ)句:
database stores_demo
Listing 1. Share lock on a database
Output from onstat -k:
----------------------
Locks
address wtlist owner lklist type tblsnum rowid key#/bsiz
300583dc 0 400d6998 0 HDR+S 100002 207 0
在這里你可以看到數(shù)據(jù)庫(kù)上加有共享鎖HDR+S。tblsnum=100002表明了數(shù)據(jù)庫(kù)的表空間。rowid=207是該數(shù)據(jù)庫(kù)信息存儲(chǔ)在數(shù)據(jù)庫(kù)
sysmaster,表sysdatabases中記錄的16進(jìn)制信息。數(shù)據(jù)庫(kù)表sysmaster:sysdatabases通常也被稱作數(shù)據(jù)庫(kù)的表空間。
數(shù)據(jù)庫(kù)及他們的16進(jìn)制rowid信息可以通過以下sql語(yǔ)句獲得:
Listing 2. Query on database sysmaster retrieving the row ID of a database tablespace entry
Query:
------
database sysmaster;
select name, hex(rowid) hex_rowid
from sysdatabases;
Result:
-------
name hex_rowid
linux_mag 0x00000204
onpload 0x00000206
stores_demo 0x00000207
sysmaster 0x00000201
sysuser 0x00000203
sysutils 0x00000202
tpcb 0x00000208
數(shù)據(jù)庫(kù)排他鎖:
一個(gè)排他鎖可以被排他的設(shè)置在數(shù)據(jù)庫(kù)上。數(shù)據(jù)庫(kù)工具:dbexport在倒出數(shù)據(jù)的時(shí)候就會(huì)在數(shù)據(jù)庫(kù)上放置一個(gè)排他鎖。
SQL 語(yǔ)句:
database stores_demo exclusive
Listing 3. Exclusive lock on a database
Output from onstat -k:
----------------------
Locks
address wtlist owner lklist type tblsnum rowid key#/bsiz
300583dc 0 400d63d8 0 HDR+X 100002 207 0
在這里你可以看到一個(gè)排他鎖(HDR+X)被放置在數(shù)據(jù)庫(kù)上,其對(duì)應(yīng)的rowid為207
表鎖:
與數(shù)據(jù)庫(kù)鎖類似,數(shù)據(jù)庫(kù)表也可以以排他或共享的形式被鎖住。排他鎖可以防止其他用戶讀取或修改該表信息。一種例外是該會(huì)話運(yùn)
行在臟讀的隔離級(jí)下。這樣就可以從已設(shè)置排他鎖的表中讀取數(shù)據(jù),但是該數(shù)據(jù)可能是不準(zhǔn)確的(正在修改中,沒有真正提交)。在表上設(shè)置
共享鎖可以允許其他用戶讀取該表數(shù)據(jù),但是不允許修改數(shù)據(jù)。
表共享鎖:
共享鎖可以以共享的形式放置在數(shù)據(jù)庫(kù)表上。數(shù)據(jù)庫(kù)工具:onunload、oncheck在使用的時(shí)候會(huì)在數(shù)據(jù)庫(kù)表上設(shè)置共享鎖(依賴于表的
鎖模式是頁(yè)還是記錄)
SQL 語(yǔ)句:
begin work; lock table orders in share mode
Listing 4. Share lock on a table
Output from onstat -k:
----------------------
Locks
address wtlist owner lklist type tblsnum rowid key#/bsiz
300582e0 0 400d63d8 300583dc HDR+S 10013b 0 0
你可以看到一個(gè)共享鎖(HDR+S)和rowid被設(shè)置為0(rowid=0)。rowid為0表明是一個(gè)表鎖。tablespace number (tblsnum=10013b)構(gòu)成
該表的16進(jìn)制partition number。
會(huì)導(dǎo)致這種情形的2種可能:
oncheck命令
Data Dictionary查詢命令
Listing 5. Identifying a table through its hexadecimal partition number
Dictionary Query:
-----------------
database stores_demo;
select st.tabname, dbinfo("dbspace", st.partnum), hex(st.partnum)
from systables st
where hex(st.partnum) = "0x0010013B";
Result:
------
tabname dbspace hex_partnum
orders rootdbs 0x0010013B
oncheck command:
----------------
oncheck -pt 0x0010013b
Result:
-------
TBLspace Report for stores_demo:informix.orders
Physical Address 1:1988
Creation date 08/21/2006 20:07:41
TBLspace Flags 801 Page Locking
TBLspace use 4 bit bit-maps
Maximum row size 80
Number of special columns 0
...
...
注意到你需要使用0x00對(duì)通過onstat -k獲得的16進(jìn)制信息進(jìn)行補(bǔ)足,使其形成8位完整的16進(jìn)制數(shù)。同時(shí)需將小寫字母轉(zhuǎn)換為大寫字
母,例如0x10013b-》0x0010013B。
如果是分片表的partnum,你需要在sysfragments表里面查找相應(yīng)信息:
Listing 6. Identifying a fragmented table through its hexadecimal partition number
Query:
------
database stores_demo;
select st.tabname, dbinfo("dbspace", sf.partn), hex(sf.partn)
from systables st, sysfragments sf
where st.tabid = sf.tabid
and sf.fragtype = "T"
and hex(sf.partn) = "0x0010013B";
Result:
-------
No rows found.
本例中的partition number 0x0010013B不是分片表的一個(gè)分片,因此在sysfragments表中不存在對(duì)應(yīng)信息。但是對(duì)于分片表則會(huì)有信
息記錄在sysfragments表中,請(qǐng)使用前面提供的語(yǔ)句進(jìn)行查詢。
oncheck -pt <hex_partnum>不能對(duì)分片表信息進(jìn)行查詢,它不會(huì)顯示真實(shí)的分片表名,僅有分片信息。
表排他鎖:
排他鎖可以被顯式的或隱式的被設(shè)置在對(duì)應(yīng)的表上。例如:alter table
SQL語(yǔ)句:
begin; lock table orders in exclusive mode
Listing 7. Exclusive lock on table
Output from onstat -k:
----------------------
Locks
address wtlist owner lklist type tblsnum rowid key#/bsiz
300582e0 0 400d63d8 300583dc HDR+X 10013b 0 0
在這里一個(gè)排他鎖(HDR+X)被設(shè)置在表上,對(duì)應(yīng)的tblsnum為10013b
頁(yè)或記錄級(jí)鎖:
鎖的級(jí)別(頁(yè)或記錄鎖)可以在創(chuàng)建表的時(shí)候進(jìn)行指定,或使用alter table對(duì)已有表進(jìn)行修改。
建表:
reate table t1 (f1 int) lock mode (row)
修改表:
alter table t1 modify lock mode (page)
缺省鎖模式,在創(chuàng)建表的時(shí)候采取何種鎖模式,可以通過在配置文件中配置DEF_TABLE_LOCKMODE來(lái)進(jìn)行指定或通過環(huán)境變量
IFX_DEF_TABLE_LOCKMODE來(lái)指定。在建表時(shí)所指定的鎖模式會(huì)優(yōu)先于通過DEF_TABLE_LOCKMODE或IFX_DEF_TABLE_LOCKMODE所指定的鎖模式。
使用頁(yè)鎖意味著即使只修改一條記錄也會(huì)將該記錄所在的整個(gè)數(shù)據(jù)頁(yè)進(jìn)行加鎖。依賴于記錄的大小及數(shù)據(jù)頁(yè)的大小,采用這種方式會(huì)
降低數(shù)據(jù)庫(kù)的并發(fā)處理性能。特別需要注意的是采取頁(yè)鎖不僅會(huì)對(duì)相關(guān)數(shù)據(jù)頁(yè)有影響,而且對(duì)索引頁(yè)同樣也會(huì)有影響。這樣會(huì)進(jìn)一步降低數(shù)據(jù)
庫(kù)的并發(fā)處理性能,因?yàn)樗饕?yè)相對(duì)于數(shù)據(jù)頁(yè)來(lái)說通常會(huì)包含更多的記錄。
你可以通過以下2種方式來(lái)確定當(dāng)前表采取了何種鎖模式:
Listing 8. Determining the lock mode of a table using oncheck (a) or a dictionary query (b)
a) Command:
-----------
oncheck -pt stores_demo:eherber.orders
Output:
-------
TBLspace Report for stores_log:informix.orders
Physical Address 1:3905
Creation date 05/08/2006 16:47:43
TBLspace Flags 801 Page Locking
...
...
b) Query:
---------
database stores_demo;
select tabname, locklevel
from systables
where tabname = "orders";
Result:
-------
tabname locklevel
orders P
以下為IDS中鎖模式的縮寫標(biāo)志:
B 視圖(需要檢查其依賴的鎖模式)
P 頁(yè)級(jí)鎖
R 記錄鎖
可以通過以下SQL語(yǔ)句產(chǎn)生相應(yīng)的修改已存在表的鎖模式的語(yǔ)句:
Listing 9. Using meta SQL to convert all tables to row locking
Meta SQL:
---------
database stores_demo;
output to alter_table.sql without headings
select "alter table '" || trim(owner) || "'." || trim(tabname) || " lock mode(row);"
from 'informix'.systables
where tabid > 99
and tabtype = 'T'
and locklevel = 'P';
Generated output file 'alter_table.sql':
----------------------------------------
alter table 'informix'.customer lock mode(row);
alter table 'informix'.orders lock mode(row);
...
...
頁(yè)鎖:
對(duì)于配置為使用頁(yè)鎖的表,在數(shù)據(jù)處理的過程中頁(yè)鎖會(huì)被設(shè)置在對(duì)應(yīng)的數(shù)據(jù)頁(yè)上。鎖的類型可能為排他鎖(插入、修改、刪除)或共
享鎖(設(shè)置隔離級(jí)為重復(fù)讀)
SQL語(yǔ)句:
begin; update orders set ship_charge = (ship_charge*1.2) where order_num = 1005
Listing 10. Exclusive lock on a page
Output from onstat -k:
----------------------
Locks
address wtlist owner lklist type tblsnum rowid key#/bsiz
440cf9bc 0 4506c3d0 0 HDR+S 100002 207 0
440cfa14 0 4506c3d0 440cf9bc HDR+IX 10013b 0 0
440d082c 0 4506c3d0 440cfa14 HDR+X 10013b 100 0
本例出現(xiàn)了3中類型的鎖:
1.數(shù)據(jù)庫(kù)上的共享鎖(HDR+S)。tblsnum=100002是該數(shù)據(jù)庫(kù)的partnum。
該共享鎖可以防止其他用戶在該數(shù)據(jù)庫(kù)上設(shè)置排他鎖
2.表上的內(nèi)部排他鎖(HDR+IX)。tblsnum=0表明這是一個(gè)表鎖。
內(nèi)部排他鎖可以防止其他用戶在該表上設(shè)置共享或排他鎖。
3.數(shù)據(jù)頁(yè)上的排他鎖(rowid=100,如果rowid的后2位為00,則表明該鎖為頁(yè)鎖)
排他鎖可以防止其他用戶在該數(shù)據(jù)頁(yè)上放置共享鎖或排他鎖。
記錄鎖:
如果數(shù)據(jù)庫(kù)表被設(shè)置為記錄級(jí)鎖,則在數(shù)據(jù)的處理過程中,只有相關(guān)的記錄上被設(shè)置上鎖。鎖的類型可能為排他鎖(插入、修改、刪
除)或共享鎖(設(shè)置隔離級(jí)為重復(fù)讀)
SQL語(yǔ)句:
begin; set isolation to repeatable read; select * from customer where customer_num = 110
Listing 11. Share lock on a row
Output from onstat -k:
----------------------
Locks
address wtlist owner lklist type tblsnum rowid key#/bsiz
440cf9bc 0 4506c3d0 0 HDR+S 100002 207 0
440cfa14 0 4506c3d0 440cf9bc HDR+IS 100139 0 0
440cfd84 0 4506c3d0 440d082c HDR+S 100139 10a 0
440d082c 0 4506c3d0 440cfa14 HDR+SR 10013a 10a K- 1
本例出現(xiàn)了4種類型的鎖:
1、數(shù)據(jù)庫(kù)上的共享鎖(HDR+S)。tblsnum=100002是該數(shù)據(jù)庫(kù)的partnum。
該共享鎖可以防止其他用戶在該數(shù)據(jù)庫(kù)上設(shè)置排他鎖
2、表上的內(nèi)部排他鎖(HDR+IX)。tblsnum=0表明這是一個(gè)表鎖。
內(nèi)部排他鎖可以防止其他用戶在該表上設(shè)置共享或排他鎖。
3、在記錄上設(shè)置的共享鎖(rowid=10a)
記錄上設(shè)置的共享鎖可以防止其他用戶在該記錄上設(shè)置排他鎖。
4、索引上設(shè)置的共享鎖(K-1)
在索引上設(shè)置的共享鎖可以防止其他用戶在該索引值上設(shè)置排他鎖。
你可以通過以下SQL查詢到被設(shè)置記錄鎖的相關(guān)記錄:
Listing 12. Identifying a locked row
Query:
------
database stores_demo;
set isolation to dirty read;
select *
from customer
where hex(rowid) = "0x0000010A";
Result:
-------
customer_num 110
fname Roy
...
...
索引鍵鎖:
類似于數(shù)據(jù)記錄上的鎖,IDS同樣在索引鍵上設(shè)置對(duì)應(yīng)的鎖,以保護(hù)其內(nèi)容。鍵值鎖可以確保唯一索引保持其唯一性,在事物未提交以
前不允許相同值的記錄插入到同樣的索引位置。
索引鍵鎖可以通過在onstat -k的輸出中于key#/bsiz字段中由K來(lái)表示出來(lái)。
數(shù)據(jù)庫(kù)的日志模式
IDS中可以使用的數(shù)據(jù)庫(kù)日志模式為以下4種:
無(wú)日志模式
緩沖日志模式
非緩沖日志模式
ANSI日志模式
這些日志模式在后續(xù)章節(jié)中進(jìn)行闡述。
無(wú)日志模式:
運(yùn)行在無(wú)日志模式下的數(shù)據(jù)庫(kù)。不能執(zhí)行begin、rollback、commit操作,事物信息不會(huì)被記錄在邏輯日志中。每條SQL語(yǔ)句的執(zhí)行,
自動(dòng)提交。所涉及的鎖只會(huì)影響當(dāng)前正在執(zhí)行的語(yǔ)句。
缺省隔離級(jí):
臟讀。這是在采用無(wú)日志模式的數(shù)據(jù)庫(kù)上唯一可以使用的隔離級(jí)
SQL語(yǔ)句:
create database stores_demo
緩沖日志模式:
事物信息被記錄在邏輯日志中。如果你想包含多條SQL操作于一個(gè)事物中,則顯式的begin操作是必須的。事物的結(jié)束以commit或
rollback為標(biāo)志。如果沒有顯式的begin作為事物的開始,則每條SQL語(yǔ)句將被看為獨(dú)立的事物。
如果commit命令被執(zhí)行,整個(gè)事物的信息并不是立即被寫入磁盤上的邏輯日志。這些信息將會(huì)被保存在共享內(nèi)存中的log buffer里。
當(dāng)log buffer滿或使用非緩沖日志方式的數(shù)據(jù)庫(kù)事物、使用ANSI日志模式的數(shù)據(jù)庫(kù)事物在事物提交的時(shí)候這些信息才真正的被寫入到磁盤上。
你應(yīng)該衡量由此帶來(lái)的對(duì)于數(shù)據(jù)庫(kù)事物吞吐率提升的好處與當(dāng)數(shù)據(jù)庫(kù)宕機(jī)時(shí)造成的數(shù)據(jù)丟失風(fēng)險(xiǎn)之間的利弊。如果你需要較高的事物
吞吐率,同時(shí)需要保存關(guān)鍵的業(yè)務(wù)數(shù)據(jù),使用高速磁盤或使用電池的ramdisk是一個(gè)不錯(cuò)的選擇。
缺省隔離級(jí):
提交讀
使用該日志模式的數(shù)據(jù)庫(kù)缺省隔離級(jí)為提交讀,但是用戶可以使用set isolation to <isol_level> 命令設(shè)置適當(dāng)?shù)钠渌綦x級(jí)
SQL命令:
create database stores_demo with buffered log
非緩沖日志模式:
與緩沖日志模式類似,但是使用該日志模式的數(shù)據(jù)庫(kù)在事物提交時(shí)將會(huì)立即將相關(guān)的事物信息寫入磁盤。你不會(huì)丟失任何已提交的事
物信息。
缺省隔離級(jí):
提交讀
使用該日志模式的數(shù)據(jù)庫(kù)缺省隔離級(jí)為提交讀,但是用戶可以使用set isolation to <isol_level> 命令設(shè)置適當(dāng)?shù)钠渌綦x級(jí)
SQL命令:
create database stores_demo with log
ANSI日志模式:
使用該日志模式的數(shù)據(jù)庫(kù)的缺省隔離級(jí)為重復(fù)讀,這意味著在處理的每條記錄上將會(huì)被設(shè)置上共享鎖。這會(huì)導(dǎo)致鎖沖突及所等待現(xiàn)象
的出現(xiàn)。隔離級(jí)別可以通過set isolation to <isolation_level> 命令進(jìn)行切換。
缺省隔離級(jí):
重復(fù)讀
使用該日志模式的數(shù)據(jù)庫(kù)可以使用set isolation to <isol_level>命令來(lái)進(jìn)行隔離級(jí)的切換
SQL命令:
create database stores_demo with log mode ansi
Database logging modes and default isolation levels
Database logging mode Create statement Default isolation level
No logging create database stores_demo Dirty read
Buffered logging create database stores_demo with buffered log Committed read
Unbuffered logging create database stores_demo with log Committed read
Mode ANSI (unbuffered logging) create database stores_demo with log mode ansi Repeatable read
當(dāng)前數(shù)據(jù)庫(kù)日志模式可以通過onmonitor工具或查詢sysmaster數(shù)據(jù)庫(kù)來(lái)獲得:
onmonitor (status-databases)
N -- 無(wú)日志
B -- 緩沖日志模式
U -- 非緩沖日志模式
U* -- ANSI模式 (unbuffered logging)
sysmaster query
Listing 13. Determining the logging mode of a database
Query:
------
database sysmaster;
select name, is_logging, is_buff_log, is_ansi
from sysmaster:sysdatabases;
Result:
-------
name stores_ansi
is_logging 1
is_buff_log 0
is_ansi 1
name stores_demo
is_logging 1
is_buff_log 0
is_ansi 0
你可以通過ontape或ondblog工具進(jìn)行數(shù)據(jù)庫(kù)日志模式的切換。需要注意的是一旦數(shù)據(jù)庫(kù)設(shè)置為ANSI日志模式,它將不能被切換為其他
的日志模式。
隔離級(jí):
在IDS中依賴于采用不同日志模式的數(shù)據(jù)庫(kù),有4中不同的隔離級(jí)可供使用。后面將一一予以介紹。
IDS isolation levels and their ANSI counterparts
Informix SQL ANSI SQL
Dirty read Read uncommittted
Committed read Read committed
Cursor stability Not available
Repeatable read Serializable
臟讀(ANSI: Read uncommitted)
如果你在讀取數(shù)據(jù)的時(shí)候采取該隔離級(jí),那么你將不會(huì)在涉及到的數(shù)據(jù)上設(shè)置鎖,也不會(huì)碰到任何鎖的問題。但是,你有可能得到的
是一個(gè)不準(zhǔn)確的數(shù)據(jù),因?yàn)樵摂?shù)據(jù)可能還沒有被提交。
臟讀是未帶日志模式的數(shù)據(jù)庫(kù)唯一可供選擇的隔離級(jí)別。
informix SQL
set isolation to dirty read [retain update locks]
ANSI SQL
set transaction isolation level read uncommitted
提交讀(ANSI: Read committed)
使用該隔離級(jí)可以確保所讀出的數(shù)據(jù)是已經(jīng)被提交后的。
運(yùn)行在提交讀隔離級(jí)下的會(huì)話會(huì)嘗試在需要讀取的數(shù)據(jù)上設(shè)置共享鎖,但不真正設(shè)置。這樣就能確保不會(huì)讀取到其他正在并發(fā)修改的
數(shù)據(jù)。然而,在讀取數(shù)據(jù)以后,由于沒有在該數(shù)據(jù)上設(shè)置任何鎖,因此其他的并發(fā)事物可以對(duì)該數(shù)據(jù)進(jìn)行修改。
提交讀是使用緩沖日志模式和非緩沖日志模式數(shù)據(jù)庫(kù)鎖采用的缺省隔離級(jí),但非使用ANSI日志模式的數(shù)據(jù)庫(kù)所采取的隔離級(jí)。
Informix SQL
set isolation to committed read [retain update locks]
ANSI SQL
set transaction isolation level read committed
游標(biāo)穩(wěn)定讀(ANSI: --)
游標(biāo)穩(wěn)定讀隔離級(jí)使用在更新游標(biāo)中。
IDS在當(dāng)前讀取的數(shù)據(jù)上放置一個(gè)更新鎖。如果該數(shù)據(jù)在此時(shí)被修改,則轉(zhuǎn)換為一個(gè)排他鎖并一直保持到事物結(jié)束,并不依賴于游標(biāo)所
處的當(dāng)前位置。如果讀取到下一條數(shù)據(jù)而當(dāng)前的數(shù)據(jù)沒有被修改,那么當(dāng)前數(shù)據(jù)上的更新鎖將被釋放,同時(shí)在下一條數(shù)據(jù)上放置更新鎖。如果
在set isolation命令中加上retain update locks子句則會(huì)改變這種情況。這樣在讀取到下一條數(shù)據(jù)的時(shí)候上一條數(shù)據(jù)上所放置的更新鎖將不
會(huì)被釋放。
更新鎖只能被放置在當(dāng)前沒有被設(shè)置任何更新鎖或排他鎖的數(shù)據(jù)上。然而,一旦更新鎖被放置,其他會(huì)話仍然是可以在該數(shù)據(jù)上放置
共享鎖的。這種情況下如果你試圖去更新這些數(shù)據(jù)將會(huì)導(dǎo)致錯(cuò)誤,因?yàn)橛捎诖嬖诠蚕礞iIDS將不能把一個(gè)更新鎖升級(jí)成為一個(gè)排他鎖。這是我們
希望得到的一種結(jié)果。如果你確定在后續(xù)的操作中你肯定需要更新數(shù)據(jù),那么你可以使用dummy update將所有的更新鎖都升級(jí)為排他鎖。這將
避免其他的并發(fā)會(huì)話在相同的記錄上設(shè)置共享鎖。
Informix SQL
set isolation to cursor stability [retain update locks]
ANSI SQL
--
重復(fù)讀(ANSI: Serializable)
使用重復(fù)讀隔離級(jí)將會(huì)在所讀取的記錄上都設(shè)置共享鎖(如果使用頁(yè)級(jí)鎖將會(huì)在所涉及的數(shù)據(jù)頁(yè)上都設(shè)置共享鎖)。這將可以避免其
他用戶更改這些數(shù)據(jù)。
retain update locks子句在這種隔離級(jí)下將不能使用,因?yàn)檫@種隔離級(jí)本身就會(huì)自動(dòng)保持共享鎖或更新鎖。
重復(fù)讀這種隔離級(jí)是采用ANSI日志模式的數(shù)據(jù)庫(kù)所使用的缺省隔離級(jí)別。
Informix SQL
set isolation to repeatable read
ANSI SQL
set transaction isolation level serializable
Informix SQL 與 ANSI SQL之間的區(qū)別:
在informix使用的SQL命令set isolation to <isol_level>和ANSI使用的SQL命令set transaction isolation level <isol_level>之
間具有2個(gè)重要的區(qū)別。
在informix中所執(zhí)行的命令是基于會(huì)話的。也就是說在整個(gè)會(huì)話中你一旦設(shè)置好隔離級(jí)就會(huì)立刻生效直到你下一次使用set isolation
to <isol_level>命令重新設(shè)置為止。
對(duì)應(yīng)的在ANSI中所執(zhí)行的命令是基于事物的。隔離級(jí)設(shè)置好以后將會(huì)只對(duì)當(dāng)前事物有效。一旦事物結(jié)束,則隔離級(jí)別將會(huì)自動(dòng)切換為
當(dāng)前打開數(shù)據(jù)庫(kù)所具有的缺省隔離級(jí)。更多的信息,請(qǐng)參照數(shù)據(jù)庫(kù)日志模式一節(jié)。
在數(shù)據(jù)庫(kù)事物中你將不能使用ANSI的SQL命令set transaction isolation level <isol_level>來(lái)設(shè)置新的隔離級(jí)別。這是不允許的。
但是informix允許在事物中進(jìn)行隔離級(jí)別的切換。
會(huì)話的隔離級(jí)別:
你可以通過執(zhí)行onstat -g sql命令來(lái)得到當(dāng)前正在執(zhí)行的會(huì)話所使用的隔離級(jí)別。
Listing 14. Listing isolation levels of individual database sessions
Command:
---------
onstat -g sql
Output:
-------
Sess SQL Current Iso Lock SQL ISAM F.E.
Id Stmt type Database Lvl Mode ERR ERR Vers Explain
50 - stores_demo RR Wait 10 0 0 9.03 Off
45 - stores_demo DR Not Wait 0 0 9.03 Off
...
...
當(dāng)前數(shù)據(jù)庫(kù)所采用的隔離級(jí)別將顯示在Iso Lvl字段下,以下為其縮寫方式:
DR -- 臟讀
CR -- 提交讀
CS -- 游標(biāo)穩(wěn)定讀
RR -- 重復(fù)讀
小結(jié):
現(xiàn)在你對(duì)數(shù)據(jù)庫(kù)鎖的類型、鎖的粒度、數(shù)據(jù)庫(kù)的日志模式、隔離級(jí)別有了一個(gè)初步的認(rèn)識(shí)。在后續(xù)部分我們將對(duì)以下內(nèi)能進(jìn)行介紹:
鎖的等待時(shí)間
鎖的動(dòng)態(tài)分配
死鎖
鎖的等待情況
本文作者:Eric Herber |
評(píng)分
-
查看全部評(píng)分
|