MySQL入門

1、MySQL數據庫的基本結構


MySQL入門

MySQL基本結構


最上層的客戶端層負責處理鏈接處理和授權認證,安全等功能。

第二層架構是MySQL中的核心層,MySQL大多數核心功能都在這一層搞定。包括查詢解析,優化,緩存以及MySQL所有的內置函數。所有的跨存儲引擎的功能都在這一層實現。

第三層是MySQL所有的存儲引擎。每一種存儲引擎都有其不同的地方,也有其優勢和劣勢。存儲引擎除了InnoDB以外都不會去解析SQL。InnoDB因為涉及到外鍵,所以需要解析SQL。

2、MySQL的併發控制

無論何時,只要涉及到讀寫操作都會涉及到併發問題。日誌,郵件,excel等等都會有這樣的問題。我之前寫過一個功能是解析日誌判斷接口中日誌打印的參數和傳遞的參數是否一致。最開始我沒有考慮到這個問題,寫了個線程池直接多線程給接口發請求。結果打印出來的日誌全是亂七八糟的,日誌格式也被改變了。

MySQL作為數據庫,肯定不能允許併發問題的發生。不可能兩個人同時對一條數據進行修改會出現很多種不同的結果,那樣就亂套了。

讀寫鎖:

我們常用的郵件功能,如果兩個人同時閱讀同一封郵件是完全沒有問題的。但是如果一個人在閱讀一封郵件,但是同時另外一個人修改了這封郵件,那麼就會導致讀郵件的人可能會看到不同的結果。有可能是空白郵件,也有可能是沒有修改以前的郵件,還有可能亂碼等各種問題。數據庫也存在同樣的問題。

解決這類問題的最經典的方法就是加共享鎖(讀鎖)和排它鎖(寫鎖)。

共享鎖又稱讀鎖。讀一個數據的時候多少個對象同時讀取都無所謂,都可以同時讀取數據,互不干擾。

排它鎖又稱寫鎖。一個寫鎖會阻塞其他的共享鎖和排它鎖。在有對象在進行寫的操作時,數據庫會將數據鎖死,不允許讀也不會允許別的用戶對其修改。

粒度鎖:

除了讀寫鎖,MySQL還有一種鎖機制叫做粒度鎖。讀寫鎖雖然可以解決讀寫矛盾問題,但是還有個很嚴重的問題就是我們應該鎖住多大的範圍?是隻要有一條內容被修改我們就鎖住整個數據庫不讓讀還是鎖住整個表又或者僅僅只是鎖住被修改的那一行不讓讀?這個就涉及到粒度鎖。

我們最希望的方式是儘量精確的鎖定被修改的地方而不是鎖定所有資源,這樣可以支持更高的併發量,只要修改的數據不互相沖突即可。

但是問題是加鎖也需要消耗資源。鎖的各種操作,包括獲得鎖,檢查鎖是否被釋放,釋放鎖等等操作,都會大幅度的增加系統的消耗。所以採取哪一種的鎖策略,也需要在鎖的開銷和數據安全之間尋求平衡。

MySQL最重要的兩種鎖策略分別是表鎖和行級鎖。

表鎖是MySQL中開銷最小的鎖策略。當一張表中有一行被更改時,當前表就不再允許查詢和修改。一個用戶在對錶進行寫操作時需要首先獲取表的排它鎖。當其獲取了排它鎖,別人就不能再對這張表進行訪問,除非他修改完該表並且釋放了鎖。

行級鎖可以最大程度的支持併發處理,但是他也是鎖消耗最大的鎖。行級鎖只會獲取需要修改的行的排它鎖,整張表的其餘行依然可以進行訪問。

3、MySQL的事務

說明事務最好的方式就是轉賬。

如果A要給B轉賬200元錢。從數據庫的操作來看就是

1. 開始事務

2. A賬戶減少200元

3. B賬戶增加200元

4. 提交事務

當第三條執行失敗時,事務沒有被提交,所以會直接回滾到執行事務以前。A的賬戶不會減少200元。

事務的四大特性:原子性,一致性,隔離性,持久性

原子性:一個事務必須被視為不可分割的最小單元,整個事務必須全部提交成功或者全部提交失敗。

一致性:數據庫總是從一個一致性的狀態轉換到另外一個一致性的狀態。

隔離性:通常來說一個事務在沒有提交以前對於別的事務來說是不可見的。前面轉賬的例子如果在執行B賬戶增加200元操作的同時另一個事務查詢了A的賬戶,A的賬戶應該還是未減少之前的狀態。

持久性:一旦事務提交,那麼數據就會被永久的保存到數據庫中。這是哪怕是系統崩潰了,死機了,數據也不會丟失。但是這也只是理論上,否則也不會需要做備份了。

隔離性實際上比想象的要複雜的多得多。在SQL中定義了四中隔離級別,級別越低的併發能力越強,當然安全性也就越差。級別越高的併發能力越差,安全性也越強。

四大隔離級別:未提交讀,提交讀(不可重複讀),可重複讀,可串行化

未提交讀:在這個隔離級別下事務裡面未提交的部分別的事務也可以看到,這又被稱之為髒讀。這個級別會導致非常多的問題,比如查詢後根據查詢到的數據修改數據,就會導致數據錯誤。在性能上來說這個級別的併發性能是最好的,但是基本上不用,因為太不安全。

提交讀(不可重複讀):大多數的數據庫的默認事務隔離級別都是不可重複讀,但是MySQL不是。不可重複讀滿足了前面隔離性的簡單定義,一個事務如果沒有被提交,那麼就不會被別的事務讀取結果。但是同一個事務中兩次讀取同一個數據可能獲取的結果不一樣。

可重複讀:該級別可以保證多次讀取同樣記錄的結果是一樣的,MySQL默認的就是該隔離級別,但是其無法解決幻讀的問題。

可串行化:可串行化是隔離級別的最高級別,它強制所有的事務必須串行執行,避免了幻讀的問題,但是效率太低,一般也不會用。

MySQL入門


分享到:


相關文章: