1.存儲(chǔ)過程是什么?我們常用的關(guān)系型數(shù)據(jù)庫是MySQL,,操作數(shù)據(jù)庫的語言一般為SQL語句,,SQL在執(zhí)行的時(shí)候需要要先編譯,然后執(zhí)行,,而存儲(chǔ)過程(Stored Procedure)是一組為了完成某種特定功能的SQL語句集,,經(jīng)編譯后存儲(chǔ)在數(shù)據(jù)庫中,用戶通過指定存儲(chǔ)過程的名字并給定參數(shù)(如果該存儲(chǔ)過程帶有參數(shù))來調(diào)用執(zhí)行它,。 一個(gè)存儲(chǔ)過程是一個(gè)可編程的函數(shù),,它在數(shù)據(jù)庫中創(chuàng)建并保存。它可以有SQL語句和一些特殊的控制結(jié)構(gòu)組成,。當(dāng)希望在不同的應(yīng)用程序或平臺(tái)上執(zhí)行相同的函數(shù),,或者封裝特定功能時(shí),存儲(chǔ)過程是非常有用的,。數(shù)據(jù)庫中的存儲(chǔ)過程可以看做是對(duì)面向?qū)ο蠓椒ǖ哪M,,它允許控制數(shù)據(jù)的訪問方式。 優(yōu)點(diǎn)(1)存儲(chǔ)過程增強(qiáng)了SQL語言的功能和靈活性:存儲(chǔ)過程可以用流控制語句編寫,,有很強(qiáng)的靈活性,,可以完成復(fù)雜的判斷和較復(fù)雜的運(yùn)算。 (2)存儲(chǔ)過程允許標(biāo)準(zhǔn)組件式編程:存儲(chǔ)過程被創(chuàng)建后,,可以在程序中被多次調(diào)用,,而不必重新編寫該存儲(chǔ)過程的SQL語句。而且可以隨時(shí)對(duì)存儲(chǔ)過程進(jìn)行修改,,對(duì)應(yīng)用程序源代碼毫無影響,。 (3)存儲(chǔ)過程能實(shí)現(xiàn)較快的執(zhí)行速度:如果某一操作包含大量的Transaction-SQL代碼或分別被多次執(zhí)行,那么存儲(chǔ)過程要比批處理的執(zhí)行速度快很多,。因?yàn)榇鎯?chǔ)過程是預(yù)編譯的,。在首次運(yùn)行一個(gè)存儲(chǔ)過程時(shí),優(yōu)化器對(duì)其進(jìn)行分析優(yōu)化,并且給出最終被存儲(chǔ)在系統(tǒng)表中的執(zhí)行計(jì)劃,。而批處理的Transaction-SQL語句在每次運(yùn)行時(shí)都要進(jìn)行編譯和優(yōu)化,,速度相對(duì)要慢一些。 (4)存儲(chǔ)過程能減少網(wǎng)絡(luò)流量:針對(duì)同一個(gè)數(shù)據(jù)庫對(duì)象的操作(如查詢,、修改),,如果這一操作所涉及的Transaction-SQL語句被組織成存儲(chǔ)過程,那么當(dāng)在客戶計(jì)算機(jī)上調(diào)用該存儲(chǔ)過程時(shí),,網(wǎng)絡(luò)中傳送的只是該調(diào)用語句,,從而大大增加了網(wǎng)絡(luò)流量并降低了網(wǎng)絡(luò)負(fù)載。 (5)存儲(chǔ)過程可被作為一種安全機(jī)制來充分利用:系統(tǒng)管理員通過執(zhí)行某一存儲(chǔ)過程的權(quán)限進(jìn)行限制,,能夠?qū)崿F(xiàn)對(duì)相應(yīng)的數(shù)據(jù)的訪問權(quán)限的限制,,避免了非授權(quán)用戶對(duì)數(shù)據(jù)的訪問,保證了數(shù)據(jù)的安全,。 2.索引是什么,?索引(Index)是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu);在數(shù)據(jù)之外,,數(shù)據(jù)庫系統(tǒng)還維護(hù)著滿足特定查找算法的數(shù)據(jù)結(jié)構(gòu),,這些數(shù)據(jù)結(jié)構(gòu)以某種方式引用(指向)數(shù)據(jù),可以在這些數(shù)據(jù)結(jié)構(gòu)上實(shí)現(xiàn)高級(jí)查找算法,,提高查詢速度,,這種數(shù)據(jù)結(jié)構(gòu),就是索引,。 索引存儲(chǔ)分類索引是在MySQL的存儲(chǔ)引擎層中實(shí)現(xiàn)的,,而不是在服務(wù)層實(shí)現(xiàn)的。所以各種存儲(chǔ)引擎支持的索引并不相同,,MySQL目前提供了以下4種索引,。 B-Tree 索引:最常見的索引類型,大部分引擎都支持B樹索引,。 HASH 索引:只有Memory引擎支持,,使用場(chǎng)景簡(jiǎn)單。 R-Tree 索引(空間索引):空間索引是MyISAM的一種特殊索引類型,,主要用于地理空間數(shù)據(jù)類型,。 Full-text (全文索引):全文索引也是MyISAM的一種特殊索引類型,主要用于全文索引,,InnoDB從MySQL5.6版本提供對(duì)全文索引的支持,。 B-TREE索引類型普通索引 這是最基本的索引類型,而且它沒有唯一性之類的限制,,可以通過以下幾種方式創(chuàng)建: (1)創(chuàng)建索引: CREATE INDEX 索引名 ON 表名(列名1,,列名2,…); (2)修改表: ALTER TABLE 表名 ADD INDEX 索引名 (列名1,,列名2,…); (3)創(chuàng)建表時(shí)指定索引:CREATE TABLE 表名 ( […], INDEX 索引名 (列名1,列名 2,…) ); UNIQUE索引 表示唯一的,,不允許重復(fù)的索引,,若某一字段的信息不能重復(fù)(例如身份證號(hào)),可以將該字段的索引設(shè)置為unique: (1)創(chuàng)建索引:CREATE UNIQUE INDEX 索引名 ON 表名(列名1,,列名2,…); (2)修改表:ALTER TABLE 表名ADD UNIQUE 索引名 (列名1,列名2,…); (3)創(chuàng)建表時(shí)指定索引:CREATE TABLE 表名( […], UNIQUE 索引名 (列名1,,列名2,…)); 主鍵:PRIMARY KEY索引 主鍵是一種唯一性索引,,但它必須指定為“PRIMARY KEY”??梢詫⑵淅斫鉃?索引名固定為 PRIMARY KEY 的 UNIQUE索引,。 (1)主鍵一般在創(chuàng)建表的時(shí)候指定:“CREATE TABLE 表名( […], PRIMARY KEY (列的列表) ); ”。 (2)但是,,我們也可以通過修改表的方式加入主鍵:“ALTER TABLE 表名 ADD PRIMARY KEY (列的列表); ”,。 每個(gè)表只能有一個(gè)主鍵。 (主鍵相當(dāng)于聚合索引,,是查找最快的索引) 注:不能用CREATE INDEX語句創(chuàng)建PRIMARY KEY索引 常用語法設(shè)置索引 在執(zhí)行CREATE TABLE語句時(shí)可以創(chuàng)建索引,,也可以單獨(dú)用CREATE INDEX或ALTER TABLE來為數(shù)據(jù)表增加索引。 1.ALTER TABLE - ALTER TABLE可以用來創(chuàng)建普通索引,、UNIQUE索引或PRIMARY KEY索引,。 ALTER TABLE table_name ADD INDEX index_name (column_list)
ALTER TABLE table_name ADD UNIQUE index_name (column_list)
ALTER TABLE table_name ADD PRIMARY KEY (column_list)
2.CREATE INDEX - CREATE INDEX可對(duì)表增加普通索引或UNIQUE索引。 CREATE INDEX index_name ON table_name (column_list)
CREATE UNIQUE INDEX index_name ON table_name (column_list)
刪除索引 可利用ALTER TABLE或DROP INDEX語句來刪除索引,。類似于CREATE INDEX語句,,DROP INDEX可以在ALTER TABLE內(nèi)部作為一條語句處理,語法如下,。 DROP INDEX index_name ON talbe_name
ALTER TABLE table_name DROP INDEX index_name
ALTER TABLE table_name DROP PRIMARY KEY
其中,,前兩條語句是等價(jià)的,刪除掉table_name中名為index_name的索引,。 第3條語句只在刪除PRIMARY KEY索引時(shí)使用,,因?yàn)橐粋€(gè)表只可能有一個(gè)PRIMARY KEY索引,因此不需要指定索引名,。如果沒有創(chuàng)建PRIMARY KEY索引,,但表具有一個(gè)或多個(gè)UNIQUE索引,則MySQL將刪除第一個(gè)UNIQUE索引,。 如果從表中刪除了某列,,則索引會(huì)受到影響。對(duì)于多列組合的索引,,如果刪除其中的某列,,則該列也會(huì)從索引中刪除。如果刪除組成索引的所有列,則整個(gè)索引將被刪除,。 查看索引 mysql> show index from tblname;
設(shè)置索引的原則較頻繁的作為查詢條件的字段應(yīng)該創(chuàng)建索引 唯一性太差的字段不適合單獨(dú)創(chuàng)建索引,,即使頻繁作為查詢條件 更新非常頻繁的字段不適合創(chuàng)建索引 不會(huì)出現(xiàn)在 WHERE 子句中的字段不該創(chuàng)建索引 索引的選擇性較低不宜建索引 注:所謂索引的選擇性(Selectivity),是指不重復(fù)的索引值(也叫基數(shù),,Cardinality)與表記錄數(shù)的比值,,顯然選擇性的取值范圍為(0, 1]:
SELECT count(DISTINCT(column_name))/count(*) AS Selectivity FROM table_name;
索引的弊端索引是有代價(jià)的:索引文件本身要消耗存儲(chǔ)空間,同時(shí)索引會(huì)加重插入,、刪除和修改記錄時(shí)的負(fù)擔(dān),,另外,MySQL在運(yùn)行時(shí)也要消耗資源維護(hù)索引,,因此索引并不是越多越好,。 參考1 3.B+ 樹 如上圖,是一顆b+樹,,淺藍(lán)色的塊我們稱之為一個(gè)磁盤塊,,可以看到每個(gè)磁盤塊包含幾個(gè)數(shù)據(jù)項(xiàng)(深藍(lán)色所示)和指針(黃色所示),如磁盤塊1包含數(shù)據(jù)項(xiàng)17和35,,包含指針P1,、P2、P3,,P1表示小于17的磁盤塊,,P2表示在17和35之間的磁盤塊,P3表示大于35的磁盤塊,。真實(shí)的數(shù)據(jù)存在于葉子節(jié)點(diǎn)即3,、5、9,、10,、13、15,、28,、29、36,、60,、75、79,、90,、99。非葉子節(jié)點(diǎn)不存儲(chǔ)真實(shí)的數(shù)據(jù),,只存儲(chǔ)指引搜索方向的數(shù)據(jù)項(xiàng),,如17,、35并不真實(shí)存在于數(shù)據(jù)表中。 b+樹的查找過程如圖所示,,如果要查找數(shù)據(jù)項(xiàng)29,,那么首先會(huì)把磁盤塊1由磁盤加載到內(nèi)存,此時(shí)發(fā)生一次IO,,在內(nèi)存中用二分查找確定29在17和35之間,,鎖定磁盤塊1的P2指針,內(nèi)存時(shí)間因?yàn)榉浅6蹋ㄏ啾却疟P的IO)可以忽略不計(jì),,通過磁盤塊1的P2指針的磁盤地址把磁盤塊3由磁盤加載到內(nèi)存,,發(fā)生第二次IO,29在26和30之間,,鎖定磁盤塊3的P2指針,通過指針加載磁盤塊8到內(nèi)存,,發(fā)生第三次IO,,同時(shí)內(nèi)存中做二分查找找到29,結(jié)束查詢,,總計(jì)三次IO,。真實(shí)的情況是,3層的b+樹可以表示上百萬的數(shù)據(jù),,如果上百萬的數(shù)據(jù)查找只需要三次IO,,性能提高將是巨大的,如果沒有索引,,每個(gè)數(shù)據(jù)項(xiàng)都要發(fā)生一次IO,,那么總共需要百萬次的IO,顯然成本非常非常高,。 b+樹性質(zhì)1.通過上面的分析,,我們知道IO次數(shù)取決于b+樹的高度h,假設(shè)當(dāng)前數(shù)據(jù)表的數(shù)據(jù)量為N,,每個(gè)磁盤塊的數(shù)據(jù)項(xiàng)的數(shù)量是m,,則有h=㏒(m+1)N,當(dāng)數(shù)據(jù)量N一定的情況下,,m越大,,h越小,;而m = 磁盤塊的大小 / 數(shù)據(jù)項(xiàng)的大小,,磁盤塊的大小也就是一個(gè)數(shù)據(jù)頁的大小,是固定的,,如果數(shù)據(jù)項(xiàng)占的空間越小,,數(shù)據(jù)項(xiàng)的數(shù)量越多,,樹的高度越低。這就是為什么每個(gè)數(shù)據(jù)項(xiàng),,即索引字段要盡量的小,,比如int占4字節(jié),要比bigint8字節(jié)少一半,。這也是為什么b+樹要求把真實(shí)的數(shù)據(jù)放到葉子節(jié)點(diǎn)而不是內(nèi)層節(jié)點(diǎn),,一旦放到內(nèi)層節(jié)點(diǎn),磁盤塊的數(shù)據(jù)項(xiàng)會(huì)大幅度下降,,導(dǎo)致樹增高,。當(dāng)數(shù)據(jù)項(xiàng)等于1時(shí)將會(huì)退化成線性表。 2.當(dāng)b+樹的數(shù)據(jù)項(xiàng)是復(fù)合的數(shù)據(jù)結(jié)構(gòu)的時(shí)候,,比如(name,age,sex),,b+樹是按照從左到右的順序來建立搜索樹的,比如當(dāng)(張三,20,F)這樣的數(shù)據(jù)來檢索的時(shí)候,,b+樹會(huì)優(yōu)先比較name來確定下一步的所搜方向,,如果name相同再依次比較age和sex,最后得到檢索的數(shù)據(jù),;但當(dāng)(20,F)這樣的沒有name的數(shù)據(jù)來的時(shí)候,,b+樹就不知道下一步該查哪個(gè)節(jié)點(diǎn),因?yàn)榻⑺阉鳂涞臅r(shí)候name就是第一個(gè)比較因子,,必須要先根據(jù)name來搜索才能知道下一步去哪里查詢,。比如當(dāng)(張三,F)這樣的數(shù)據(jù)來檢索時(shí),b+樹可以用name來指定搜索方向,,但下一個(gè)字段age的缺失,,所以只能把名字等于張三的數(shù)據(jù)都找到,然后再匹配性別是F的數(shù)據(jù)了,, 這個(gè)是非常重要的性質(zhì),,即索引的最左匹配特性。 參考2 4.事務(wù)是什么,?事務(wù)(Transaction)是并發(fā)控制的基本單位,。所謂的事務(wù),它是一個(gè)操作序列,,由一條或者多條sql語句組成,這些操作要么都執(zhí)行,,要么都不執(zhí)行,它是一個(gè)不可分割的工作單位,。 ACID特性事務(wù)應(yīng)該具有4個(gè)屬性:原子性,、一致性,、隔離性、持久性,。 原子性(Atomicity):指整個(gè)數(shù)據(jù)庫事務(wù)是不可分割的工作單位,。只有事務(wù)中所有的數(shù)據(jù)庫操作都執(zhí)行成功,整個(gè)事務(wù)的執(zhí)行才算成功,。事務(wù)中任何一個(gè)sql語句執(zhí)行失敗,那么已經(jīng)執(zhí)行成功的sql語句也必須撤銷,,數(shù)據(jù)庫狀態(tài)應(yīng)該退回到執(zhí)行事務(wù)前的狀態(tài),。 一致性(Consistency):事務(wù)應(yīng)確保數(shù)據(jù)庫的狀態(tài)從一個(gè)一致狀態(tài)轉(zhuǎn)變?yōu)榱硪粋€(gè)一致狀態(tài),。一致狀態(tài)的含義是數(shù)據(jù)庫中的數(shù)據(jù)應(yīng)滿足完整性約束,,也就是說在事務(wù)開始之前和事務(wù)結(jié)束以后,數(shù)據(jù)庫的完整性約束沒有被破壞 隔離性(Isolation):隔離性也叫做并發(fā)控制,、可串行化或者鎖,。事務(wù)的隔離性要求每個(gè)讀寫事務(wù)的對(duì)象與其它事務(wù)的操作對(duì)象能相互分離,即該事務(wù)提交前對(duì)其它事務(wù)都不可見,,這通常使用鎖來實(shí)現(xiàn)多個(gè)事務(wù)并發(fā)執(zhí)行時(shí),,一個(gè)事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行,。 持久性(Durability):表示事務(wù)一旦提交了,其結(jié)果就是永久性的,,也就是數(shù)據(jù)就已經(jīng)寫入到數(shù)據(jù)庫了,,如果發(fā)生了宕機(jī)等事故,數(shù)據(jù)庫也能將數(shù)據(jù)恢復(fù),。 事務(wù)的分類事務(wù)分為一下5類: 扁平事務(wù); 帶有保存點(diǎn)的扁平事務(wù),; 鏈?zhǔn)聞?wù); 嵌套事務(wù),; 分布式事務(wù),。
扁平事務(wù) 扁平事務(wù)是最簡(jiǎn)單的一種,也是實(shí)際開發(fā)中使用的最多的一種事務(wù),。在這種事務(wù)中,,所有操作都處于同一層次,最常見的方式如下: BEGIN WORK
Operation 1
Operation 2
Operation 3
...
Operation N
COMMIT WORK
或者: BEGIN WORK
Operation 1
Operation 2
Operation 3
...
Operation N
(Error Occured)
ROLLBACK WORK
扁平事務(wù)很簡(jiǎn)單,,但有一個(gè)主要缺點(diǎn)是不能提交或回滾事務(wù)的某一部分,,或者分幾個(gè)獨(dú)立的步驟去提交。 比如有這樣的一個(gè)例子,,我從呼和浩特去深圳,,為了便宜,我可能這么干: BEGIN WORK
Operation1:呼和浩特---火車--->北京
Operation2:北京---飛機(jī)--->深圳
ROLLBACK WORK
但是,,如果在Operation1中,,從呼和浩特到北京的火車晚點(diǎn)了,錯(cuò)過了航班,,怎么辦,? 因?yàn)楸馄绞聞?wù)的特性,那我就需要回滾,,我需要再回到呼和浩特,,這樣做的成本太高,,所以就有了下面的第二種事務(wù)——帶有保存點(diǎn)的扁平事務(wù)。 帶有保存點(diǎn)的扁平事務(wù) 這種事務(wù)除了支持扁平事務(wù)支持的操作外,,允許在事務(wù)執(zhí)行過程中回滾到同一事務(wù)中較早的一個(gè)狀態(tài),,這是因?yàn)榭赡苣承┦聞?wù)在執(zhí)行過程中出現(xiàn)的錯(cuò)誤并不會(huì)對(duì)所有的操作都無效,放棄整個(gè)事務(wù)不合乎要求,,開銷也太大,。保存點(diǎn)用來通知系統(tǒng)應(yīng)該記住事務(wù)當(dāng)前的狀態(tài),以便以后發(fā)生錯(cuò)誤時(shí),,事務(wù)能回到該狀態(tài),。 鏈?zhǔn)聞?wù) 鏈?zhǔn)聞?wù),就是指回滾時(shí),,只能恢復(fù)到最近一個(gè)保存點(diǎn),;而帶有保存點(diǎn)的扁平事務(wù)則可以回滾到任意正確的保存點(diǎn)。 嵌套事務(wù) 通過下面實(shí)例來說明什么叫嵌套事務(wù) BEGIN WORK
SubTransaction1:
BEGIN WORK
SubOperationX
COMMIT WORK
SubTransaction2:
BEGIN WORK
SubOperationY
COMMIT WORK
...
SubTransactionN:
BEGIN WORK
SubOperationN
COMMIT WORK
COMMIT WORK
這就是嵌套事務(wù),,在事務(wù)中再嵌套事務(wù),,位于根節(jié)點(diǎn)的事務(wù)稱為頂層事務(wù)。事務(wù)的前驅(qū)稱為父事務(wù),,事務(wù)的下一層稱為子事務(wù),。 子事務(wù)既可以提交也可以回滾,但是它的提交操作并不馬上生效,,除非由其父事務(wù)提交,。因此就可以確定,任何子事務(wù)都在頂層事務(wù)提交后才真正的被提交了,。同理,任意一個(gè)事務(wù)的回滾都會(huì)引起它的所有子事務(wù)一同回滾,。 分布式事務(wù) 分布式事務(wù)通常是指在一個(gè)分布式環(huán)境下運(yùn)行的扁平事務(wù),,因此需要根據(jù)數(shù)據(jù)所在位置訪問網(wǎng)絡(luò)中的不同節(jié)點(diǎn),比如:通過建設(shè)銀行向招商銀行轉(zhuǎn)賬,,建設(shè)銀行和招商銀行肯定用的不是同一個(gè)數(shù)據(jù)庫,,同時(shí)二者的數(shù)據(jù)庫也不在一個(gè)網(wǎng)絡(luò)節(jié)點(diǎn)上,那么當(dāng)用戶跨行轉(zhuǎn)賬,,就是通過分布式事務(wù)來保證數(shù)據(jù)的ACID的,。 在MySQL中使用事務(wù)在MySQL命令行的默認(rèn)設(shè)置下,事務(wù)都是自動(dòng)提交的,,即執(zhí)行SQL語句后就會(huì)馬上執(zhí)行COMMIT操作,。因此要顯示地開啟一個(gè)事務(wù)須使用命令BEGIN或START TRANSACTION,或者執(zhí)行命令SET AUTOCOMMIT=0,,用來禁止使用當(dāng)前會(huì)話的自動(dòng)提交,。 來看看我們可以使用哪些事務(wù)控制語句,。 BEGIN或START TRANSACTION;顯示地開啟一個(gè)事務(wù),; COMMIT,;也可以使用COMMIT WORK,,不過二者是等價(jià)的,。COMMIT會(huì)提交事務(wù),,并使已對(duì)數(shù)據(jù)庫進(jìn)行的所有修改稱為永久性的,; ROLLBACK,;有可以使用ROLLBACK WORK,,不過二者是等價(jià)的,?;貪L會(huì)結(jié)束用戶的事務(wù),,并撤銷正在進(jìn)行的所有未提交的修改,; SAVEPOINT identifier;SAVEPOINT允許在事務(wù)中創(chuàng)建一個(gè)保存點(diǎn),,一個(gè)事務(wù)中可以有多個(gè)SAVEPOINT,; RELEASE SAVEPOINT identifier;刪除一個(gè)事務(wù)的保存點(diǎn),,當(dāng)沒有指定的保存點(diǎn)時(shí),,執(zhí)行該語句會(huì)拋出一個(gè)異常; ROLLBACK TO identifier,;把事務(wù)回滾到標(biāo)記點(diǎn),; SET TRANSACTION;用來設(shè)置事務(wù)的隔離級(jí)別,。
事務(wù)的隔離級(jí)別在數(shù)據(jù)庫操作中,,為了有效保證并發(fā)讀取數(shù)據(jù)的正確性,提出的事務(wù)隔離級(jí)別,。 InnoDB存儲(chǔ)引擎提供事務(wù)的隔離級(jí)別有READ UNCOMMITTED,、READ COMMITTED、REPEATABLE READ和SERIALIZABLE,。這些隔離級(jí)別之間的區(qū)別如下:
臟讀:一個(gè)事務(wù)讀取到了另外一個(gè)事務(wù)沒有提交的數(shù)據(jù),; 比如:事務(wù)T1更新了一行記錄的內(nèi)容,但是并沒有提交所做的修改,。事務(wù)T2讀取到了T1更新后的行,,然后T1執(zhí)行回滾操作,取消了剛才所做的修改?,F(xiàn)在T2所讀取的行就無效了,; 不可重復(fù)讀:在同一事務(wù)中,兩次讀取同一數(shù)據(jù),得到內(nèi)容不同,; 比如:事務(wù)T1讀取一行記錄,,緊接著事務(wù)T2修改了T1剛才讀取的那一行記錄。然后T1又再次讀取這行記錄,,發(fā)現(xiàn)與剛才讀取的結(jié)果不同,。這就稱為“不可重復(fù)”讀,因?yàn)門1原來讀取的那行記錄已經(jīng)發(fā)生了變化,; 幻讀:同一事務(wù)中,,用同樣的操作讀取兩次,得到的記錄數(shù)不相同,; 比如:事務(wù)T1讀取一條指定的WHERE子句所返回的結(jié)果集,。然后事務(wù)T2新插入 一行記錄,這行記錄恰好可以滿足T1所使用的查詢條件中的WHERE子句的條件,。然后T1又使用相同的查詢?cè)俅螌?duì)表進(jìn)行檢索,,但是此時(shí)卻看到了事務(wù)T2剛才插入的新行。這個(gè)新行就稱為“幻像”,,因?yàn)閷?duì)T1來說這一行就像突然出現(xiàn)的一樣,。 隔離級(jí)別越低,事務(wù)請(qǐng)求的鎖越少或保持鎖的時(shí)間就越短,。InnoDB存儲(chǔ)引擎默認(rèn)的支持隔離級(jí)別是REPEATABLE READ,;在這種默認(rèn)的事務(wù)隔離級(jí)別下已經(jīng)能完全保證事務(wù)的隔離性要求,即達(dá)到SQL標(biāo)準(zhǔn)的SERIALIZABLE級(jí)別隔離,。 我們可以可以用SET TRANSACTION語句改變單個(gè)會(huì)話或者所有新進(jìn)連接的隔離級(jí)別,。它的語法如下: 5.視圖視圖是一種虛擬的表,具有和物理表相同的功能,,可以對(duì)視圖進(jìn)行增,,改,查操作,,視圖通常是有一個(gè)表或者多個(gè)表的行或列的子集,,對(duì)視圖的修改不影響基本表,它使得我們獲取數(shù)據(jù)更容易,,相比多表查詢。 6.超鍵 候選鍵 主鍵 外鍵超鍵:在關(guān)系中能唯一標(biāo)識(shí)元組(數(shù)據(jù)庫中的一條記錄)的屬性集稱為關(guān)系模式的超鍵,。一個(gè)屬性可以為作為一個(gè)超鍵,,多個(gè)屬性組合在一起也可以作為一個(gè)超鍵。超鍵包含候選鍵和主鍵,。 候選鍵:是最小超鍵,,即沒有冗余元素的超鍵。 主鍵:數(shù)據(jù)庫表中對(duì)儲(chǔ)存數(shù)據(jù)對(duì)象予以唯一和完整標(biāo)識(shí)的數(shù)據(jù)列或?qū)傩缘慕M合,用戶選作元組標(biāo)識(shí)的一個(gè)侯選鍵稱為主鍵,。一個(gè)數(shù)據(jù)列只能有一個(gè)主鍵,,且主鍵的取值不能缺失,即不能為空值(Null),。 外鍵:在一個(gè)表中存在的另一個(gè)表的主鍵稱此表的外鍵,,外鍵主要是用來描述兩個(gè)表的關(guān)系。 7.三個(gè)范式第一范式(1NF):數(shù)據(jù)庫表中的字段都是單一屬性的,,不可再分,。這個(gè)單一屬性由基本類型構(gòu)成,包括整型,、實(shí)數(shù),、字符型、邏輯型,、日期型等,。 第二范式(2NF):數(shù)據(jù)庫表中不存在非關(guān)鍵字段對(duì)任一候選關(guān)鍵字段的部分函數(shù)依賴(部分函數(shù)依賴指的是存在組合關(guān)鍵字中的某些字段決定非關(guān)鍵字段的情況),也即所有非關(guān)鍵字段都完全依賴于任意一組候選關(guān)鍵字,。 第三范式(3NF):在第二范式的基礎(chǔ)上,,數(shù)據(jù)表中如果不存在非關(guān)鍵字段對(duì)任一候選關(guān)鍵字段的傳遞函數(shù)依賴則符合第三范式。所謂傳遞函數(shù)依賴,,指的是如 果存在”A → B → C”的決定關(guān)系,,則C傳遞函數(shù)依賴于A。因此,,滿足第三范式的數(shù)據(jù)庫表應(yīng)該不存在如下依賴關(guān)系: 關(guān)鍵字段 → 非關(guān)鍵字段 x → 非關(guān)鍵字段y,。 8.E-R圖是什么?E-R圖也稱實(shí)體-聯(lián)系圖(Entity Relationship Diagram),,提供了表示實(shí)體類型,、屬性和聯(lián)系的方法,用來描述現(xiàn)實(shí)世界的概念模型,。 E-R方法是“實(shí)體-聯(lián)系方法”(Entity-Relationship Approach)的簡(jiǎn)稱,。它是描述現(xiàn)實(shí)世界概念結(jié)構(gòu)模型的有效方法,是表示概念模型的一種方式,,用矩形表示實(shí)體型,,矩形框內(nèi)寫明實(shí)體名;用橢圓表示實(shí)體的屬性,,并用無向邊將其與相應(yīng)的實(shí)體型連接起來,;用菱形表示實(shí)體型之間的聯(lián)系,在菱形框內(nèi)寫明聯(lián)系名,,并用無向邊分別與有關(guān)實(shí)體型連接起來,,同時(shí)在無向邊旁標(biāo)上聯(lián)系的類型(1:1,1:n或m:n),。 構(gòu)成在ER圖中有如下四個(gè)成分: 矩形框:表示實(shí)體,在框中記入實(shí)體名,。 菱形框:表示聯(lián)系,,在框中記入聯(lián)系名。 橢圓形框:表示實(shí)體或聯(lián)系的屬性,,將屬性名記入框中,。對(duì)于主屬性名,則在其名稱下劃一下劃線,。 連線:實(shí)體與屬性之間,;實(shí)體與聯(lián)系之間;聯(lián)系與屬性之間用直線相連,,并在直線上標(biāo)注聯(lián)系的類型,。(對(duì)于一對(duì)一聯(lián)系,要在兩個(gè)實(shí)體連線方向各寫1,; 對(duì)于一對(duì)多聯(lián)系,,要在一的一方寫1,多的一方寫N,;對(duì)于多對(duì)多關(guān)系,,則要在兩個(gè)實(shí)體連線方向各寫N,M。) 實(shí)體型(Entity):具有相同屬性的實(shí)體具有相同的特征和性質(zhì),,用實(shí)體名及其屬性名集合來抽象和刻畫同類實(shí)體;在E-R圖中用矩形表示,,矩形框內(nèi)寫明實(shí)體名;比如學(xué)生張三豐,、學(xué)生李尋歡都是實(shí)體,。如果是弱實(shí)體的話,在矩形外面再套實(shí)線矩形,。 屬性(Attribute):實(shí)體所具有的某一特性,,一個(gè)實(shí)體可由若干個(gè)屬性來刻畫。在E-R圖中用橢圓形表示,,并用無向邊將其與相應(yīng)的實(shí)體連接起來,;比如學(xué)生的姓名、學(xué)號(hào),、性別,、都是屬性。如果是多值屬性的話,,在橢圓形外面再套實(shí)線橢圓,,如果是派生屬性則用虛線橢圓表示。 聯(lián)系(Relationship):聯(lián)系也稱關(guān)系,,信息世界中反映實(shí)體內(nèi)部或?qū)嶓w之間的聯(lián)系。實(shí)體內(nèi)部的聯(lián)系通常是指組成實(shí)體的各屬性之間的聯(lián)系;實(shí)體之間的聯(lián)系通常是指不同實(shí)體集之間的聯(lián)系,。在E-R圖中用菱形表示,,菱形框內(nèi)寫明聯(lián)系名,并用無向邊分別與有關(guān)實(shí)體連接起來,,同時(shí)在無向邊旁標(biāo)上聯(lián)系的類型(1 : 1,,1 : n或m : n),比如老師給學(xué)生授課存在授課關(guān)系,,學(xué)生選課存在選課關(guān)系,。如果是弱實(shí)體的聯(lián)系則在菱形外面再套菱形。 聯(lián)系可分為以下 3 種類型: (1) 一對(duì)一聯(lián)系(1 ∶1) 例如,,一個(gè)班級(jí)有一個(gè)班長(zhǎng),,而每個(gè)班長(zhǎng)只在一個(gè)班級(jí)任職,則班級(jí)與班長(zhǎng)的聯(lián)系是一對(duì)一的,。 (2) 一對(duì)多聯(lián)系(1 ∶N) 例如,,某校教師與課程之間存在一對(duì)多的聯(lián)系“教”,即每位教師可以教多門課程,,但是每門課程只能由一位教師來教,。 (3) 多對(duì)多聯(lián)系(M ∶N) 例如,學(xué)生與課程間的聯(lián)系(“學(xué) ”)是多對(duì)多的,,即一個(gè)學(xué)生可以學(xué)多門課程,,而每門課程可以有多個(gè)學(xué)生來學(xué)。聯(lián)系也可能有屬性,。例如,,學(xué)生“ 學(xué)” 某門課程所取得的成績(jī),既不是學(xué)生的屬性也不是課程的屬性,。由于“ 成績(jī)” 既依賴于某名特定的學(xué)生又依賴于某門特定的課程,,所以它是學(xué)生與課程之間的聯(lián)系“ 學(xué)”的屬性。 作圖步驟⑴確定所有的實(shí)體集合 ⑵選擇實(shí)體集應(yīng)包含的屬性 ⑶確定實(shí)體集之間的聯(lián)系 ⑷確定實(shí)體集的關(guān)鍵字,,用下劃線在屬性上表明關(guān)鍵字的屬性組合 ⑸確定聯(lián)系的類型,,在用線將表示聯(lián)系的菱形框聯(lián)系到實(shí)體集時(shí),在線旁注明聯(lián)系的類型,。 實(shí)例:
參考3 參考4 9.處理重復(fù)記錄的常用操作(1)查找表中多余的重復(fù)記錄,,重復(fù)記錄是根據(jù)單個(gè)字段(column_name)來判斷。 select * from table_name where column_name in (select column_name from table_name group by column_name having count(column_name) > 1)
(2)刪除表中多余的重復(fù)記錄,,重復(fù)記錄是根據(jù)單個(gè)字段(column_name)來判斷,,只留有id最小的記錄。 delete from table_name where column_name in (select b.column_name from (select column_name from table_name group by column_name having count(column_name)>1)b);
(3)查找表中多余的重復(fù)記錄(多個(gè)字段),。 select * from table_name a where (a.column_name1,a.column_name2) in (select column_name1,column_name2 from vitae group by column_name1,column_name2 having count(*) > 1)
(4)刪除表中多余的重復(fù)記錄(多個(gè)字段),,只留有rowid最小的記錄 ,。 delete from table_name a where (a.column_name1,a.column_name2) in (select column_name1,column_name2 from table_name group by column_name1,column_name2 having count(*) > 1) and rowid not in (select min(rowid) from table_name group by column_name1,column_name2 having count(rowid)>1)
10.批處理MySQL 支持以批處理的方式執(zhí)行一批SQL語句,例如: create table test(id int,name varchar(20));
insert into test values(1,'watson');
batchfile.txt里包含下面的一些SQL 語句,,此文件在linux系統(tǒng)中的路徑/home/wming/batchfile.txt: insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
執(zhí)行上面的文件,,test 表在 MyZone 數(shù)據(jù)庫中: mysql -uroot -p -D MyZone < /home/wming/batchfile.txt
上面的例子通過批處理執(zhí)行插入語句,下面的例子是通過批處理執(zhí)行查詢語句: 此時(shí)的batchfile2.txt里含有query的信息: select * from test limit 200;
insert into test select * from test;
insert into test select * from test;
下面的mysql0716.out就記錄了 select * from test limit 200 查詢語句的結(jié)果集,。 mysql -uroot -p -D MyZone < /home/wming/batchfile2.txt >/home/wming/mysql0716.out
11.MyISAM與InnoDB的區(qū)別是什么,?1、存儲(chǔ)結(jié)構(gòu)MyISAM:每個(gè)MyISAM表在磁盤上存儲(chǔ)成三個(gè)文件,,文件的名字以表的名字開始,,擴(kuò)展名指出文件類型:.frm文件存儲(chǔ)表定義;數(shù)據(jù)文件的擴(kuò)展名為.MYD (MYData),;索引文件的擴(kuò)展名是.MYI (MYIndex),。 InnoDB:所有的表都保存在同一個(gè)數(shù)據(jù)文件中(也可能是多個(gè)文件,或者是獨(dú)立的表空間文件),,InnoDB表的大小只受限于操作系統(tǒng)文件的大小,,一般為2GB。 2,、存儲(chǔ)空間MyISAM:可被壓縮,,存儲(chǔ)空間較小。支持三種不同的存儲(chǔ)格式:靜態(tài)表(默認(rèn),,但是注意數(shù)據(jù)末尾不能有空格,,會(huì)被去掉)、動(dòng)態(tài)表,、壓縮表,。 InnoDB:需要更多的內(nèi)存和存儲(chǔ),它會(huì)在主內(nèi)存中建立其專用的緩沖池用于高速緩沖數(shù)據(jù)和索引,。 3,、可移植性、備份及恢復(fù)MyISAM:數(shù)據(jù)是以文件的形式存儲(chǔ),,所以在跨平臺(tái)的數(shù)據(jù)轉(zhuǎn)移中會(huì)很方便,。在備份和恢復(fù)時(shí)可單獨(dú)針對(duì)某個(gè)表進(jìn)行操作。 InnoDB:免費(fèi)的方案可以是拷貝數(shù)據(jù)文件,、備份 binlog,,或者用 mysqldump,在數(shù)據(jù)量達(dá)到幾十G的時(shí)候就相對(duì)痛苦了,。 4,、事務(wù)支持MyISAM:強(qiáng)調(diào)的是性能,每次查詢具有原子性,其執(zhí)行數(shù)度比InnoDB類型更快,,但是不提供事務(wù)支持,。 InnoDB:支持事務(wù),,外部鍵等高級(jí)數(shù)據(jù)庫功能。 具有事務(wù)(commit),、回滾(rollback)和崩潰修復(fù)能力(crash recovery capabilities)的事務(wù)安全(transaction-safe (ACID compliant))型表,。 這一點(diǎn)是非常重要。事務(wù)是一種高級(jí)的處理方式,,如在一些列增刪改中只要哪個(gè)出錯(cuò)還可以回滾還原,而MyISAM就不可以了,。 5,、AUTO_INCREMENTMyISAM:可以和其他字段一起建立聯(lián)合索引。引擎的自動(dòng)增長(zhǎng)列必須是索引,,如果是組合索引,,自動(dòng)增長(zhǎng)可以不是第一列,他可以根據(jù)前面幾列進(jìn)行排序后遞增,。 InnoDB: InnoDB中必須包含只有該字段的索引,。引擎的自動(dòng)增長(zhǎng)列必須是索引,如果是組合索引也必須是組合索引的第一列,。 6,、表鎖差異MyISAM:只支持表級(jí)鎖,用戶在操作myisam表時(shí),,select,,update,delete,,insert語句都會(huì)給表自動(dòng)加鎖,,如果加鎖以后的表滿足insert并發(fā)的情況下,可以在表的尾部插入新的數(shù)據(jù),。 InnoDB:支持事務(wù)和行級(jí)鎖,,是innodb的最大特色。行鎖大幅度提高了多用戶并發(fā)操作的性能,。但是InnoDB的行鎖,,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會(huì)鎖全表的,。 7,、 全文索引MyISAM:支持 FULLTEXT類型的全文索引。 InnoDB:不支持FULLTEXT類型的全文索引,,但是innodb可以使用sphinx插件支持全文索引,,并且效果更好。 8,、表主鍵MyISAM:允許沒有任何索引和主鍵的表存在,,索引都是保存行的地址,。 InnoDB:如果沒有設(shè)定主鍵或者非空唯一索引,就會(huì)自動(dòng)生成一個(gè)6字節(jié)的主鍵(用戶不可見),,數(shù)據(jù)是主索引的一部分,,附加索引保存的是主索引的值。 9,、 表的具體行數(shù)MyISAM:保存有表的總行數(shù),,如果select count() from table;會(huì)直接取出出該值。 InnoDB:沒有保存表的總行數(shù),,如果使用select count() from table,;就會(huì)遍歷整個(gè)表,消耗相當(dāng)大,,但是在加了wehre條件后,,myisam和innodb處理的方式都一樣。 10,、CURD操作MyISAM:如果執(zhí)行大量的SELECT,,MyISAM是更好的選擇。 InnoDB:如果你的數(shù)據(jù)執(zhí)行大量的INSERT或UPDATE,,出于性能方面的考慮,,應(yīng)該使用InnoDB表。DELETE 從性能上InnoDB更優(yōu),,但DELETE FROM table時(shí),,InnoDB不會(huì)重新建立表,而是一行一行的刪除,,在innodb上如果要清空保存有大量數(shù)據(jù)的表,,最好使用truncate table這個(gè)命令。 11,、 外鍵MyISAM:不支持 InnoDB:支持 通過上述的分析,,基本上可以考慮使用InnoDB來替代MyISAM引擎了,原因是InnoDB自身很多良好的特點(diǎn),,比如事務(wù)支持,、存儲(chǔ) 過程、視圖,、行級(jí)鎖定等等,,在并發(fā)很多的情況下,相信InnoDB的表現(xiàn)肯定要比MyISAM強(qiáng)很多,。另外,,任何一種表都不是萬能的,只用恰當(dāng)?shù)尼槍?duì)業(yè)務(wù)類型來選擇合適的表類型,才能最大的發(fā)揮MySQL的性能優(yōu)勢(shì),。如果不是很復(fù)雜的Web應(yīng)用,,非關(guān)鍵應(yīng)用,還是可以繼續(xù)考慮MyISAM的,,這個(gè)具體視情況而定,。 參考 12. 樂觀鎖 與 悲觀鎖數(shù)據(jù)庫管理系統(tǒng)(DBMS)中的并發(fā)控制的任務(wù)是確保在多個(gè)事務(wù)同時(shí)存取數(shù)據(jù)庫中同一數(shù)據(jù)時(shí)不破壞事務(wù)的隔離性和一致性以及數(shù)據(jù)庫的統(tǒng)一性。 樂觀并發(fā)控制(樂觀鎖)和悲觀并發(fā)控制(悲觀鎖)是并發(fā)控制采用的主要技術(shù)手段,。 無論是悲觀鎖還是樂觀鎖,,都是人們定義出來的概念,可以認(rèn)為是一種思想,。其實(shí)不僅僅是關(guān)系型數(shù)據(jù)庫系統(tǒng)中有樂觀鎖和悲觀鎖的概念,,像memcache、hibernate,、tair等都有類似的概念。 針對(duì)不同的業(yè)務(wù)場(chǎng)景,,應(yīng)該選用不同的并發(fā)控制方式,。所以,不要把樂觀并發(fā)控制和悲觀并發(fā)控制狹義的理解為僅在DBMS中存在的概念,,更不要把他們和數(shù)據(jù)庫中提供的鎖機(jī)制(行鎖,、表鎖、排他鎖,、共享鎖)混為一談,。其實(shí),在DBMS中,,悲觀鎖正是利用數(shù)據(jù)庫本身提供的鎖機(jī)制來實(shí)現(xiàn)的,。 悲觀鎖在關(guān)系數(shù)據(jù)庫管理系統(tǒng)里,悲觀并發(fā)控制(又名“悲觀鎖”,,Pessimistic Concurrency Control,,縮寫“PCC”)是一種并發(fā)控制的方法。它可以阻止一個(gè)事務(wù)以影響其他用戶的方式來修改數(shù)據(jù),。如果一個(gè)事務(wù)執(zhí)行的操作在某行數(shù)據(jù)上應(yīng)用了鎖,,那只有當(dāng)這個(gè)事務(wù)把鎖釋放,其他事務(wù)才能夠執(zhí)行與該鎖沖突的操作,。 悲觀并發(fā)控制主要用于數(shù)據(jù)爭(zhēng)用激烈的環(huán)境,,以及發(fā)生并發(fā)沖突時(shí)使用鎖保護(hù)數(shù)據(jù)的成本要低于回滾事務(wù)的成本的環(huán)境中。 悲觀鎖:正如其名,,它指的是對(duì)數(shù)據(jù)被外界(包括本系統(tǒng)當(dāng)前的其他事務(wù),,以及來自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度(悲觀),因此,,在整個(gè)數(shù)據(jù)處理過程中,,將數(shù)據(jù)處于鎖定狀態(tài),。 悲觀鎖的實(shí)現(xiàn),往往依靠數(shù)據(jù)庫提供的鎖機(jī)制 (也只有數(shù)據(jù)庫層提供的鎖機(jī)制才能真正保證數(shù)據(jù)訪問的排他性,,否則,,即使在本系統(tǒng)中實(shí)現(xiàn)了加鎖機(jī)制,也無法保證外部系統(tǒng)不會(huì)修改數(shù)據(jù)),。 悲觀鎖的流程: 1.在對(duì)某一記錄進(jìn)行修改前,,先嘗試為該記錄加上排他鎖(exclusive locking)。 2.如果加鎖失敗,,說明該記錄正在被修改,,那么當(dāng)前操作可能要等待或者拋出異常, 具體響應(yīng)方式由開發(fā)者根據(jù)實(shí)際情況決定,。 3.如果成功加鎖,,那么就可以對(duì)記錄做修改,事務(wù)完成后就會(huì)解鎖了,。 4.其間如果有其他事務(wù)要對(duì)該記錄做修改或加排他鎖,,都會(huì)等待該事務(wù)將該記錄解鎖或直接拋出異常。 MySQL InnoDB中使用悲觀鎖 注意:要使用悲觀鎖,,必須先關(guān)閉mysql數(shù)據(jù)庫的自動(dòng)提交功能,,因?yàn)镸ySQL默認(rèn)使用autocommit模式,也就是說,,當(dāng)你執(zhí)行一個(gè)更新操作后,,MySQL會(huì)立刻將結(jié)果進(jìn)行提交。 set autocommit=0;
//0.開始事務(wù)
begin;/begin work;/start transaction; (三者選一就可以)
//1.查詢出商品信息
select status from t_goods where id=1 for update;
//2.根據(jù)商品信息生成訂單
insert into t_orders (id,goods_id) values (null,1);
//3.修改商品status為2
update t_goods set status=2;
//4.提交事務(wù)
commit;/commit work;
上面的查詢語句中,,我們使用了select…for update的方式,,這樣就通過開啟排他鎖的方式實(shí)現(xiàn)了悲觀鎖。此時(shí)在t_goods表中,,id為1的 那條數(shù)據(jù)就被我們鎖定了,,其它事務(wù)必須等本次事務(wù)提交之后才能對(duì)該記錄進(jìn)行操作。這樣我們可以保證當(dāng)前的數(shù)據(jù)不會(huì)被其它事務(wù)修改,。 注意:上面提到,,使用select…for update會(huì)把數(shù)據(jù)給鎖住,不過我們需要注意一下鎖的級(jí)別,,MySQL InnoDB默認(rèn)為行級(jí)鎖,。行級(jí)鎖都是基于索引的,如果一條SQL語句沒有用到索引是不會(huì)使用行級(jí)鎖的,,會(huì)使用表級(jí)鎖把整張表鎖住,,這點(diǎn)需要注意。 優(yōu)點(diǎn)與不足: 優(yōu)點(diǎn):悲觀并發(fā)控制實(shí)際上是采用“先取鎖再訪問”的保守策略,為數(shù)據(jù)處理的安全性提供了保證,; 缺點(diǎn):在效率方面,,處理加鎖的機(jī)制會(huì)讓數(shù)據(jù)庫產(chǎn)生額外的開銷,同時(shí)會(huì)增加產(chǎn)生死鎖的機(jī)率,;另外,,在只讀型事務(wù)中由于不會(huì)產(chǎn)生沖突,也沒必要使用鎖,,這樣做只會(huì)增加系統(tǒng)負(fù)載,;還會(huì)降低并行性,一個(gè)事務(wù)如果鎖定了某行數(shù)據(jù),,其他事務(wù)就必須等待該事務(wù)處理完才可以處理那行數(shù) 樂觀鎖在關(guān)系數(shù)據(jù)庫管理系統(tǒng)里,,樂觀并發(fā)控制(又名“樂觀鎖”,Optimistic Concurrency Control,,縮寫“OCC”)是一種并發(fā)控制的方法,。它假設(shè)多用戶并發(fā)的事務(wù)在處理數(shù)據(jù)時(shí)不會(huì)彼此互相影響,各事務(wù)能夠在不產(chǎn)生鎖的情況下處理各自影響的那部分?jǐn)?shù)據(jù),。在提交數(shù)據(jù)更新之前,,每個(gè)事務(wù)會(huì)先檢查在該事務(wù)讀取數(shù)據(jù)后,有沒有其他事務(wù)對(duì)該數(shù)據(jù)做過修改,。如果其他事務(wù)更新過該數(shù)據(jù)的話,正在提交的事務(wù)會(huì)進(jìn)行回滾,。樂觀事務(wù)控制最早是由孔祥重(H.T.Kung)教授提出,。 樂觀鎖( Optimistic Locking )是相對(duì)悲觀鎖而言,樂觀鎖假設(shè)數(shù)據(jù)一般情況下不會(huì)造成沖突,,所以在事務(wù)對(duì)數(shù)據(jù)進(jìn)行提交更新的時(shí)候,,才會(huì)正式對(duì)數(shù)據(jù)的沖突與否進(jìn)行檢測(cè),如果發(fā)現(xiàn)沖突了,,則返回錯(cuò)誤信息,,讓用戶決定如何去做。 相對(duì)于悲觀鎖,,在對(duì)數(shù)據(jù)庫進(jìn)行處理的時(shí)候,,樂觀鎖并不會(huì)使用數(shù)據(jù)庫提供的鎖機(jī)制,一般用記錄數(shù)據(jù)版本的方式實(shí)現(xiàn)樂觀鎖,。 數(shù)據(jù)版本:為數(shù)據(jù)增加的一個(gè)版本標(biāo)識(shí),。當(dāng)讀取數(shù)據(jù)時(shí),將版本標(biāo)識(shí)的值一同讀出,,數(shù)據(jù)每更新一次,,便對(duì)版本標(biāo)識(shí)進(jìn)行一次更新。當(dāng)事務(wù)提交更新的時(shí)候,需要判斷數(shù)據(jù)庫表對(duì)應(yīng)記錄的當(dāng)前版本信息與第一次取出來的版本標(biāo)識(shí)是否一致,,如果數(shù)據(jù)庫表當(dāng)前版本號(hào)與第一次取出來的版本標(biāo)識(shí)值相等,,則予以更新,否則認(rèn)為是過期數(shù)據(jù),。 實(shí)現(xiàn)數(shù)據(jù)版本有兩種方式,,第一種是使用版本號(hào),第二種是使用時(shí)間戳,。 使用版本號(hào)實(shí)現(xiàn)樂觀鎖 使用版本號(hào)時(shí),,可以在數(shù)據(jù)初始化時(shí)指定一個(gè)版本號(hào),每次對(duì)數(shù)據(jù)的更新操作都對(duì)版本號(hào)執(zhí)行+1操作,。并判斷當(dāng)前版本號(hào)是不是該數(shù)據(jù)的最新的版本號(hào),。 1.查詢出商品信息
select (status,status,version) from t_goods where id=#{id}
2.根據(jù)商品信息生成訂單
3.修改商品status為2
update t_goods
set status=2,version=version+1
where id=#{id} and version=#{version};
樂觀并發(fā)控制假設(shè)事務(wù)之間的數(shù)據(jù)競(jìng)爭(zhēng)(data race)概率比較小,因此盡可能直接做下去,,直到提交的時(shí)候才去鎖定,,所以不會(huì)產(chǎn)生任何鎖和死鎖。但如果直接簡(jiǎn)單這么做,,還是有可能會(huì)遇到不可預(yù)期的結(jié)果,,例如兩個(gè)事務(wù)都讀取了數(shù)據(jù)庫的某一行,經(jīng)過修改以后寫回?cái)?shù)據(jù)庫,,這時(shí)就遇到了問題,。 13.左 右 連接 全連接 內(nèi)連接
|