MySQL心得10-2-鎖定 1. 偽事務 前面已經介紹了InnoDB和BDB表環境中的事務,這是MySQL天生支持的ACID規則事務的僅有的表類型。舊的MySQL表類型,在許多安裝MySQL的環境中仍然在使用,它們不支持事務,但是MySQL仍然可以使用戶通過表鎖定來實現原始形式的事務。在此介紹偽事務,提供對非事務表執行安全事務的一些基本指標。 www.2cto.com 2. 鎖定與解鎖 因為MyISAM(以及其他舊的MySQL表)不支持InnoDB格式的COMMIT和ROLLBACK語法,所以每次數據庫的變化都被立即保存在磁盤上。像前面所講的那樣,在單用戶的環境中,這沒有問題,但是在多用戶的環境中,就會導致很多問題。因為它不能創建事務來使用戶所做的變化隔離於其他用戶所做的變化。在這種情況下,唯一一種保證不同用戶能夠看到一致數據的方法是強制方法:在變化的過程中阻止其他用戶訪問正在變化的表(通過鎖定表),只在變化完成後才允許訪問。 前面已經討論了InnoDB和BDB表,它們支持行級和頁級的鎖定來保證同時執行的事務的安全。不過,MyISAM表類型不支持這些鎖定機制。所以,要明確地設置表鎖定,以避免同時存在的事務互相侵犯空間。 MySQL提供了LOCK TABLES語句來鎖定當前線程的表,語法格式如下:LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} 說明: 表鎖定支持以下類型的鎖定。 ● READ:讀鎖定,確保用戶可以讀取表,但是不能修改表。加上LOCAL後允許在表鎖定後用戶可以進行非沖突的INSERT語句,只適用於MyISAM類型的表。 ● WRITE:寫鎖定,只有鎖定該表的用戶可以修改表,其他用戶無法訪問該表。加上LOW_PRIORITY後允許其他用戶讀取表,但是不能修改它。 當用戶在一次查詢中多次使用到一個鎖定了的表,需要在鎖定表的時候用AS子句為表定義一個別名,alias表示表的別名。 www.2cto.com 3. 表鎖定只用於防止其他客戶端進行不正當地讀取和寫入。 保持鎖定(即使是讀取鎖定)的客戶端可以進行表層級的操作,如DROP TABLE。 在對一個事務表使用表鎖定的時候需要注意以下幾點: (1)在鎖定表時會隱式地提交所有事務,在開始一個事務時,如START TRANSACTION,會隱式解開所有表鎖定。 (2)在事務表中,系統變量AUTOCOMMIT值必須設為0。否則,MySQL會在調用LOCK TABLES之後立刻釋放表鎖定,並且很容易形成死鎖。 例: 在XS表上設置一個只讀鎖定:LOCK TABLES XS READ; 說明:LOCK TABLES還可以同時鎖定多個表,中間用逗號隔開即可。 例: 在KC表上設置一個寫鎖定: LOCK TABLES KC WRITE; 在鎖定表以後,可以使用UNLOCK TABLES命令解除鎖定。語法格式為: UNLOCK TABLES; UNLOCK TABLES命令不需要指出解除鎖定的表的名字。MySQL會自動對前面通過LOCK TABLES鎖定的所有表解除鎖定。當用戶發布另一個LOCK TABLES時,或當與服務器的連接關閉時,所有由當前用戶鎖定的表被隱式地解鎖。 4.當用戶對數據庫並發訪問時,為了確保事務完整性和數據庫一致性,需要使用鎖定,它是實現數據庫並發控制的主要手段。鎖定可以防止用戶讀取正在由其他用戶更改的數據,並可以防止多個用戶同時更改相同數據。如果不使用鎖定,則數據庫中的數據可能在邏輯上不正確,並且對數據的查詢可能會產生意想不到的結果。具體地說,鎖定可以防止丟失更新、髒讀、不可重復讀和幻讀。 丟失更新(lost update),指當兩個或多個事務選擇同一行,然後基於最初選定的值更新該行時,由於每個事務都不知道其他事務的存在,因此最後的更新將重寫由其他事務所做的更新,這將導致數據丟失。 www.2cto.com 髒讀(dirty read)指一個事務正在訪問數據,而其他事務正在更新該數據,但尚未提交,此時就會發生髒讀問題,即第一個事務所讀取的數據是“髒”(不正確)數據,它可能會引起錯誤。 當一個事務多次訪問同一行而且每次讀取不同的數據時,會發生不可重復讀(unrepeatable read)問題。不可重復讀與髒讀有相似之處,因為該事務也是正在讀取其他事務正在更改的數據。當一個事務訪問數據時,另外的事務也訪問該數據並對其進行修改,因此就發生了由於第二個事務對數據的修改而導致第一個事務兩次讀到的數據不一樣的情況,這就是不可重復讀。 當一個事務對某行執行插入或刪除操作,而該行屬於某個事務正在讀取的行的范圍時,會發生幻讀(phantom read)問題。事務第一次讀的行范圍顯示出其中一行已不復存在於第二次讀或後續讀中,因為該行已被其他事務刪除。同樣,由於其他事務的插入操作,事務的第二次讀或後續讀顯示有一行已不存在於原始讀中。 作者 tianyazaiheruan