溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么用mysql實(shí)現(xiàn)一個(gè)小魔術(shù)

發(fā)布時(shí)間:2021-12-04 09:45:33 來(lái)源:億速云 閱讀:126 作者:iii 欄目:MySQL數(shù)據(jù)庫(kù)

本篇內(nèi)容介紹了“怎么用mysql實(shí)現(xiàn)一個(gè)小魔術(shù)”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

測(cè)試過(guò)程如下:
mysql> select * from test;
+------+
| name |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+------+
5 rows in set (0.00 sec)

mysql> select * from test;
+------+
| name |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+------+
5 rows in set (0.00 sec)

mysql> flush tables;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test;
+------------------------------+
| name |
+------------------------------+
| 熱烈祝賀宇宙大爆炸一萬(wàn)萬(wàn)周年 |
| 忽忽變了變了 |
+------------------------------+
2 rows in set (0.00 sec)

mysql>

測(cè)試中使用的表是MyIsam引擎。
只是執(zhí)行flush table并沒(méi)有update,delete,insert的操作說(shuō)明這個(gè)現(xiàn)象也就是跟緩存之類(lèi)的有關(guān)。
先看看flush table是做了什么。
mysql參考手冊(cè)中解釋?zhuān)?br/>關(guān)閉打開(kāi)的表,并迫使所有正在使用的表關(guān)閉。這也會(huì)刷新查詢緩存。和RESET QUERY CACHE語(yǔ)句一樣,F(xiàn)LUSH TABLES還會(huì)取消來(lái)自查詢緩存的所有查詢結(jié)果。
呵呵 下面來(lái)分析一下這個(gè)“魔術(shù)”是怎么產(chǎn)生的。
首先我們會(huì)想到query cache,其實(shí)這很容易理解。
本次測(cè)試中query cache參數(shù)如下:
mysql> show variables like 'q%';
+------------------------------+----------+
| Variable_name | Value |
+------------------------------+----------+
| query_alloc_block_size | 8192 |
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 34603008 |
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
| query_prealloc_size | 8192 |
+------------------------------+----------+
7 rows in set (0.00 sec)
mysql中的query cache的功能是緩存查詢結(jié)果,在下次查詢是如果查詢語(yǔ)句相同會(huì)直接從緩存中提取結(jié)果,而不是從數(shù)據(jù)表中查詢。
當(dāng)然并非是所有的查詢都會(huì)被緩存,要滿足一定條件:結(jié)果集超過(guò)query_cache_limit的大小不緩存,procedure中的結(jié)果不緩存,子查詢中的外聯(lián)結(jié)果集不緩存。。
本次測(cè)試不存在這些問(wèn)題。
所有過(guò)程如下:
先插入數(shù)據(jù):
mysql> insert into test values("熱烈祝賀宇宙大爆炸一萬(wàn)萬(wàn)周年");
Query OK, 1 row affected (0.00 sec)

mysql> insert into test values("忽忽變了變了");
Query OK, 1 row affected (0.00 sec)
然后把數(shù)據(jù)文件copy到其他位置
root@qadb:/var/lib/mysql/test# cp -a test.* /root/test
刪除表中的數(shù)據(jù)
mysql> delete from test;
Query OK, 3 rows affected (0.00 sec)
插入新數(shù)據(jù)
mysql> insert into fuleqing values('1');
Query OK, 1 row affected (0.00 sec)

mysql> insert into fuleqing values('2');
Query OK, 1 row affected (0.00 sec)

mysql> insert into fuleqing values('3');
Query OK, 1 row affected (0.00 sec)

mysql> insert into fuleqing values('4');
Query OK, 1 row affected (0.00 sec)

mysql> insert into fuleqing values('5');
Query OK, 1 row affected (0.00 sec)

最后把之前備份的數(shù)據(jù)文件覆蓋現(xiàn)在的數(shù)據(jù)文件
root@qadb:/var/lib/mysql/test# cp -a /root/test.* .

現(xiàn)在在之客戶端執(zhí)行select ,flush,select這個(gè)”魔術(shù)“就可以了

到這里大家應(yīng)該都看明白了吧,如果我們使用DDL語(yǔ)句更改數(shù)據(jù)則相關(guān)的query cache則會(huì)相應(yīng)的失效,再次使用會(huì)從數(shù)據(jù)表中讀取。但如果使用直接數(shù)據(jù)文件覆蓋的話至少目前mysql的MyIsam引擎并不知道數(shù)據(jù)發(fā)生了變化,相應(yīng)的query cache并不會(huì)失效。第一次select的結(jié)果其實(shí)是從cache里取的舊數(shù)據(jù),直到flush后query cache被清空,然后再select才是從新的數(shù)據(jù)文件讀取。

下面我再做一個(gè)小”魔術(shù)“,不使用query cache
mysql> select sql_no_cache * from test;
+------+
| name |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+------+
5 rows in set (0.00 sec)

mysql> select sql_no_cache * from test;
+------+
| name |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+------+
5 rows in set (0.00 sec)

mysql> flush tables;
Query OK, 0 rows affected (0.00 sec)

mysql> select sql_no_cache * from test;
+------------------------------+
| name |
+------------------------------+
| 熱烈祝賀宇宙大爆炸一萬(wàn)萬(wàn)周年 |
| 忽忽變了變了 |
+------------------------------+
2 rows in set (0.00 sec)

mysql>

一般到這里大家會(huì)產(chǎn)生點(diǎn)疑問(wèn),都不從cache里取數(shù)據(jù)了為什么也會(huì)出現(xiàn)這個(gè)現(xiàn)象呢?

如果我們還是按照之前的操作,用備份的數(shù)據(jù)文件覆蓋是不行的。
大家可以看到有兩種情況,如果備份的數(shù)據(jù)比當(dāng)前的數(shù)據(jù)多,只顯示新數(shù)據(jù)文件中的部分?jǐn)?shù)據(jù)。如果備份的數(shù)據(jù)比當(dāng)前的數(shù)據(jù)少,查詢即報(bào)錯(cuò)。
mysql> select sql_no_cache * from test;
ERROR 1194 (HY000): Table 'test' is marked as crashed and should be repaired
這些跟mysql的故障偵測(cè)機(jī)制有關(guān),我沒(méi)有深入的研究。等以后有時(shí)間再看
在出現(xiàn)上面這些情況時(shí)做一下flush table或者repair一下都可以恢復(fù)正常,但是重現(xiàn)不了我們這次的”魔術(shù)“
說(shuō)一下我操作的過(guò)程:
插入數(shù)據(jù)->備份表的數(shù)據(jù)文件

delete舊數(shù)據(jù)
insert新數(shù)據(jù)
這個(gè)過(guò)程跟前一個(gè)場(chǎng)景相同.之后就不一樣了
刪除當(dāng)前數(shù)據(jù)文件
root@qadb:/var/lib/mysql/test# rm test.*
copy回備份數(shù)據(jù)文件
root@qadb:/var/lib/mysql/test# cp -a /root/temp/test.* .
現(xiàn)在前面的客戶端又可以執(zhí)行select,flush,select這個(gè)"魔術(shù)"了

這次又是為什么呢?
首先聲明這次的測(cè)試只有在linux/unix中才能實(shí)現(xiàn),windows不可以
我們知道m(xù)ysql是通過(guò)os來(lái)操作數(shù)據(jù)文件的,這就要跟linux/unix對(duì)文件的處理有關(guān).
一個(gè)比較經(jīng)典的問(wèn)題,在windows中當(dāng)一個(gè)文件被使用的時(shí)候,另一個(gè)進(jìn)程可以刪除這個(gè)文件嗎?這個(gè)我們都知道不行。
但在linux/unix中呢?是可以的。之前讀取文件的進(jìn)程在文件被另一個(gè)進(jìn)程刪除后會(huì)報(bào)錯(cuò)嗎?也不會(huì)。

這個(gè)文件這時(shí)候其實(shí)并沒(méi)有真正意義上刪除。在linux/unix中只有所有操作該文件的進(jìn)程/線程都退出,該文件才會(huì)真正的被釋放。
分析本次的select,flush,select的操作如下:
雖然另一個(gè)進(jìn)程刪除了數(shù)據(jù)文件并copy進(jìn)新的數(shù)據(jù)文件但由于之前表是open的,mysql后臺(tái)線程一直在使用舊數(shù)據(jù)文件,該文件并未真正刪除。此時(shí)select的數(shù)據(jù)仍是舊數(shù)據(jù)。
flush 關(guān)閉表,使用舊數(shù)據(jù)文件的線程退出,舊數(shù)據(jù)文件被真實(shí)釋放;
再次select 表open這時(shí)讀取新的數(shù)據(jù)文件。此時(shí)select的數(shù)據(jù)為新數(shù)據(jù)。

“怎么用mysql實(shí)現(xiàn)一個(gè)小魔術(shù)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI