您現在的位置是:首頁 > 音樂首頁音樂

你還不知道的Mysql知識總結

由 魚頭剪輯 發表于 音樂2021-07-25
簡介MySQL InnoDB 引擎透過鎖機制、MVCC等手段來保證事務的隔離性( 預設支援的隔離級別是REPEATABLE-READ)

表就是資料庫資料庫就是表對的嗎

MySQL 基礎

關係型資料庫介紹

顧名思義,關係型資料庫就是一種建立在關係模型的基礎上的資料庫。關係模型表明了資料庫中所儲存的資料之間的聯絡(一對一、一對多、多對多)。

關係型資料庫中,我們的資料都被存放在了各種表中(比如使用者表),表中的每一列就存放著一條資料(比如一個使用者的資訊)。

你還不知道的Mysql知識總結

大部分關係型資料庫都使用 SQL 來操作資料庫中的資料。並且,大部分關係型資料庫都支援事務的四大特性(ACID)。

有哪些常見的關係型資料庫呢?

MySQL、PostgreSQL、Oracle、SQL Server、SQLite(微信本地的聊天記錄的儲存就是用的 SQLite) ……。

MySQL 介紹

你還不知道的Mysql知識總結

MySQL 是一種關係型資料庫,主要用於持久化儲存我們的系統中的一些資料比如使用者資訊。

由於 MySQL 是開源免費並且比較成熟的資料庫,因此,MySQL 被大量使用在各種系統中。任何人都可以在 GPL(General Public License) 的許可下下載並根據個性化的需要對其進行修改。MySQL 的預設埠號是

3306

儲存引擎

儲存引擎相關的命令

檢視 MySQL 提供的所有儲存引擎

mysql> show engines;

你還不知道的Mysql知識總結

檢視MySQL提供的所有儲存引擎

從上圖我們可以查看出 MySQL 當前預設的儲存引擎是 InnoDB,並且在 5。7 版本所有的儲存引擎中只有 InnoDB 是事務性儲存引擎,也就是說只有 InnoDB 支援事務。

檢視 MySQL 當前預設的儲存引擎

我們也可以透過下面的命令檢視預設的儲存引擎。

mysql> show variables like ‘%storage_engine%’;

查看錶的儲存引擎

show table status like “table_name” ;

你還不知道的Mysql知識總結

查看錶的儲存引擎

MyISAM 和 InnoDB 的區別

你還不知道的Mysql知識總結

MySQL 5。5 之前,MyISAM 引擎是 MySQL 的預設儲存引擎,可謂是風光一時。

雖然,MyISAM 的效能還行,各種特性也還不錯(比如全文索引、壓縮、空間函式等)。但是,MyISAM 不支援事務和行級鎖,而且最大的缺陷就是崩潰後無法安全恢復。

5。5 版本之後,MySQL 引入了 InnoDB(事務性資料庫引擎),MySQL 5。5 版本後預設的儲存引擎為 InnoDB。小夥子,一定要記好這個 InnoDB ,你每次使用 MySQL 資料庫都是用的這個儲存引擎吧?

言歸正傳!咱們下面還是來簡單對比一下兩者:

1.是否支援行級鎖

MyISAM 只有表級鎖(table-level locking),而 InnoDB 支援行級鎖(row-level locking)和表級鎖,預設為行級鎖。

也就說,MyISAM 一鎖就是鎖住了整張表,這在併發寫的情況下是多麼滴憨憨啊!這也是為什麼 InnoDB 在併發寫的時候,效能更牛皮了!

2.是否支援事務

MyISAM 不提供事務支援。

InnoDB 提供事務支援,具有提交(commit)和回滾(rollback)事務的能力。

3.是否支援外來鍵

MyISAM 不支援,而 InnoDB 支援。

拓展一下:

一般我們也是不建議在資料庫層面使用外來鍵的,應用層面可以解決。不過,這樣會對資料的一致性造成威脅。具體要不要使用外來鍵還是要根據你的專案來決定。

4.是否支援資料庫異常崩潰後的安全恢復

MyISAM 不支援,而 InnoDB 支援。

使用 InnoDB 的資料庫在異常崩潰後,資料庫重新啟動的時候會保證資料庫恢復到崩潰前的狀態。這個恢復的過程依賴於 redo log 。

拓展一下:

MySQL InnoDB 引擎使用

redo log(重做日誌)

保證事務的

永續性

,使用

undo log(回滾日誌)

來保證事務的

原子性

。MySQL InnoDB 引擎透過

鎖機制

MVCC

等手段來保證事務的隔離性( 預設支援的隔離級別是

REPEATABLE-READ

)。保證了事務的永續性、原子性、隔離性之後,一致性才能得到保障。

5.是否支援 MVCC

MyISAM 不支援,而 InnoDB 支援。

講真,這個對比有點廢話,畢竟 MyISAM 連行級鎖都不支援。

MVCC 可以看作是行級鎖的一個升級,可以有效減少加鎖操作,提供效能。

關於 MyISAM 和 InnoDB 的選擇問題

大多數時候我們使用的都是 InnoDB 儲存引擎,在某些讀密集的情況下,使用 MyISAM 也是合適的。不過,前提是你的專案不介意 MyISAM 不支援事務、崩潰恢復等缺點(可是~我們一般都會介意啊!)。

《MySQL 高效能》上面有一句話這樣寫到:

不要輕易相信“MyISAM 比 InnoDB 快”之類的經驗之談,這個結論往往不是絕對的。在很多我們已知場景中,InnoDB 的速度都可以讓 MyISAM 望塵莫及,尤其是用到了聚簇索引,或者需要訪問的資料都可以放入記憶體的應用。

一般情況下我們選擇 InnoDB 都是沒有問題的,但是某些情況下你並不在乎可擴充套件能力和併發能力,也不需要事務支援,也不在乎崩潰後的安全恢復問題的話,選擇 MyISAM 也是一個不錯的選擇。但是一般情況下,我們都是需要考慮到這些問題的。

因此,對於咱們日常開發的業務系統來說,你幾乎找不到什麼理由再使用 MyISAM 作為自己的 MySQL 資料庫的儲存引擎。

鎖機制與 InnoDB 鎖演算法

MyISAM 和 InnoDB 儲存引擎使用的鎖:

MyISAM 採用表級鎖(table-level locking)。InnoDB 支援行級鎖(row-level locking)和表級鎖,預設為行級鎖

表級鎖和行級鎖對比:

表級鎖:

MySQL 中鎖定

粒度最大

的一種鎖,對當前操作的整張表加鎖,實現簡單,資源消耗也比較少,加鎖快,不會出現死鎖。其鎖定粒度最大,觸發鎖衝突的機率最高,併發度最低,MyISAM 和 InnoDB 引擎都支援表級鎖。

行級鎖:

MySQL 中鎖定

粒度最小

的一種鎖,只針對當前操作的行進行加鎖。 行級鎖能大大減少資料庫操作的衝突。其加鎖粒度最小,併發度高,但加鎖的開銷也最大,加鎖慢,會出現死鎖。

InnoDB 儲存引擎的鎖的演算法有三種:

Record lock:記錄鎖,單個行記錄上的鎖Gap lock:間隙鎖,鎖定一個範圍,不包括記錄本身Next-key lock:record+gap臨鍵鎖,鎖定一個範圍,包含記錄本身

查詢快取

執行查詢語句的時候,會先查詢快取。不過,MySQL 8。0 版本後移除,因為這個功能不太實用

my。cnf 加入以下配置,重啟 MySQL 開啟查詢快取

query_cache_type=1query_cache_size=600000

MySQL 執行以下命令也可以開啟查詢快取

set global query_cache_type=1;set global query_cache_size=600000;

如上,

開啟查詢快取後在同樣的查詢條件以及資料情況下,會直接在快取中返回結果

。這裡的查詢條件包括查詢本身、當前要查詢的資料庫、客戶端協議版本號等一些可能影響結果的資訊。因此任何兩個查詢在任何字元上的不同都會導致快取不命中。此外,如果查詢中包含任何使用者自定義函式、儲存函式、使用者變數、臨時表、MySQL 庫中的系統表,其查詢結果也不會被快取。

快取建立之後,MySQL 的查詢快取系統會跟蹤查詢中涉及的每張表,如果這些表(資料或結構)發生變化,那麼和這張表相關的所有快取資料都將失效。

快取雖然能夠提升資料庫的查詢效能,但是快取同時也帶來了額外的開銷,每次查詢後都要做一次快取操作,失效後還要銷燬。

因此,開啟查詢快取要謹慎,尤其對於寫密集的應用來說更是如此。如果開啟,要注意合理控制快取空間大小,一般來說其大小設定為幾十 MB 比較合適。此外,

還可以透過 sql_cache 和 sql_no_cache 來控制某個查詢語句是否需要快取:

select sql_no_cache count(*) from usr;

事務

何為事務?

一言蔽之,

事務是邏輯上的一組操作,要麼都執行,要麼都不執行。

可以簡單舉一個例子不?

事務最經典也經常被拿出來說例子就是轉賬了。假如小明要給小紅轉賬 1000 元,這個轉賬會涉及到兩個關鍵操作就是:

1。將小明的餘額減少 1000 元2。將小紅的餘額增加 1000 元。

事務會把這兩個操作就可以看成邏輯上的一個整體,這個整體包含的操作要麼都成功,要麼都要失敗。

這樣就不會出現小明餘額減少而小紅的餘額卻並沒有增加的情況。

何為資料庫事務?

資料庫事務在我們日常開發中接觸的最多了。如果你的專案屬於單體架構的話,你接觸到的往往就是資料庫事務了。

平時,我們在談論事務的時候,如果沒有特指

分散式事務

,往往指的就是

資料庫事務

那資料庫事務有什麼作用呢?

簡單來說:資料庫事務可以保證多個對資料庫的操作(也就是 SQL 語句)構成一個邏輯上的整體。構成這個邏輯上的整體的這些資料庫操作遵循:

要麼全部執行成功,要麼全部不執行

# 開啟一個事務START TRANSACTION;# 多條 SQL 語句SQL1,SQL2。。。## 提交事務COMMIT;

你還不知道的Mysql知識總結

另外,關係型資料庫(例如:MySQL、SQL Server、Oracle 等)事務都有

ACID

特性:

你還不知道的Mysql知識總結

何為 ACID 特性呢?

1。

原子性

(Atomicity) : 事務是最小的執行單位,不允許分割。事務的原子性確保動作要麼全部完成,要麼完全不起作用;2。

一致性

(Consistency): 執行事務前後,資料保持一致,例如轉賬業務中,無論事務是否成功,轉賬者和收款人的總額應該是不變的;3。

隔離性

(Isolation): 併發訪問資料庫時,一個使用者的事務不被其他事務所幹擾,各併發事務之間資料庫是獨立的;4。

永續性

(Durabilily): 一個事務被提交之後。它對資料庫中資料的改變是持久的,即使資料庫發生故障也不應該對其有任何影響。

資料事務的實現原理呢?

我們這裡以 MySQL 的 InnoDB 引擎為例來簡單說一下。

MySQL InnoDB 引擎使用

redo log(重做日誌)

保證事務的

永續性

,使用

undo log(回滾日誌)

來保證事務的

原子性

MySQL InnoDB 引擎透過

鎖機制

MVCC

等手段來保證事務的隔離性( 預設支援的隔離級別是

REPEATABLE-READ

)。

保證了事務的永續性、原子性、隔離性之後,一致性才能得到保障。

併發事務帶來哪些問題?

在典型的應用程式中,多個事務併發執行,經常會操作相同的資料來完成各自的任務(多個使用者對同一資料進行操作)。併發雖然是必須的,但可能會導致以下的問題。

髒讀(Dirty read):

當一個事務正在訪問資料並且對資料進行了修改,而這種修改還沒有提交到資料庫中,這時另外一個事務也訪問了這個資料,然後使用了這個資料。因為這個資料是還沒有提交的資料,那麼另外一個事務讀到的這個資料是“髒資料”,依據“髒資料”所做的操作可能是不正確的。

丟失修改(Lost to modify):

指在一個事務讀取一個數據時,另外一個事務也訪問了該資料,那麼在第一個事務中修改了這個資料後,第二個事務也修改了這個資料。這樣第一個事務內的修改結果就被丟失,因此稱為丟失修改。 例如:事務 1 讀取某表中的資料 A=20,事務 2 也讀取 A=20,事務 1 修改 A=A-1,事務 2 也修改 A=A-1,最終結果 A=19,事務 1 的修改被丟失。

不可重複讀(Unrepeatableread):

指在一個事務內多次讀同一資料。在這個事務還沒有結束時,另一個事務也訪問該資料。那麼,在第一個事務中的兩次讀資料之間,由於第二個事務的修改導致第一個事務兩次讀取的資料可能不太一樣。這就發生了在一個事務內兩次讀到的資料是不一樣的情況,因此稱為不可重複讀。

幻讀(Phantom read):

幻讀與不可重複讀類似。它發生在一個事務(T1)讀取了幾行資料,接著另一個併發事務(T2)插入了一些資料時。在隨後的查詢中,第一個事務(T1)就會發現多了一些原本不存在的記錄,就好像發生了幻覺一樣,所以稱為幻讀。

不可重複讀和幻讀區別:

不可重複讀的重點是修改比如多次讀取一條記錄發現其中某些列的值被修改,幻讀的重點在於新增或者刪除比如多次讀取一條記錄發現記錄增多或減少了。

事務隔離級別有哪些?

SQL 標準定義了四個隔離級別:

READ-UNCOMMITTED(讀取未提交):

最低的隔離級別,允許讀取尚未提交的資料變更,

可能會導致髒讀、幻讀或不可重複讀

READ-COMMITTED(讀取已提交):

允許讀取併發事務已經提交的資料,

可以阻止髒讀,但是幻讀或不可重複讀仍有可能發生

REPEATABLE-READ(可重複讀):

對同一欄位的多次讀取結果都是一致的,除非資料是被本身事務自己所修改,

可以阻止髒讀和不可重複讀,但幻讀仍有可能發生

SERIALIZABLE(可序列化):

最高的隔離級別,完全服從 ACID 的隔離級別。所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,

該級別可以防止髒讀、不可重複讀以及幻讀

隔離級別髒讀不可重複讀幻讀READ-UNCOMMITTED√√√READ-COMMITTED×√√REPEATABLE-READ××√SERIALIZABLE×××

MySQL 的預設隔離級別是什麼?

MySQL InnoDB 儲存引擎的預設支援的隔離級別是

REPEATABLE-READ(可重讀)

。我們可以透過SELECT @@tx_isolation;命令來檢視,MySQL 8。0 該命令改為SELECT @@transaction_isolation;

mysql> SELECT @@tx_isolation;+————————-+| @@tx_isolation |+————————-+| REPEATABLE-READ |+————————-+

這裡需要注意的是:與 SQL 標準不同的地方在於 InnoDB 儲存引擎在

REPEATABLE-READ(可重讀)

事務隔離級別下使用的是 Next-Key Lock 鎖演算法,因此可以避免幻讀的產生,這與其他資料庫系統(如 SQL Server)是不同的。所以說 InnoDB 儲存引擎的預設支援的隔離級別是

REPEATABLE-READ(可重讀)

已經可以完全保證事務的隔離性要求,即達到了 SQL 標準的

SERIALIZABLE(可序列化)

隔離級別。

問題更正:

MySQL InnoDB 的 REPEATABLE-READ(可重讀)並不保證避免幻讀,需要應用使用加鎖讀來保證。而這個加鎖度使用到的機制就是 Next-Key Locks。

因為隔離級別越低,事務請求的鎖越少,所以大部分資料庫系統的隔離級別都是

READ-COMMITTED(讀取提交內容)

,但是你要知道的是 InnoDB 儲存引擎預設使用

REPEAaTABLE-READ(可重讀)

並不會有任何效能損失。

InnoDB 儲存引擎在

分散式事務

的情況下一般會用到

SERIALIZABLE(可序列化)

隔離級別。

拓展一下(以下內容摘自《MySQL 技術內幕:InnoDB 儲存引擎(第 2 版)》7。7 章):

InnoDB 儲存引擎提供了對 XA 事務的支援,並透過 XA 事務來支援分散式事務的實現。分散式事務指的是允許多個獨立的事務資源(transactional resources)參與到一個全域性的事務中。事務資源通常是關係型資料庫系統,但也可以是其他型別的資源。全域性事務要求在其中的所有參與的事務要麼都提交,要麼都回滾,這對於事務原有的 ACID 要求又有了提高。另外,在使用分散式事務時,InnoDB 儲存引擎的事務隔離級別必須設定為 SERIALIZABLE。

參考

《高效能 MySQL》https://www。omnisci。com/technical-glossary/relational-database