MySQL 全局鎖、表級鎖、行級鎖,你搞清楚了嗎?( 二 )


因為在可重復讀的隔離級別下 , 即使其他事務更新了表的數據 , 也不會影響備份數據庫時的 Read View , 這就是事務四大特性中的隔離性 , 這樣備份期間備份的數據一直是在開啟事務時的數據 。
備份數據庫的工具是 mysqldump , 在使用 mysqldump 時加上 –single-transaction 參數的時候 , 就會在備份數據庫之前先開啟事務 。這種方法只適用于支持「可重復讀隔離級別的事務」的存儲引擎 。
InnoDB 存儲引擎默認的事務隔離級別正是可重復讀 , 因此可以采用這種方式來備份數據庫 。
但是 , 對于 MyISAM 這種不支持事務的引擎 , 在備份數據庫時就要使用全局鎖的方法 。
表級鎖

MySQL 表級鎖有哪些?具體怎么用的 。
MySQL 里面表級別的鎖有這幾種:
  • 表鎖;
  • 元數據鎖(MDL);
  • 意向鎖;
  • AUTO-INC 鎖;
表鎖先來說說表鎖 。
如果我們想對學生表(t_student)加表鎖 , 可以使用下面的命令:
//表級別的共享鎖 , 也就是讀鎖;lock tables t_student read;//表級別的獨占鎖 , 也就是寫鎖;lock tables t_stuent write;需要注意的是 , 表鎖除了會限制別的線程的讀寫外 , 也會限制本線程接下來的讀寫操作 。
也就是說如果本線程對學生表加了「共享表鎖」 , 那么本線程接下來如果要對學生表執行寫操作的語句 , 是會被阻塞的 , 當然其他線程對學生表進行寫操作時也會被阻塞 , 直到鎖被釋放 。
要釋放表鎖 , 可以使用下面這條命令 , 會釋放當前會話的所有表鎖:
unlock tables另外 , 當會話退出后 , 也會釋放所有表鎖 。
不過盡量避免在使用 InnoDB 引擎的表使用表鎖 , 因為表鎖的顆粒度太大 , 會影響并發性能 , InnoDB 牛逼的地方在于實現了顆粒度更細的行級鎖 。
元數據鎖再來說說元數據鎖(MDL) 。
我們不需要顯示的使用 MDL , 因為當我們對數據庫表進行操作時 , 會自動給這個表加上 MDL:
  • 對一張表進行 CRUD 操作時 , 加的是 MDL 讀鎖;
  • 對一張表做結構變更操作的時候 , 加的是 MDL 寫鎖;
MDL 是為了保證當用戶對表執行 CRUD 操作時 , 防止其他線程對這個表結構做了變更 。
當有線程在執行 select 語句( 加 MDL 讀鎖)的期間 , 如果有其他線程要更改該表的結構( 申請 MDL 寫鎖) , 那么將會被阻塞 , 直到執行完 select 語句( 釋放 MDL 讀鎖) 。
反之 , 當有線程對表結構進行變更( 加 MDL 寫鎖)的期間 , 如果有其他線程執行了 CRUD 操作( 申請 MDL 讀鎖) , 那么就會被阻塞 , 直到表結構變更完成( 釋放 MDL 寫鎖) 。
MDL 不需要顯示調用 , 那它是在什么時候釋放的?
MDL 是在事務提交后才會釋放 , 這意味著事務執行期間 , MDL 是一直持有的 。
那如果數據庫有一個長事務(所謂的長事務 , 就是開啟了事務 , 但是一直還沒提交) , 那在對表結構做變更操作的時候 , 可能會發生意想不到的事情 , 比如下面這個順序的場景:
  1. 首先 , 線程 A 先啟用了事務(但是一直不提交) , 然后執行一條 select 語句 , 此時就先對該表加上 MDL 讀鎖;

    經驗總結擴展閱讀