Innodb存储引擎的特性(1).
生活随笔
收集整理的這篇文章主要介紹了
Innodb存储引擎的特性(1).
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
現在關于系統表空間和獨立表空間還有一個問題,也要說明一下,我們把數據遷移到獨立表空間后,那么現在的系統表空間中呢,還有什么內容呢,答案是我們雖然已經把表的數據從系統表空間中遷移出來,但是對于系統表空間來說,還是有一個很重要的東西要清除的,其中之一呢,就是Innodb的數據字典,數據字典是數據庫對象結構的源數據信息,當存放與數據庫對象相關的一些信息,表,列,索引,外鍵等這些內容,細心的朋友可能已經發現了,我之前說過,MYSQL是使用frm文件來存儲表結構定義的,那么frm文件和系統表空間中,存放的數據字典之間有什么區別呢,首先來說,frm文件是MYSQL服務器產生的文件,可以理解為MYSQL數據庫層的數據字典,這個對于MYSQL的所有存儲引擎呢,一樣的,大家如果還記得話,我在介紹MYSQL數據庫架構的時候說過,在MYSQL服務器層,所保存的東西是與存儲引擎無關的,而Innodb內部的數據字典呢,是存儲引擎內部產生的,并可以保證事務的安全性,另外innodb存儲引擎呢,沒有直接使用MYSQL數據庫上的,一些上傳的類型,而是自己封裝了一些定義,因此,數據字典存儲的都是引擎相關的一些內容,最后,frm只是一個簡單的二進制文件,而innodb數據字典呢,是通過B樹進行管理的,除了innodb數據字典以外,在系統表空間,還會存在undo回滾段和innodb臨時表,雖然這兩種數據呢,在MYSQL5.7版本中,都是可以從系統表空間中移出的,但是還是有很多會默認在表空間中,對于Undo字段的在MYSQL5.6時就已經支持了,這里講了Innodb存儲上的一些特點,下面來看一下其他的一些特色
存儲引擎的其他特色,首先Innodb是一種事務性的存儲引擎,其完全支持事務的ACID特性,也就是原子性,一致性,隔離性,持久性,關于事務的這四個特性呢,之前已經介紹過了,這里就不過多介紹了,我們在這里主要介紹一下,Innodb是如何實現這幾個特性的,為了實現事務的原子性呢,一致性和持久性,Innodb使用了兩個特殊的日志類型,也就是重構日志,Redo log,和回滾日志 undo log,這兩個日志的作用是完全不同的,Redo Log主要是用于實現事務的永久性,其由兩部分組成,一個是內存中的重做日志緩存區,由Innodb參數來決定大小,另一個是日志文件,我們在文件系統中看到的,我們可以在系統中來看一下這兩個配置
首先我們要進入到我們的系統,我們可以使用show命令來看一下,系統中的關于我們剛才所說的,兩個參數的配置情況,其中一個是innodb_log_buffer_sizeshow variables like 'innodb_log_buffer_size';
這個就是我們目前MYSQL中所配備的redo log緩沖區的大小,這個數值是以字節為單位的,由于我們最多每隔一秒把緩沖區刷新到磁盤上,所以這緩沖區呢不用配置的太大,另外一個呢,我們在文件系統中查看,我們可以在數據庫目錄下看到,ib_logfile來開頭的一些文件,這個文件的數量呢,是由innodb_log_file來決定的,這里我們看到有兩個ib_logfile的文件,一個是ib_logfile0,一個是ib_logfile1
就是參數,我們剛才所提到的參數,innodb_log_files_in_group,所以會產生兩個innodb文件show variables like 'innod_log_file_in_group';
undo log的主要作用是,用于幫助未提交事務進行回滾,和實現那個mvcc,多版本并發控制的,Redo log中存儲的是已提交的事務,而undo log中呢,存儲的是未提交的事務,因此當我們對innodb表中的數據,進行修改時,也會產生redo log,還會產生一定的undo log,這樣如果用戶執行的語句由于某種原因失敗使用rollback語句進行回滾時,就需要利用undo log中的信息了,由上面的介紹可知,redo log基本是順序寫入的,在數據庫運行時,不需要對redo log進行讀取,而undo log呢,且需要隨機的讀寫的,前面說過,MYSQL5.6版本的undo log呢可以獨立于系統表空間而存在,如果條件允許,我們就可以把undolog存儲在固態存儲上,比如SSD和PCI-E設備上,這樣可以獲得更好的性能,Innodb第二個特性是,Innodb所支持的是行級鎖,而這一點呢,同MYISAM引擎所支持的表級鎖呢,是不一樣的,行級鎖的特點呢,在進行寫操作時呢,我們需要鎖定的資源呢,更少,這樣呢所能支持的并發呢更多,這里所需要注意的是,行級鎖是在存儲引擎層實現的,MYSQL服務器呢,完全不了解存儲引擎中,鎖的實現方式,說到鎖,可能大家還不是太了解,鎖的作用是什么呢,因為鎖對于數據庫的性能又非常大的影響,所以我覺得有必要在這里給大家簡單的介紹一下,什么是鎖,可能很多開發人員呢會問,經常聽到DBA說到各種各樣的鎖,比如說行級鎖啊,表級鎖啊,共享鎖,那么這些鎖的作用又是什么呢
首先我們來看一下什么是鎖,鎖是數據庫系統區別于文件系統的一個重要特性,作用是管理共享資源的并發訪問,并發訪問是一個讓人很頭疼的問題了,對于任何的串行環境下,良好的系統,一旦涉及到并發的情況下,可能會出現各種各樣的問題,在這里我們可以舉一個很常見的郵件系統的列子,來說明鎖的作用,我們知道一個郵箱中,所有的郵件是串行連接在一起的,于此首尾相連,這種結構呢,對于讀取郵件呢,都是有很大的好處的,當有新的郵件到來時呢,只要插入到文件末尾就可以了,那我們想象一下,這時如果有兩個用戶同一個郵件進行郵件投遞,會出現什么樣的情況呢,很有可能,郵箱的數據會被破壞,兩封信件的內容會交叉在一起,當然了,這可能跟我們平常生活中感受可能有很大的不同,那是因為現在的郵件系統,都是通過鎖,對這種情況進行的控制,所保證了在一個用戶向這郵件投遞郵件時,另一個用戶會阻塞,無法向相同的郵件末尾寫入郵件,那么鎖的另一個作用呢,需要事務的隔離性,前面提到過,通過redo log和undo log實現了事務的原子性,一致性和持久性,而隔離性是需要鎖來實現的,對于未提交的事務,鎖定的事務是無法被其他的事務所查詢到的
了解了什么是鎖,以及鎖的作用后,我們來看一看鎖的常見分類,其實鎖最主要的類型只有兩種,共享鎖也稱之為讀鎖,和獨占鎖也稱之為寫鎖,從名字中我們也可以看出來,讀鎖是共享的,也就是說,相互之間不會阻塞的,多個線程可以在同一個時間讀取同一資源,而不相互干擾,寫鎖是獨占的,可以說是排他的,也就是說,一個寫鎖會阻塞其他的寫鎖或讀鎖,這是出于數據完整性的考慮,只有這樣才能保證在給定的時間里,就一個線程能執行寫入,并防止其他用戶讀取正在寫入的同一資源,也就是前面我們說的事務的隔離性,我們看一下旁邊的表給出了讀寫鎖的兼容關系,從表中我們可以看出,寫鎖也就是獨占鎖,和所有的其他鎖是不兼容的,而讀鎖和讀鎖之間是兼容的,需要注意的是,以Innodb來說,讀鎖和寫鎖呢,都是行鎖,兼容性是指的同一行記錄,兼容性的情況,當然Innodb的鎖呢,實際上呢,要比這個復雜的多,如果按照我們上面介紹的,大家可能會發現,對于同一資源的讀寫請求呢,應該是互斥的,但是我們實際體驗呢,可能并不和以下的情況相同,我們可以通過以下的實驗來看一下
就以我們剛才建的myinnodb來測試,我們現在回顧一下這個表的結構,其實這個表的結構是相當簡單的,只有兩列數據,分別是id和c1,我們可以往這個表中插入一些數據
再來看一下這個表的內容,我們先插入一些數據,為了下面演示方便呢,我們來看,我們來看一下表的內容insert into myinnodb values(2,'bb'),(3,'cc');select * from myinnodb;
這個表一共有兩行數據,一個是id為2,一個是id為3,現在我們就可以開始我們的測試了,測試需要兩個連接來請求兩個事務,在一個連接中呢,我們啟動一個事務,并在第一個表的記錄加一個獨占鎖,這里啟動一個事務就是begin,這里我們就啟動了一個事務,我們來給這個把表的第一行加一個獨占鎖,set c1='bbb',條件id等于2的,我們id等于2的加了一個獨占鎖begin;update myinnodb set c1='bbb' where id = 2;
我們對他不可以提交,我們來看一下相同行數據的情況,id等于2select * from myinnodb where id = 2;
我們看到的還是更新之前的數據,那么問題出現了,大家可以看到,在連接2中查詢呢,并沒有被連接1上的獨占鎖給阻塞,這和我們上面的兼容性情況完全不同,這是為什么呢,這是innodb實現鎖的獨到之處,Innodb用到了我們上面提到的undo log記錄,所以呢,我們在第二個連接中查看的數據呢,實際上是存在undo log中的版本,并不是我們在第一個連接中所更新的,他看到的還是老的數據版本,所以innodb在實現鎖上還是相當復雜的,其實在innodb中呢,還存在異向共享鎖和異向獨占鎖兩種鎖,這是為了在不同力度上進行加鎖而設計的,下面我們來看看鎖的粒度是什么,熟悉數據倉庫的朋友呢,可能對粒度的含義很清楚了,所謂鎖的粒度呢,實際上也是鎖的策略,就是被加鎖的最小單位,比如在行上加鎖,那么最小單位就是行,這種鎖就稱之為行級鎖,如果的鎖的最小單位是頁,那么這個鎖也稱之為頁級鎖,同理,如果最小單位是表的話,這個鎖的粒度是表級鎖,這種提高并發的方式呢,讓鎖定義的對象盡可能的小,最理想的方式呢,只需要對需要修改的數據進行精確的鎖定,任何時候在給定的資源上,鎖定的數據越小,數據的并發性能也就越高,只要相互之間不產生阻塞,就可以了,我們來看一下MYSQL的兩種鎖的粒度,首先第一種呢是表級鎖,就是MYSQL中,最基本的鎖策略,也是開銷最小的策略,開銷小呢,意味著并發性就會低,表鎖會在加鎖時呢,鎖定整張表,一個用戶在對表進行寫操作前,需要獲得寫鎖,就會阻塞其他用戶讀寫操作,只有沒有寫鎖時呢,他讀取的用戶呢,才能獲得鎖,讀鎖之前說了,相互間是不會阻塞的,表級鎖呢通常是在MYSQL服務器上所實現的,所以雖然Innodb實現了行級鎖,但是在一些時候,MYSQL數據服務層呢,還是會對Innodb加上表級鎖,比如我們在做alter table操作時,為了讓大家更直觀的了解MYSQL中表級鎖,還是通過實驗來讓大家看一下表的效果,還是用之前的myinnodb這張表吧,大家知道這張表呢是innodb存儲引擎的表這里呢可以來看一下,我們把剛才的事務呢rollback掉rollback;這個時候我們再來看一下這張表的定義show create table myinnodb;
這張表呢是一張innodb存儲引擎的表,默認是在表上加行級鎖的,我們怎么讓這張表加表級鎖呢,其實很簡單,這個實驗我們同樣需要兩個連接,在第一個連接上我們只需要執行下面這個命令,lock table myinnodb write;這樣就給myinnodb加上一個表級的獨占鎖
我們在第二個連接上進行上面的查詢,我們看會怎么樣select * from myinnodb;大家可以看到,這個時候這個操作就被阻塞了
知道在第一個連接上執行解鎖操作時,那么第二個連接上的查詢才會被執行unlock tables;
MYSQL常見的粒度呢就是行級鎖,行級鎖可以最大程度的支持并發處理,當然鎖的開銷要比表級鎖要大,目前innodb和其他的存儲引擎已經實現了行級鎖,行級鎖是在存儲引擎中進行實現,而MYSQL服務器并沒有實現,關于行級鎖我們之前已經介紹了很多了,所以就不再多說了
?
總結
以上是生活随笔為你收集整理的Innodb存储引擎的特性(1).的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL常用存储引擎之Innodb
- 下一篇: Innodb存储引擎的特性(2)