久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長(zhǎng)資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      一文詳解MySql行級(jí)鎖和表級(jí)鎖

      MySql 行級(jí)鎖 表級(jí)鎖

      如何保證數(shù)據(jù)并發(fā)訪問(wèn)的一致性、有效性是所有數(shù)據(jù)庫(kù)必須解決的一個(gè)問(wèn)題,鎖沖突也是影響數(shù)據(jù)庫(kù)并發(fā)訪問(wèn)性能的一個(gè)重要因素。從這個(gè)角度來(lái)說(shuō),鎖對(duì)數(shù)據(jù)庫(kù)而言顯得尤其重要,也更加復(fù)雜。

      MySQL鎖概述

      相對(duì)其他數(shù)據(jù)庫(kù)而言,MySQL的鎖機(jī)制比較簡(jiǎn)單,其最顯著的特點(diǎn)是不同的存儲(chǔ)引擎支持不同的鎖機(jī)制。
      比如

      MyISAM和MEMORY存儲(chǔ)引擎采用的是表級(jí)鎖(table-level locking)。

      InnoDB存儲(chǔ)引擎既支持行級(jí)鎖(row-level locking),也支持表級(jí)鎖,但默認(rèn)情況下是采用行級(jí)鎖。

      MySQL這3種鎖的特性可大致歸納如下

      表級(jí)鎖:開(kāi)銷(xiāo)小,加鎖快;不會(huì)出現(xiàn)死鎖;鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)度最低。

      行級(jí)鎖:開(kāi)銷(xiāo)大,加鎖慢;會(huì)出現(xiàn)死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。

      頁(yè)面鎖:開(kāi)銷(xiāo)和加鎖時(shí)間界于表鎖和行鎖之間;會(huì)出現(xiàn)死鎖;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般。

      僅從鎖的角度來(lái)說(shuō):表級(jí)鎖更適合于以查詢?yōu)橹鳎挥猩倭堪此饕龡l件更新數(shù)據(jù)的應(yīng)用,如Web應(yīng)用;而行級(jí)鎖則更適合于有大量按索引條件并發(fā)更新少量不同數(shù)據(jù),同時(shí)又有并發(fā)查詢的應(yīng)用,如一些在線事務(wù)處理(OLTP)系統(tǒng)。下面幾節(jié)我們重點(diǎn)介紹MySQL表鎖和 InnoDB行鎖的問(wèn)題。

      MyISAM表鎖

      MyISAM存儲(chǔ)引擎只支持表鎖,這也是MySQL開(kāi)始幾個(gè)版本中唯一支持的鎖類(lèi)型。隨著應(yīng)用對(duì)事務(wù)完整性和并發(fā)性要求的不斷提高,MySQL才開(kāi)始開(kāi)發(fā)基于事務(wù)的存儲(chǔ)引擎,后來(lái)慢慢出現(xiàn)了支持頁(yè)鎖的BDB存儲(chǔ)引擎和支持行鎖的InnoDB存儲(chǔ)引擎(實(shí)際 InnoDB是單獨(dú)的一個(gè)公司,現(xiàn)在已經(jīng)被Oracle公司收購(gòu))。但是MyISAM的表鎖依然是使用最為廣泛的鎖類(lèi)型。本節(jié)將詳細(xì)介紹MyISAM表鎖的使用。

      查詢表級(jí)鎖爭(zhēng)用情況

      可以通過(guò)檢查table_locks_waited和table_locks_immediate狀態(tài)變量來(lái)分析系統(tǒng)上的表鎖定爭(zhēng)奪:

      mysql> show status like 'table%';

      | Variable_name | Value |

      | Table_locks_immediate | 2979 |

      | Table_locks_waited | 0 |

      2 rows in set (0.00 sec))

      如果Table_locks_waited的值比較高,則說(shuō)明存在著較嚴(yán)重的表級(jí)鎖爭(zhēng)用情況。

      MySQL表級(jí)鎖的鎖模式

      MySQL的表級(jí)鎖有兩種模式:表共享讀鎖(Table Read Lock)和表獨(dú)占寫(xiě)鎖(Table Write Lock)。

      MyISAM表的讀操作,不會(huì)阻塞其他用戶對(duì)同一表的讀請(qǐng)求,但會(huì)阻塞對(duì)同一表的寫(xiě)請(qǐng)求;
      MyISAM表的寫(xiě)操作,則會(huì)阻塞其他用戶對(duì)同一表的讀和寫(xiě)操作;
      MyISAM表的讀操作與寫(xiě)操作之間,以及寫(xiě)操作之間是串行的;
      當(dāng)一個(gè)線程獲得對(duì)一個(gè)表的寫(xiě)鎖后,只有持有鎖的線程可以對(duì)表進(jìn)行更新操作。其他線程的讀、寫(xiě)操作都會(huì)等待,直到鎖被釋放為止。

      獲得表film_text的WRITE鎖定

      mysql> lock table film_text write;

      Query OK, 0 rows affected (0.00 sec)

      當(dāng)前session對(duì)鎖定表的查詢、更新、插入操作都可以執(zhí)行:

      mysql> select film_id,title from film_text where film_id = 1001;

      | film_id | title |

      | 1001 | Update Test |

      1 row in set (0.00 sec)

      mysql> insert into film_text (film_id,title) values(1003,'Test');

      Query OK, 1 row affected (0.00 sec)

      mysql> update film_text set title = 'Test' where film_id = 1001;

      Query OK, 1 row affected (0.00 sec)

      Rows matched: 1 Changed: 1 Warnings: 0

      其他session對(duì)鎖定表的查詢被阻塞,需要等待鎖被釋放:

      mysql> select film_id,title from film_text where film_id = 1001;

      等待

      釋放鎖:

      mysql> unlock tables;

      Query OK, 0 rows affected (0.00 sec)

      等待

      Session2獲得鎖,查詢返回:

      mysql> select film_id,title from film_text where film_id = 1001;

      | film_id | title |

      | 1001 | Test |

      1 row in set (57.59 sec)

      如何加表鎖?

      MyISAM在執(zhí)行查詢語(yǔ)句(SELECT)前,會(huì)自動(dòng)給涉及的所有表加讀鎖,在執(zhí)行更新操作(UPDATE、DELETE、INSERT等)前,會(huì)自動(dòng)給涉及的表加寫(xiě)鎖,這個(gè)過(guò)程并不需要用戶干預(yù),因此,用戶一般不需要直接用LOCK TABLE命令給MyISAM表顯式加鎖。在示例中,顯式加鎖基本上都是為了方便而已,并非必須如此。

      給MyISAM表顯示加鎖,一般是為了在一定程度模擬事務(wù)操作,實(shí)現(xiàn)對(duì)某一時(shí)間點(diǎn)多個(gè)表的一致性讀取。例如,有一個(gè)訂單表orders,其中記錄有各訂單的總金額total,同時(shí)還有一個(gè)訂單明細(xì)表order_detail,其中記錄有各訂單每一產(chǎn)品的金額小計(jì) subtotal,假設(shè)我們需要檢查這兩個(gè)表的金額合計(jì)是否相符,可能就需要執(zhí)行如下兩條SQL:

      Select sum(total) from orders;

      Select sum(subtotal) from order_detail;

      這時(shí),如果不先給兩個(gè)表加鎖,就可能產(chǎn)生錯(cuò)誤的結(jié)果,因?yàn)榈谝粭l語(yǔ)句執(zhí)行過(guò)程中,order_detail表可能已經(jīng)發(fā)生了改變。因此,正確的方法應(yīng)該是:

      Lock tables orders read local, order_detail read local;

      Select sum(total) from orders;

      Select sum(subtotal) from order_detail;

      Unlock tables;

      要特別說(shuō)明以下兩點(diǎn)內(nèi)容。

      上面的例子在LOCK TABLES時(shí)加了“l(fā)ocal”選項(xiàng),其作用就是在滿足MyISAM表并發(fā)插入條件的情況下,允許其他用戶在表尾并發(fā)插入記錄,有關(guān)MyISAM表的并發(fā)插入問(wèn)題,后面還會(huì)進(jìn)一步介紹。

      在用LOCK TABLES給表顯式加表鎖時(shí),必須同時(shí)取得所有涉及到表的鎖,并且MySQL不支持鎖升級(jí)。也就是說(shuō),在執(zhí)行LOCK TABLES后,只能訪問(wèn)顯式加鎖的這些表,不能訪問(wèn)未加鎖的表;同時(shí),如果加的是讀鎖,那么只能執(zhí)行查詢操作,而不能執(zhí)行更新操作。其實(shí),在自動(dòng)加鎖的情況下也基本如此,MyISAM總是一次獲得SQL語(yǔ)句所需要的全部鎖。這也正是MyISAM表不會(huì)出現(xiàn)死鎖(Deadlock Free)的原因。

      一個(gè)session使用LOCK TABLE命令給表film_text加了讀鎖,這個(gè)session可以查詢鎖定表中的記錄,但更新或訪問(wèn)其他表都會(huì)提示錯(cuò)誤;同時(shí),另外一個(gè)session可以查詢表中的記錄,但更新就會(huì)出現(xiàn)鎖等待。

      當(dāng)使用LOCK TABLES時(shí),不僅需要一次鎖定用到的所有表,而且,同一個(gè)表在SQL語(yǔ)句中出現(xiàn)多少次,就要通過(guò)與SQL語(yǔ)句中相同的別名鎖定多少次,否則也會(huì)出錯(cuò)!

      舉例說(shuō)明如下。

      (1)對(duì)actor表獲得讀鎖:

      mysql> lock table actor read;

      Query OK, 0 rows affected (0.00 sec)

      (2)但是通過(guò)別名訪問(wèn)會(huì)提示錯(cuò)誤:

      mysql> select a.first_name,a.last_name,b.first_name,b.last_name from actor a,actor b where a.first_name = b.first_name and a.first_name = 'Lisa' and a.last_name = 'Tom' and a.last_name <> b.last_name;

      ERROR 1100 (HY000): Table 'a' was not locked with LOCK TABLES

      (3)需要對(duì)別名分別鎖定:

      mysql> lock table actor as a read,actor as b read;

      Query OK, 0 rows affected (0.00 sec)

      (4)按照別名的查詢可以正確執(zhí)行:

      mysql> select a.first_name,a.last_name,b.first_name,b.last_name from actor a,actor b where a.first_name = b.first_name and a.first_name = 'Lisa' and a.last_name = 'Tom' and a.last_name <> b.last_name;

      | first_name | last_name | first_name | last_name |

      | Lisa | Tom | LISA | MONROE |

      1 row in set (0.00 sec)

      并發(fā)插入(Concurrent Inserts)

      上文提到過(guò)MyISAM表的讀和寫(xiě)是串行的,但這是就總體而言的。在一定條件下,MyISAM表也支持查詢和插入操作的并發(fā)進(jìn)行。

      MyISAM存儲(chǔ)引擎有一個(gè)系統(tǒng)變量concurrent_insert,專(zhuān)門(mén)用以控制其并發(fā)插入的行為,其值分別可以為0、1或2。

      當(dāng)concurrent_insert設(shè)置為0時(shí),不允許并發(fā)插入。

      當(dāng)concurrent_insert設(shè)置為1時(shí),如果MyISAM表中沒(méi)有空洞(即表的中間沒(méi)有被刪除的行),MyISAM允許在一個(gè)進(jìn)程讀表的同時(shí),另一個(gè)進(jìn)程從表尾插入記錄。這也是MySQL的默認(rèn)設(shè)置。

      當(dāng)concurrent_insert設(shè)置為2時(shí),無(wú)論MyISAM表中有沒(méi)有空洞,都允許在表尾并發(fā)插入記錄。

      可以利用MyISAM存儲(chǔ)引擎的并發(fā)插入特性,來(lái)解決應(yīng)用中對(duì)同一表查詢和插入的鎖爭(zhēng)用。例如,將concurrent_insert系統(tǒng)變量設(shè)為2,總是允許并發(fā)插入;同時(shí),通過(guò)定期在系統(tǒng)空閑時(shí)段執(zhí)行 OPTIMIZE TABLE語(yǔ)句來(lái)整理空間碎片,收回因刪除記錄而產(chǎn)生的中間空洞。有關(guān)OPTIMIZE TABLE語(yǔ)句的詳細(xì)介紹,可以參見(jiàn)第18章中“兩個(gè)簡(jiǎn)單實(shí)用的優(yōu)化方法”一節(jié)的內(nèi)容。

      MyISAM的鎖調(diào)度

      前面講過(guò),MyISAM存儲(chǔ)引擎的讀鎖和寫(xiě)鎖是互斥的,讀寫(xiě)操作是串行的。那么,一個(gè)進(jìn)程請(qǐng)求某個(gè) MyISAM表的讀鎖,同時(shí)另一個(gè)進(jìn)程也請(qǐng)求同一表的寫(xiě)鎖,MySQL如何處理呢?答案是寫(xiě)進(jìn)程先獲得鎖。不僅如此,即使讀請(qǐng)求先到鎖等待隊(duì)列,寫(xiě)請(qǐng)求后到,寫(xiě)鎖也會(huì)插到讀鎖請(qǐng)求之前!這是因?yàn)镸ySQL認(rèn)為寫(xiě)請(qǐng)求一般比讀請(qǐng)求要重要。這也正是MyISAM表不太適合于有大量更新操作和查詢操作應(yīng)用的原因,因?yàn)?,大量的更新操作?huì)造成查詢操作很難獲得讀鎖,從而可能永遠(yuǎn)阻塞。這種情況有時(shí)可能會(huì)變得非常糟糕!幸好我們可以通過(guò)一些設(shè)置來(lái)調(diào)節(jié)MyISAM 的調(diào)度行為。

      通過(guò)指定啟動(dòng)參數(shù)low-priority-updates,使MyISAM引擎默認(rèn)給予讀請(qǐng)求以優(yōu)先的權(quán)利。

      通過(guò)執(zhí)行命令SET LOW_PRIORITY_UPDATES=1,使該連接發(fā)出的更新請(qǐng)求優(yōu)先級(jí)降低。

      通過(guò)指定INSERT、UPDATE、DELETE語(yǔ)句的LOW_PRIORITY屬性,降低該語(yǔ)句的優(yōu)先級(jí)。

      雖然上面3種方法都是要么更新優(yōu)先,要么查詢優(yōu)先的方法,但還是可以用其來(lái)解決查詢相對(duì)重要的應(yīng)用(如用戶登錄系統(tǒng))中,讀鎖等待嚴(yán)重的問(wèn)題。

      另外,MySQL也提供了一種折中的辦法來(lái)調(diào)節(jié)讀寫(xiě)沖突,即給系統(tǒng)參數(shù)max_write_lock_count設(shè)置一個(gè)合適的值,當(dāng)一個(gè)表的讀鎖達(dá)到這個(gè)值后,MySQL就暫時(shí)將寫(xiě)請(qǐng)求的優(yōu)先級(jí)降低,給讀進(jìn)程一定獲得鎖的機(jī)會(huì)。

      上面已經(jīng)討論了寫(xiě)優(yōu)先調(diào)度機(jī)制帶來(lái)的問(wèn)題和解決辦法。這里還要強(qiáng)調(diào)一點(diǎn):一些需要長(zhǎng)時(shí)間運(yùn)行的查詢操作,也會(huì)使寫(xiě)進(jìn)程“餓死”!因此,應(yīng)用中應(yīng)盡量避免出現(xiàn)長(zhǎng)時(shí)間運(yùn)行的查詢操作,不要總想用一條SELECT語(yǔ)句來(lái)解決問(wèn)題,因?yàn)檫@種看似巧妙的SQL語(yǔ)句,往往比較復(fù)雜,執(zhí)行時(shí)間較長(zhǎng),在可能的情況下可以通過(guò)使用中間表等措施對(duì)SQL語(yǔ)句做一定的“分解”,使每一步查詢都能在較短時(shí)間完成,從而減少鎖沖突。如果復(fù)雜查詢不可避免,應(yīng)盡量安排在數(shù)據(jù)庫(kù)空閑時(shí)段執(zhí)行,比如一些定期統(tǒng)計(jì)可以安排在夜間執(zhí)行。

      InnoDB鎖

      InnoDB與MyISAM的最大不同有兩點(diǎn):一是支持事務(wù)(TRANSACTION);二是采用了行級(jí)鎖。行級(jí)鎖與表級(jí)鎖本來(lái)就有許多不同之處,另外,事務(wù)的引入也帶來(lái)了一些新問(wèn)題。下面我們先介紹一點(diǎn)背景知識(shí),然后詳細(xì)討論InnoDB的鎖問(wèn)題。

      1.事務(wù)(Transaction)及其ACID屬性

      事務(wù)是由一組SQL語(yǔ)句組成的邏輯處理單元,事務(wù)具有以下4個(gè)屬性,通常簡(jiǎn)稱為事務(wù)的ACID屬性。

      (Atomicity)原子性:事務(wù)是一個(gè)原子操作單元,其對(duì)數(shù)據(jù)的修改,要么全都執(zhí)行,要么全都不執(zhí)行。

      (Consistent)一致性:在事務(wù)開(kāi)始和完成時(shí),數(shù)據(jù)都必須保持一致?tīng)顟B(tài)。這意味著所有相關(guān)的數(shù)據(jù)規(guī)則都必須應(yīng)用于事務(wù)的修改,以保持?jǐn)?shù)據(jù)的完整性;事務(wù)結(jié)束時(shí),所有的內(nèi)部數(shù)據(jù)結(jié)構(gòu)(如B樹(shù)索引或雙向鏈表)也都必須是正確的。

      (Isolation)隔離性:數(shù)據(jù)庫(kù)系統(tǒng)提供一定的隔離機(jī)制,保證事務(wù)在不受外部并發(fā)操作影響的“獨(dú)立”環(huán)境執(zhí)行。這意味著事務(wù)處理過(guò)程中的中間狀態(tài)對(duì)外部是不可見(jiàn)的,反之亦然。

      (Durable)持久性:事務(wù)完成之后,它對(duì)于數(shù)據(jù)的修改是永久性的,即使出現(xiàn)系統(tǒng)故障也能夠保持。

      銀行轉(zhuǎn)帳就是事務(wù)的一個(gè)典型例子。

      2.并發(fā)事務(wù)處理帶來(lái)的問(wèn)題

      相對(duì)于串行處理來(lái)說(shuō),并發(fā)事務(wù)處理能大大增加數(shù)據(jù)庫(kù)資源的利用率,提高數(shù)據(jù)庫(kù)系統(tǒng)的事務(wù)吞吐量,從而可以支持

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)