mysqldump備份數據庫時出現when using LOCK TABLES的提示

      今天在備份一位客戶的mysql數據庫的時候,使用mysqldump命令備份,出現when using LOCK TABLES的提示。如果對mysql中的用戶的權限進行過詳細設置的話,會知道用戶可以被分配LOCK TABLES和UNLOCK TABLES兩個權限,使該用戶在對該用戶的表進行讀寫鎖設定

   遇到該問題,解決方案如下:

   在執行備份的時候,將命令中添加 --skip-lock-tables,即命令如下:

  mysqldump -u 用戶名 -p 用戶密碼 --skip-lock-tables -R test > D:\test_1120.dmp


   下面是對事務表使用LOCK TABLES的說明:

      在嘗試鎖定表之前,LOCK TABLES不是事務安全型的,會隱含地提交所有活性事務。同時,開始一項事務(例如,使用START TRANSACTION),會隱含地執行UNLOCK TABLES

       對事務表(如InnoDB)使用LOCK TABLES的正確方法是,設置AUTOCOMMIT=0並且不能調用UNLOCK TABLES,直到您明確地提交事務爲止。當您調用LOCK TABLES時,InnoDB會內部地取其自己的表鎖定,MySQL取其自己的表鎖定。InnoDB在下一個提交時釋放其表鎖定,但是,對於MySQL,要釋放表鎖定,您必須調用UNLOCK TABLES。您不應該讓AUTOCOMMIT=1,因爲那樣的話,InnoDB會在調用LOCK TABLES之後立刻釋放表鎖定,並且很容易形成死鎖定。注意,如果AUTOCOMMIT=1,我們根本不能獲取InnoDB表鎖定,這樣就可以幫助舊的應用軟件避免不必要的死鎖定。

      ROLLBACK不會釋放MySQL的非事務表鎖定。

       要使用LOCK TABLES,您必須擁有相關表的LOCK TABLES權限和SELECT權限。
       使用LOCK TABLES的主要原因是仿效事務,或在更新表時加快速度。這將在後面進行更詳細的解釋。
如果一個線程獲得對一個表地READ鎖定,該線程(和所有其它線程)只能從該表中讀取。如果一個線程獲得對一個表的WRITE鎖定,只有保持鎖定的線程可以對錶進行寫入。其它的線程被阻止,直到鎖定被釋放時爲止。

READ LOCAL和READ之間的區別是,READ LOCAL允許在鎖定被保持時,執行非衝突性INSERT語句(同時插入)。但是,如果您正打算在MySQL外面操作數據庫文件,同時您保持鎖定,則不能使用READ LOCAL。對於InnoDB表,READ LOCAL與READ相同。

       當您使用LOCK TABLES時,您必須鎖定您打算在查詢中使用的所有的表。雖然使用LOCK TABLES語句獲得的鎖定仍然有效,但是您不能訪問沒有被此語句鎖定的任何的表。同時,您不能在一次查詢中多次使用一個已鎖定的表——使用別名代替,在此情況下,您必須分別獲得對每個別名的鎖定。

mysql> LOCK TABLE t WRITE, t AS t1 WRITE;mysql> INSERT INTO t SELECT * FROM t;ERROR 1100: Table 't' was not locked with LOCK TABLESmysql> INSERT INTO t SELECT * FROM t AS t1;如果您的查詢使用一個別名引用一個表,那麼您必須使用同樣的別名鎖定該表。如果沒有指定別名,則不會鎖定該表。

mysql> LOCK TABLE t READ;mysql> SELECT * FROM t AS myalias;ERROR 1100: Table 'myalias' was not locked with LOCK TABLES相反的,如果您使用一個別名鎖定一個表,您必須使用該別名在您的查詢中引用該表。

mysql> LOCK TABLE t AS myalias READ;mysql> SELECT * FROM t;ERROR 1100: Table 't' was not locked with LOCK TABLESmysql> SELECT * FROM t AS myalias;WRITE鎖定通常比READ鎖定擁有更高的優先權,以確保更新被儘快地處理。這意味着,如果一個線程獲得了一個READ鎖定,則另一個線程會申請一個WRITE鎖定,後續的READ鎖定申請會等待,直到WRITE線程獲得鎖定並釋放鎖定。您可以使用LOW_PRIORITY WRITE鎖定來允許其它線程在該線程正在等待WRITE鎖定時獲得READ鎖定。只有當您確定最終將有一個時機,此時沒有線程擁有READ鎖定時,您才應該使用LOW_PRIORITY WRITE鎖定。

LOCK TABLES按照如下方式執行:

1.    按照內部定義的順序,對所有要被鎖定的表進行分類。從用戶的角度,此順序是未經定義的。

2.    如果使用一個讀取和一個寫入鎖定對一個表進行鎖定,則把寫入鎖定放在讀取鎖定之前。

3.    一次鎖定一個表,直到線程得到所有鎖定爲止。

該規則確保表鎖定不會出現死鎖定。但是,對於該規則,您需要注意其它的事情:

如果您正在對一個表使用一個LOW_PRIORITY WRITE鎖定,這隻意味着,MySQL等待特定的鎖定,直到沒有申請READ鎖定的線程時爲止。當線程已經獲得WRITE鎖定,並正在等待得到鎖定表清單中的用於下一個表的鎖定時,所有其它線程會等待WRITE鎖定被釋放。如果這成爲對於應用程序的嚴重的問題,則您應該考慮把部分錶轉化爲事務安全型表。

您可以安全地使用KILL來結束一個正在等待表鎖定的線程。

注意,您不能使用INSERT DELAYED鎖定任何您正在使用的表,因爲,在這種情況下,INSERT由另一個線程執行。

通常,您不需要鎖定表,因爲所有的單個UPDATE語句都是原子性的;沒有其它的線程可以干擾任何其它當前正在執行的SQL語句。但是,在幾種情況下,鎖定表會有好處:

        如果您正在對一組MyISAM表運行許多操作,鎖定您正在使用的表,可以快很多。鎖定MyISAM表可以加快插入、更新或刪除的速度。不利方面是,沒有線程可以更新一個用READ鎖定的表(包括保持鎖定的表),也沒有線程可以訪問用WRITE鎖定的表(除了保持鎖定的表以外)。

有些MyISAM操作在LOCK TABLES之下更快的原因是,MySQL不會清空用於已鎖定表的關鍵緩存,直到UNLOCK TABLE被調用爲止。通常,關鍵緩存在每個SQL語句之後被清空。

        如果您正在使用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,有可能另一個線程會在執行SELECT和UPDATE語句之間在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,這是獲得備份的一個非常方便的方式。

註釋:如果您對一個已鎖定的表使用ALTER TABLE,該表可能會解鎖。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章