mysql中flush tables和flush tables with read lock詳解


mysql中flush tables和flush tables with read lock詳解


FLUSH TABLES

官方手冊中關於Flush tables的介紹, Closes all open tables, forces all tables in use to be closed, and flushes the query cache. FLUSH TABLES also removes all query results from the query cache, like the RESET QUERY CACHE statement.其解析就是關閉所有已打開的表對象,同時將查詢緩存中的結果清空。就是說Flush tables的一個效果就是會等待所有正在運行的SQL請求結束。

因為,語句在執行前,都會打開相應的表對象,如select * from t1語句,會找到t1表的frm文件,並打開表內存對象。為了控制表對象使用的內存空間和其他資源,MySQL會隱式(後臺表對象管理線程)或顯式(flush tables等)來關閉已打開但並沒有使用的表對象。

然而,正在使用的表對象是不能關閉的(如SQL請求仍在運行),因此,Flush Tables操作會被正在運行的SQL請求阻塞。

注意這裡是清空query cache,這個查詢緩存基本不會在生產中應用,所以清空不清空的都影響,總之flush就是將現有數據庫連接全部關閉,那麼它可以立即關閉現有的連接嗎? 答案當然是否定的,比如有些連接在插入數據 更新數據 甚至正在查詢數據,這些都是不能立即關閉的,它要等人家完成後才能關閉人家的連接,也就是它需要等待的。我們來看下flush table等待情況

1.準備表a 和 表 b 並各自插入數據

CREATE TABLE `a` (

`id` int(11) NOT NULL,

PRIMARY KEY (`id`)

);

CREATE TABLE `b` (

`id` int(11) NOT NULL,

PRIMARY KEY (`id`)

) ;

insert into a values(1);

insert into b values(1);

2.進程1

select sleep(20) from a limit 1 ; 執行中

進程2:

flush tables; 被阻塞(被進程1阻塞)

進程3:

select * from a; 被阻塞(被進程2阻塞)

進程4:

select * from b;執行完成

insert into b values(3); 執行完成

結論:flush tables 是會被當前正在運行的sql阻塞的,但是 flush tables 還是會把阻塞它的表(無論多少個)都給鎖定起來,這個時候這些表就不會在被其他進程使用,哪怕是select 也不行,而其他表則是還可以進行查詢的。甚至其他表還可以被插入或修改,因此這裡我們要清楚 flush tables 是隻會將它執行的那個時間點之前的連接來關閉,執行完flush tables之後哪怕它正在被阻塞中,之後的那些連接照樣可以進行其他操作,如果我們把進程4改成 insert操作也是可以正常執行。

那麼我們在做主從設置時候需要主從在某個日誌點備份一致該怎麼是實現呢,那就是flush tables 之後不僅僅鎖定正在阻塞該指令的表,其他表也要一併鎖定起來,只運行查詢操作,注入更新或插入都是不允許的,這裡我們就要用到了

flush tables with read lock

FLUSH TABLES WITH READ LOCK

該操作是在flush tables 之後使用一個全局鎖,將所有表都進行鎖定,只允許查詢

我們來進行下測試

.進程1

select sleep(20) from a limit 1 ; 執行中

進程2:

flush tables with read lock; 被阻塞(被進程1阻塞)

進程3:

select * from a; 被阻塞(被進程2阻塞)

進程4:

select * from b;執行完成

insert into b values(3); 執行被阻塞(被進程2阻塞)

我們看到進程4中查詢是額可以正常執行的,但是插入被阻塞了,哪怕是當進程1執行完成後,進程2也提交後,

數據庫中的所有表還是隻能查詢,而不能進行dml的操作,這樣就保證數據庫目前的pid穩定不會變化

注意如果要解除全局鎖要顯式的解除鎖定

unlock tables;

另外flush tables with read lock 可以鎖定單獨表的

flush tables a with read lock;

當然解鎖的話也是 unlock tables;


分享到:


相關文章: