MySQL 4.1.0 中文參考手冊 --- 6.7 MySQL 事務與鎖定命令 (轉)

gugu99發表於2008-01-27
MySQL 4.1.0 中文參考手冊 --- 6.7 MySQL 事務與鎖定命令 (轉)[@more@] 4.1.0 中文參考手冊"> words" content="MySQL,4.1.0,Shuixin13,MySQL 4.1.0,中文,中文參考手冊,犬犬(心帆)"> CSS rel=STYLESHEET>

MySQL Reference Manual for version 4.1.0-alpha.


6.7 MySQL 事務與鎖定命令

6.7.1 BEGIN/COMMIT/ROLLBACK 句法

預設的,MySQL 執行在 autocommit 。這就意味著,當你完一個時,MySQL 將立刻將更新到上。

如果你使用事務表 (例如 InnoBDB),透過下面的命令,你可以設定 MySQL 為非 autocommit 模式:

SET AUTOCOMMIT=0


在此之後,你必須使用 COMMIT 來儲存你的更改到磁碟上,或者使用 ROLLBACK ,如果你希望忽略從你的事務開始所做的更改。

如果你希望為一系列語句從 AUTOCOMMIT 模式轉換,你可以使用 START TRANSACTIONBEGINBEGIN WORK 語句:

START TRANSACTION; @A:=SUM(salary) FROM table1 WHERE type=1; UPDATE table2 SET summmary=@A WHERE type=1; COMMIT;


START TRANSACTION 在 MySQL 4.0.11 中被加入;這是被推薦的開始一個特別(ad-hoc)事務的方式,因為這是 ANSI SQL 句法。

注意,如果你使用的是一個非事務安全表,更改會立刻被儲存,不受 autocommit 模式狀態的。

當你更新了一個非事務表後,如果你執行一個 ROLLBACK,你將得到一個錯誤 (ER_WARNING_NOT_COMPLETE_ROLLBACK) 作為一個警告。所有事務安全表將被恢復,但是非事務安全表將不會改變。

如果你使用 START TRANSACTIONSET AUTOCOMMIT=0,你應該使用 MySQL 二進位制日誌做以代替老的更新日誌。事務處理被以一個大塊形式儲存在二進位制日誌中,在 COMMIT 上面,為了保護回滾的事務,而不是被儲存的。檢視章節 。如果您使用起動事務處理或集AUTOCOMMIT=0 ,您應該使用MySQL 二進位制日誌為備份代替更舊的更新日誌。 事務處理儲存在二進位制登入一大塊,做,保證, 滾的事務處理不儲存。 參見部分4 。9.4 二進位制日誌。

下列命令自動的結束一個事務 (就好像你在執行這個命令之前,做了一個 COMMIT):

命令 命令 命令 ALTER TABLE BEGIN CREATE INDEX DROP DATABASE DROP TABLE RENAME TABLE TRUNCATE    

你可以使用 SET TRANSACTION ISOLATION LEVEL ... 改變事務的隔離級。檢視章節 。

6.7.2 LOCK TABLES/UNLOCK TABLES 句法

LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} [, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} ...] ... UNLOCK TABLES


LOCK TABLES 為當前執行緒鎖定表。UNLOCK TABLES 釋放當前執行緒擁有的所有鎖定。當執行緒發出另一個 LOCK TABLES,或當與的連線被關閉時,被當前執行緒鎖定的所有表將被自動地解鎖。

為了在 MySQL 4.0.2 使用 LOCK TABLES ,你必須擁有一個全域性的 LOCK TABLES 和一個在相關表上的 SELECT 許可權。在 MySQL 3.23 中,你對該表需要有 SELECTinsertDELETEUPDATE 許可權。

使用 LOCK TABLES 的主要原因是,仿效事務處理或在更新表時得到更快的速度。此後會有更詳細的描述。

如果一個執行緒在一個表上得到一個 READ 鎖,該執行緒 (和所有其它執行緒) 只能從表中讀取。如果一個執行緒在一個表上得到一個 WRITE 鎖,那麼只有擁有這個鎖的執行緒可以從表中讀取和寫表。其它的執行緒被阻塞。

READ LOCALREAD 之間的不同就在於,當鎖被載入時,READ LOCAL 允許非衝突(non-conflicting) INSERT 語句執行。如果當你載入著鎖時從 MySQL 外部操作,這將仍不能被使用。

當你使用 LOCK TABLES 是地,你必須鎖定所有你將使用的表,並且必須使用與你的查詢中將使用的別名相同!如果你在一個查詢中多次使用一個表(用別名),你必須為每一個別名獲得一個鎖。

WRITE 鎖透過比 READ 鎖有更高的許可權,以確保更新被儘快地處理。這就意味著,如果一個執行緒獲得一個 READ 鎖,而同時另外一個執行緒請求一個 WRITE 鎖,併發的 READ 鎖請求將等待直到 WRITE 執行緒得到了鎖並釋放了它。你可以使用 LOW_PRIORITY WRITE 鎖,當該執行緒在等待 WRITE 鎖時,它將允許其它的執行緒獲得 READ 鎖。 你應該只使用 LOW_PRIORITY WRITE 鎖,如果你確信這將是最後一次,當沒有執行緒將擁有 READ 鎖。

LOCK TABLES 工作如下:

  1. 以內部定義的次序排序所有被鎖定的表 (從立場說,該次序是不明確的)。
  2. 如果一個表被以一個讀鎖和一個寫鎖鎖定,將寫鎖放在讀鎖之前。
  3. 一次只鎖定一個表,只到執行緒得到所有的鎖定。

這個方案是為了確保,表鎖定死鎖釋放。 對於這個模式你仍然有些其它事情需要知道:

如果你對一個表使用一個 LOW_PRIORITY WRITE 鎖定,這就意味著,MySQL 將等待這個鎖,直到沒有執行緒請求一個 READ 鎖。當執行緒得到了 WRITE 鎖,並等待獲得鎖定表列表中的下一個表的鎖定時,其它所有的執行緒將等待 WRITE 鎖被釋放。如果這在你的應用中會引起一個嚴重的問題,你應該考慮將你的某些錶轉換為事務安全表。

你可以使用 KILL 安全地殺死一個正在表鎖定的執行緒。檢視章節 。

注意,你不應該 鎖定你正在對其使用 INSERT DELAYED 的表。這是因為,在這種情況下,INSERT 是透過單獨的執行緒完成的。

通常,你不需要鎖定任何表,因為所有單 UPDATE 語句都是原子的;其它的執行緒無法干擾當前執行的 SQL 語句。當你無論如何希望鎖定表時,這裡有一些情況:

  • 如果你在一束表上執行許多操作,鎖定你將要使用的表,這會更快一些。當然有不利的方面,其它執行緒將不能更新一個 READ 鎖的表,並且沒有其它執行緒要以讀取一個 WRITE 鎖的表。在 LOCK TABLES 下,某些事執行得更快一些的原因是,MySQL 將不會轉儲清除被鎖定表鍵高速緩衝,直到 UNLOCK TABLES 被 (通常鍵高速緩衝在每個 SQL 語句後都會被轉儲清除)。這將加速在 MyISAM 表上的插入、更新、刪除。

  • 如果你在 MySQL 中正在使用一個不支援事務的儲存引擎,如果你希望能確保沒有其它的執行緒會出現在一個 SELECT 和 一個 UPDATE 之間,你必須使用 LOCK TABLES 。下面的示例顯示為了安全地執行,這裡需要LOCK TABLES

    mysql> LOCK TABLES trans READ, customer WRITE; mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id; mysql> UPDATE customer SET total_value=sum_from_previous_statement -> WHERE customer_id=some_id; mysql> UNLOCK TABLES;

    不使用 LOCK TABLES,將可能發生在 SELECTUPDATE 語句執行期間有另外一個執行緒可能在 trans 表中插入一行新記錄。 

透過使用遞增更新 (UPDATE customer SET value=value+new_value) 或 LAST_INSERT_ID() ,你可以在很多情況下避免使用 LOCK TABLES

你也可以使用使用者級鎖定函式 GET_LOCK()RELEASE_LOCK() 解決一些情況,這些鎖被儲存在伺服器上的一個雜湊表中,並以 pthread_mutex_lock()pthread_mutex_unlock() 實現以獲得高速度。檢視章節 。

檢視章節 ,以獲取關於鎖定方案的更多資訊。

你可以使用 FLUSH TABLES WITH READ LOCK 命令以讀鎖鎖定所有資料庫中的所有表。檢視章節 。如果你有一個可以及時建立檔案快照的檔案,例如 Veritas,這將是得到備份的非常方便方式。

注意:LOCK TABLES 不是事務安全的,在嘗試鎖定一個表之前,將自動地提交所有的活動事務。

6.7.3 SET TRANSACTION 句法

SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }


設定全域性的、整個會話或下一個事務的事務隔離級。

預設行為是設定下一個(未啟動的)事務的隔離級。如果你使用 GLOBAL 關鍵詞,語句為所有在那個點上建立的新連線設定預設的全域性事務隔離級。為了這樣做,你需要有 SUPER 許可權。使用 SESSION 關鍵詞為當前連線所有將來執行的事務設定預設的事務隔離級。

你可以使用 --transaction-isolation=...mysqld 設定預設的全域性隔離級。檢視章節 。

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-998562/,如需轉載,請註明出處,否則將追究法律責任。

相關文章