MySQL存儲引擎
-
MySQL是插件式存儲存儲引擎漏健,支持多種存儲引擎
-
常見的存儲引擎有:MyISAM, Aria, InnoDB, MRG_MYISAM, CSV, BLACKHOLE, MEMORY, PERFORMANCE_SCHEMA, ARCHIVE, FEDERATED
mysql> SHOW ENGINES; #查看支持多少種存儲引擎 *************************** 1. row *************************** Engine: FEDERATED #引擎名稱 Support: NO #是否支持 Comment: Federated MySQL storage engine #簡要注釋 Transactions: NULL #是否支持事務(wù)功能 XA: NULL #是否支持分布式事務(wù)功能 Savepoints: NULL # 是否支持保存點功能 *************************** 2. row ***************************
...
-
-
存儲引擎是表級別的概念婉刀,因此又稱為“表類型”损话;不建議在同一個庫中的表上使用不同的ENGINE;
CREATE TABLE ... ENGINE[=]STORAGE_ENGINE_NAME ... SHOW TABLE STATUS
1. InnoDB存儲引擎
InnoDB存儲引擎翎碑,把數(shù)據(jù)存儲在一個文件中谬返,是個黑盒,根varnish是一樣日杈,varnish中的數(shù)據(jù)緩存都存儲在一個文件中遣铝,但其內(nèi)部完全有自組織有序的結(jié)果從外部看來就是一個文件,內(nèi)部可以有自己的元數(shù)據(jù)莉擒,數(shù)據(jù)是構(gòu)建在文件系統(tǒng)之上的文件系統(tǒng)蚪拦;而InnoDB也是這樣匆绣,默認情況下可以將n張表放在一個表空間里媒殉,在外部看來就是一個表交播,其內(nèi)部存放了n張表甚至存放了n張表的索引檀何;不過把n張表的索引放在同一表中很難實現(xiàn)高級功能蝇裤;比如像單表導(dǎo)入導(dǎo)出等;因此频鉴,這就是為什么在安裝MariaDB時栓辜,都要求使用innodb_file_per_table這表示每張表使用一個表空間;
InnoDB的表空間為了能跨文件系統(tǒng)(分區(qū))垛孔,InnoDB的表空間背后所對應(yīng)的文件 可以不止一個藕甩,而且還可以自動增長;表空間剛創(chuàng)建時周荐,就占用固定大小的空間狭莱,如果再許愿空間時,就又占用固定大小的空間概作,用不用都占用腋妙;可理解為是基于步進的方式進行劃分;InnoDB將所有的表和索引放在一個表空間中讯榕;
如果所有表和數(shù)據(jù)都存儲在一個表空間中時骤素,表空間文件是存儲在datadir定義的目錄中的匙睹;
如果每張表單獨存儲在一個表空間中,則表空間文件是放置在數(shù)據(jù)庫目錄下济竹,而不是數(shù)據(jù)目錄下痕檬;例如有一個數(shù)據(jù)庫叫mydb就相當于在數(shù)據(jù)庫目錄下創(chuàng)建一個mydb的目錄而已;
當然數(shù)據(jù)庫目錄有可能在數(shù)據(jù)目錄下的子目錄送浊;
MariaDB [(none)]> SHOW ENGINES\G;
...
*************************** 6. row ***************************
Engine: InnoDB
Support: DEFAULT
Comment: Percona-XtraDB, Supports transactions, row-level locking, and foreign keys
Transactions: YES
XA: YES
Savepoints: YES
-
數(shù)據(jù)存儲于“表空間(table space)”中梦谜,是個黑盒:有兩種管理方式:
(1) 所有數(shù)據(jù)庫中的所有類型為InnoDB的表的數(shù)據(jù)和索引存儲于同一個表空間中;- 表空間文件:存儲在datadir定義的目錄下罕袋;
- 表現(xiàn)出的文件為:ibddata1改淑,ibddata2,...
(2) 每個表單獨使用一個表空間存儲表的數(shù)據(jù)和索引浴讯;使用innodb_file_per_table=ON
開啟朵夏; - 數(shù)據(jù)文件(存儲數(shù)據(jù)和索引)名:tb1_name.frm
- 每張表由2個文件組成:tb1_name.ldb和tb1_name.frm
- 文件存儲于數(shù)據(jù)庫目錄中
注:基于第一種方式管理時,所有數(shù)據(jù)庫的InnoDB表將使用同一個表空間榆纽,例如有10個庫仰猖,每個庫中有100張表,都放在同一個表空間中奈籽,于后期管理無益饥侵。
-
InnoDB存儲引擎是事務(wù)性存儲引擎,適合處理大量的短期任務(wù)衣屏;
- 基于MVCC(Mutli Version Concurrenvy Contro躏升,多版本并發(fā)控制)支持高并發(fā),支持所有的四個隔離級別狼忱;默認支持間隙鎖防止幻讀膨疏;
- 使用聚簇索引(一般是主鍵索引);
- 一張表的聚簇索引只能有一個钻弄;索引在哪數(shù)據(jù)就在哪里
- 支持自適應(yīng)hash索引佃却;
- 鎖粒度:行級鎖,間隙鎖窘俺;
注意:級別越高事務(wù)發(fā)生沖突性越小饲帅,事務(wù)安全性越高但并發(fā)性能就越低;
注:MVCC瘤泪,multi version concurrency control:多版本并發(fā)訪問控制灶泵,它就是類似于lvm的快照功能;也就意味著对途,當啟動n個事務(wù)時丘逸,每一個事務(wù),都針對于mysql當中的InnoDB存儲引擎現(xiàn)有數(shù)據(jù)做一個快照掀宋; 每一個快照深纲,通過快照過去訪問時間點是一致的仲锄,所以現(xiàn)在要啟動一個事務(wù),就對InnoDB數(shù)據(jù)集做個快照湃鹊,就在快照基礎(chǔ)上做操作儒喊;因此有50個事務(wù)為了彼此間不受影響,每個事務(wù)啟動一次做一個快照币呵。
但是怀愧,這病不意味著就沒有沖突,想象以下余赢,如果第一個快照和第二個也快照了芯义,兩個操作同一個數(shù)據(jù)集,一個刪了一行妻柒,而第二個事務(wù)把這個行改了扛拨,此時就會出現(xiàn)問題,所以举塔,必須有隔離機制來實現(xiàn)所謂的事務(wù)隔離绑警;
而事務(wù)隔離中最核心組件就是鎖;這么一來事務(wù)也沒法并發(fā)了央渣,既然鎖了计盒,看上去事務(wù)同時啟動,但是還得等待一個個完成芽丹;所以北启,隔離級別至關(guān)重要了;
另:percona公司對mysql做了二次開發(fā)拔第,服務(wù)器版本為percona-server咕村,把InnoDB改進為XtraDB存儲引擎,mariadb使用了XtraDB引擎楼肪,但是名稱依然叫InnoDB
總結(jié)InnoDB引擎的特性:
- 存儲數(shù)據(jù):表空間
- 并發(fā):MVCC培廓,間隙鎖
- 索引:聚集索引惹悄、輔助索引
- 性能:預(yù)讀操作春叫、自適應(yīng)hash索引、插入操作緩存區(qū)
- 備份:支持熱備
SHOW ENGINE INNODB STATUS;
2. MyISAM存儲引擎
MyISAM內(nèi)部的復(fù)雜機制很少泣港,特別適應(yīng)于讀多寫少的應(yīng)用暂殖;但是,mysql自己的表当纱,內(nèi)部的元數(shù)據(jù)的庫還是使用的MyISAM存儲引擎呛每;
MyISAM存儲引擎最大特性是支持全文索引,全文索引指的是全文中的每一個關(guān)鍵字都可以被搜索坡氯;
MyISAM在崩潰后無法安全恢復(fù)晨横,有可能會導(dǎo)致某些數(shù)據(jù)丟失洋腮,比如要插入一行數(shù)據(jù),剛插入一般數(shù)據(jù)庫崩潰手形,只能把剛插入的半行刪了啥供,保證數(shù)據(jù)是一致性的;解決辦法是使用MyISAM表修復(fù)工具库糠,會對全表掃描伙狐,一行行掃描,看哪一行中的數(shù)據(jù)不是完整的給它刪了瞬欧,所以這就是崩潰后的恢復(fù)贷屎,如果表要大的話,恢復(fù)時間會非常長艘虎;索引說可以接受較長時間的修復(fù)操作才能使用MyISAM;這個較長時間還是指的較小的表唉侄,如果表答可能修復(fù)一天都有可能。
MariaDB雖然支持MyISAM存儲引擎但是顷帖,默認對于MyISAM而言使用的是Aria存儲引擎美旧,其實就是MyISAM的增強版,支持崩潰后的安全恢復(fù)贬墩;
MyISAM存儲引擎的文件榴嗅,表和索引是獨立存放的;索引可看出來使用的是非聚集索引陶舞;因此嗽测,每一個索引的葉子節(jié)點,都是個指針肿孵,指向了真正數(shù)據(jù)所在的位置唠粥;這就類似于書中的目錄和后面正文的關(guān)系;
對于InnoDB停做,每張表使用兩個文件一個是用來存儲數(shù)據(jù)和索引的.ibd文件晤愧,一個是用來存儲表格式的.frm格式的文件;而對于MyISAM蛉腌,每張表有三個文件且都放在數(shù)據(jù)庫目錄下而不是datadir=指定的目錄下官份,也就是說的datadir指定的目錄下的子目錄里;
- tbl_name.frm:表格式定義烙丛;
- tbl_name.MYD:數(shù)據(jù)文件舅巷;
- tbl_name.MYI:索引文件;
MariaDB [(none)]> SHOW ENGINES\G;
*************************** 5. row ***************************
Engine: MyISAM
Support: YES
Comment: MyISAM storage engine
Transactions: NO
XA: NO
Savepoints: NO
總結(jié)MyISAM存儲引擎特性:
- 加鎖好并發(fā):支持表級鎖
- 修復(fù):只能手動或自動修復(fù)(使用工具)河咽、但可能會丟失數(shù)據(jù)钠右;并不是安全恢復(fù)
- 索引:使用的是非聚集索引
- 支持延遲更新索引:只是為了提高性能
- 支持表壓縮:壓縮后表數(shù)據(jù)不能修改
行格式:
{DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}
-
dynamic:
動態(tài)行 -
fixed
:固定行 -
compressed:
壓縮行 -
compact:
緊致行 -
redundent:
冗余行
態(tài)還是固定行取決于表中字段的類型,例如字段的類型是varchar類型長度是可變的忘蟹,如果某一字段使用varchar類型飒房,每行可以不同的長度搁凸;行長度不一樣管理很麻煩,性能比較低狠毯;行的長度一樣只需根據(jù)距離來判斷下一行在什么位置就可以了坪仇;
以上InnoDB和MyISAM是mysql中最為經(jīng)典的兩種存儲引擎;
MariaDB [hellodb]> SHOW ENGINES; #查看所有支持的存儲引擎
+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| CSV | YES | CSV storage engine | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| InnoDB | DEFAULT | Percona-XtraDB, Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
| FEDERATED | YES | FederatedX pluggable storage engine |
MariaDB [hellodb]> SHOW GLOBAL VARIABLES LIKE '%STORAGE%'; #查看默認存儲引擎
+------------------------+--------+
| Variable_name | Value |
+------------------------+--------+
| default_storage_engine | InnoDB |
| storage_engine | InnoDB |
+------------------------+--------+
3. 其他存儲引擎
- CSV:將普通的CSV文件(字段基于逗號分隔)作為MySQL表使用垃你;
- 所謂CSV文件:一個文件中也是有很多行組成椅文,每一行有很多字段組成,而字段用逗號分隔惜颇,把整個文件當表使用皆刺;
- CVS文件好處在于可以使用grep、awk凌摄、sed工具直接處理羡蛾,但是由于基于文本存儲的,浮點型數(shù)據(jù)轉(zhuǎn)換為文本字符串存儲后會丟失精度
- CVS特別適合用于在多個不同的數(shù)據(jù)庫之間共享數(shù)據(jù)時使用
- MRG_MYISAM:由多個MyISAM表合并成的虛擬表
- 表可以分割成小表锨亏,就像zabbix中數(shù)據(jù)一樣痴怨,把表分成多個小標按天存放,一天一張表器予,要想刪除時浪藻,直接刪除某天的表即可;每一天的表其實就是一個表分區(qū)table partion
- 要查詢多張表是合并即可
- BLACKHOLE:類似于/dev/null乾翔,不真正存儲任何數(shù)據(jù)爱葵,只會在特定場景中使用
- 對mysql而言blachole stroage engine相當于linux上的/dev/null,索引某張表的存儲引擎是該類型反浓,這個表存儲的所有數(shù)據(jù)都不會產(chǎn)生任何IO萌丈,因為數(shù)據(jù)被丟棄了
- 只在特定的場景中使用:比如多級架構(gòu)執(zhí)行復(fù)制操作時;
- MEMORY:基于內(nèi)存存儲雷则,支持hash索引辆雾,表級鎖,常用語臨時表月劈;
- PERFORMANCE_SCHEMA:類似于Linux/proc目錄度迂,用于存儲mysql的性能數(shù)據(jù);
- 是關(guān)于mysql性能各類統(tǒng)計的收集存儲的表艺栈,只用來收集mysql運行中的統(tǒng)計數(shù)據(jù)英岭,做性能評估湾盒,或者是有助于優(yōu)化器優(yōu)化湿右;
- 表中的統(tǒng)計數(shù)據(jù)只對當前有效,一旦mysql停機罚勾,這個表就作廢變?yōu)榭盏囊闳耍瑔雍缶蜁粩嗟奶钊牒芏嗍占降呐c性能相關(guān)的數(shù)據(jù)
- 此存儲引擎用處在于mysql為了達到一切皆sql表的目的吭狡,索引把它內(nèi)部的統(tǒng)計數(shù)據(jù)基于sql接口進行輸出了
- ARCHIVE:支持SELECT 和INSERT 操作,支持行級鎖和專用緩存區(qū)丈莺;
- 用于數(shù)據(jù)永久存儲并且當做數(shù)據(jù)倉庫使用划煮;不支持修改操作
- FEDERATED:類似于MRG_MYISAM,不用支出在于MRG_MYISAM所合并的多張表一定是同一個mysql服務(wù)器上的缔俄,甚至是同一個數(shù)據(jù)庫中的多張表弛秋;但是FEDERATED能把兩個數(shù)據(jù)庫服務(wù)器上的表聯(lián)合在一起使用
- 用于訪問其它的遠程的MySQL Server的代理接口,它通過創(chuàng)建一個到遠程MySQL Server的客戶端連接俐载,并將查詢語句傳輸至遠程服務(wù)器執(zhí)行蟹略;
- 自己本地沒有表,但可以把這個當做接口遏佣,所有發(fā)給FEDERATED存儲引擎表的所有語句挖炬,都會基于mysql連接發(fā)給另一個數(shù)據(jù)庫服務(wù)器上另外一張表,而后完成數(shù)據(jù)存茸瓷簟意敛;
注:FEDERATED也僅支持mariadb;是夸數(shù)據(jù)庫服務(wù)器的角色
4. MariaDB支持的其他存儲引擎
- OQGraph:支持實體存儲
- Sphinx SE:搜索引擎
- 而mariadb支持sphinxSE存儲引擎膛虫,意味著草姻,這個表存儲的所有數(shù)據(jù)都直接基于sphinxSE接口導(dǎo)入到sphinx存儲里了;
- TokuDB:支持海量數(shù)據(jù)的存儲引擎稍刀,支持原生分布式存儲
- Cassandra:由facebook研發(fā)碴倾,分布式無中心的存儲;
- mariadb支持把表存儲Cassandra以后掉丽,沒有在mysql本地存儲跌榔,而是導(dǎo)入到Cassandra表中;
- CONNECT存儲引擎
- SQUENCE存儲引擎
MySQL事務(wù)
并發(fā)控制:
鎖是mysql實現(xiàn)并發(fā)訪問控制的重要組件捶障;
為什么要有鎖機制:
任何文件或數(shù)據(jù)集只要支持并發(fā)訪問模型僧须,就必須基于鎖機制對其機制進行控制;對mysql服務(wù)器项炼,允許多個線程同時連進來支持做讀寫操作請求担平,這樣多個查詢語句就有可能只對同一個數(shù)據(jù)集進行,例如第一個線程對數(shù)據(jù)集中的某行做修改锭部,第二個線程對同一個數(shù)據(jù)集中的同一行做查詢暂论,這樣二者同時操作就會帶來混亂;
所以拌禾,mysql為了能夠?qū)崿F(xiàn)并發(fā)訪問中避免數(shù)據(jù)讀寫沖突取胎,就必須施加所機制。-
鎖類型:
- 讀鎖:共享鎖,可以共享給其他的讀操作
- 寫鎖:獨占所闻蛀,其他操作不可讀寫
-
鎖粒度:
- 表級鎖:在表級別施加鎖匪傍,并發(fā)性較低;
- 行級鎖:在行級別施加鎖觉痛,并發(fā)性較高役衡;維持鎖狀態(tài)的成本較大;
- 頁級鎖(早些時候支持)
-
所策略: 在鎖粒度及數(shù)據(jù)安全性之間尋求一種平衡機制薪棒;
- 存儲引擎:每種存儲引擎都可以自行實現(xiàn)其所策略和鎖粒度
- MySQL Server:表級別手蝎,可自行決定,也允許顯示請求俐芯;
-
根據(jù)所本身根據(jù)用戶手動施加還是由服務(wù)器自動實現(xiàn)柑船,鎖又可以分兩種類型:
顯式鎖:用火狐手動請求施加的鎖
-
隱式鎖:有存儲引擎(或mysql服務(wù)器)自行根據(jù)需要施加的鎖;
顯示鎖使用:
(1) LOCK TABLES 命令:鎖定整張表或多張表
用法:LOCK TABLES tbl_name [[AS] alias] lock_type [,tbl_name [[AS] alias ] lock_type] ...
lock_type : 所類型 READ[ LOCAL] | [LOW_PRIORITY] WRITE
tbl_name: 鎖名稱UNLOCK TABLES; 解鎖泼各; (2) FLUSH TABLES 命令:作用在于如果一張表被打開了鞍时,需要把內(nèi)存中的所有數(shù)據(jù)都清到磁盤上,在把表關(guān)閉扣蜻; 用法:FLUSH TABLES tbl_name[,...] [WITH READ LOCK] [FOR UPDATE] WITH READ LOCK: 施加讀鎖 FOR UPDATE: 請求修改逆巍,即施加寫鎖 (3) SELECT 語句:鎖定表中的某些行 用法:SELECT clause [FOR UPDATE] [WITH READ LOCK]
示例:
MariaDB [(none)]> CREATE DATABASE testdb; #創(chuàng)建數(shù)據(jù)庫
Query OK, 1 row affected (0.01 sec)
MariaDB [(none)]> USE testdb
Database changed
MariaDB [testdb]> CREATE TABLE tbl; #創(chuàng)建表
ERROR 1113 (42000): A table must have at least 1 column
MariaDB [testdb]> CREATE TABLE tbl (id INT NOT NULL ,name VARCHAR(50)); #插入數(shù)據(jù)
Query OK, 0 rows affected (0.05 sec)
MariaDB [testdb]> INSERT INTO tbl (id,name) VALUE (1,'TOM');
Query OK, 1 row affected (0.01 sec)
MariaDB [testdb]> SELECT * FROM tbl;
+----+------+
| id | name |
+----+------+
| 1 | TOM |
+----+------+
1 row in set (0.01 sec)
MariaDB [testdb]> LOCK TABLE tbl READ; #施加讀鎖
Query OK, 0 rows affected (0.00 sec)
另外啟動一個線程:
MariaDB [(none)]> use testdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [testdb]> SELECT * FROM tbl;
+----+------+
| id | name |
+----+------+
| 1 | TOM |
+----+------+
1 row in set (0.00 sec)
MariaDB [testdb]> INSERT INTO tbl (id,name) VALUE (2,‘JERRY’); #插入數(shù)據(jù)被阻塞
線程1釋放鎖:
MariaDB [testdb]> UNLOCK TABLES;
Query OK, 0 rows affected (0.00 sec)
線程2插入數(shù)據(jù)成功:
MariaDB [testdb]> INSERT INTO tbl (id,name) VALUE (2,'JERRY');
Query OK, 1 row affected (0.01 sec)
事務(wù)日志:
事務(wù)日志就是mysql數(shù)據(jù)文件之外的另外一個存儲區(qū)域,這個存儲區(qū)域帶來的作用是:當一個事務(wù)型存儲引擎在運行過程中莽使,需要啟動一個事務(wù)并完成數(shù)據(jù)修改時锐极,所有的修改操作(由多個sql語句組成),每一次的操作所涉及到的數(shù)據(jù)修改芳肌,這個修改的操作要轉(zhuǎn)換成底層存儲引擎所支持的相關(guān)操作的操作過程灵再,它會把每一次的sql語句所涉及的操作步驟,具體的過程記錄在事務(wù)日志文件中亿笤。
注意翎迁,事務(wù)日志記錄的是每一步的具體操作;例如净薛,插入一行的數(shù)據(jù)是什么汪榔、插入什么位置、什么時候插入得等都記錄下來肃拜;再例如痴腌,如果是修改幾行,先修改哪行后修改哪行燃领、幾點開始修改士聪、幾點結(jié)束等等都記錄下來;而且這個日志要能夠重現(xiàn)操作就叫做事務(wù)日志猛蔽。
一個事務(wù)型存儲引擎它的操作借助于事務(wù)日志來保證其對應(yīng)的事務(wù)特性剥悟;所以,任何事務(wù)型存儲引擎的相關(guān)操作,默認不會直接寫在數(shù)據(jù)庫文件上懦胞,而是先寫在事務(wù)日志中,并且事務(wù)日志為保證足夠可靠凉泄,基本上很少在內(nèi)存中緩沖躏尉,寫完建基本比較差,都會先寫在內(nèi)存上后众,然后等過一會再同步到磁盤上胀糜;事務(wù)日志也有這段緩沖區(qū),但這個緩沖區(qū)不能太大時間也不能太久蒂誉,因為如果允許緩存5秒鐘教藻,系統(tǒng)崩潰最大會丟失5秒的數(shù)據(jù),所以建議這個時間要足夠短右锨,一般為1秒鐘同步到磁盤上一次括堤;但是,同步越頻繁性能就越差绍移,數(shù)據(jù)可靠性就越高悄窃。
事務(wù)日志的每一步在記錄時,還會把修改之前的原始數(shù)據(jù)內(nèi)容也記錄下來蹂窖,這是為了支持undo和redo機制而記錄的轧抗;即當記錄的是修改數(shù)據(jù)時會把又該的數(shù)據(jù)之前的數(shù)據(jù)記錄下來。假如瞬测,操作進行到一半服務(wù)器崩潰了横媚,把修改的操作日志撤銷了即可,因為還沒有同步到磁盤上月趟;如為例如保證數(shù)據(jù)的穩(wěn)定性灯蝴,一個大事務(wù)中間有可能事務(wù)還沒完成,已經(jīng)在事務(wù)日志記錄了30個孝宗,再記錄事務(wù)日志會先把一部分信息往磁盤上同步绽乔,開始真正修改原始數(shù)據(jù)了,這時如果崩潰碳褒,則只能把已經(jīng)同步到表中的數(shù)據(jù)撤銷折砸,這就是undo機制;
還有一種情況是沙峻,比如一個事務(wù)有60個sql語句都寫完了且都記錄在事務(wù)日志中了睦授,但只有氣筒30個同步到了磁盤上,如果此時崩潰摔寨,則此時數(shù)據(jù)是不一致的去枷;因為有些事務(wù)已經(jīng)提交,但是沒有存儲到磁盤上,這樣就必須把事務(wù)日志中為完成的語句同步到磁盤上删顶,這就是redo機制竖螃;
同步的要做提交,沒能完成的要做回滾逗余,這就是崩潰后恢復(fù)特咆。
如果日志文件非常大,恰好寫滿了崩潰录粱,下次啟動mysql時腻格,必須把里面的所有語句統(tǒng)統(tǒng)同步到磁盤才能正常啟動,啥繁;如果事務(wù)日志文件大道2G菜职,為了能夠把2G的語句同步到磁盤上,有可能mysql服務(wù)器啟動半小時旗闽,所以為了避免崩潰后啟動時間太長酬核,把日志文件設(shè)置小一點;但是适室,有事會出現(xiàn)日志填滿了愁茁,但是日志內(nèi)容還沒來的急同步到磁盤上,還有新的日志需要寫進來亭病,那么久在啟動一個文件鹅很;也就是說日志文件一般啟動2個或3個是輪轉(zhuǎn)使用的,所謂輪轉(zhuǎn)指的是第一個日志文件填滿了就用第二個罪帖,同時把第一個日志文件同步到磁盤上促煮,等第二個日志寫滿了就可以再使用第一個了,這樣輪轉(zhuǎn)使用整袁,由多個事務(wù)日志文件組成的叫做事務(wù)日志組菠齿,日志組內(nèi)至少應(yīng)該有2個文件,但是多了同樣不好坐昙。
事務(wù)日志文件和數(shù)據(jù)文件不應(yīng)該放在同一磁盤上绳匀,因為會對磁盤寫IO操作帶來很大壓力,影響其性能炸客;分開存放比較理想疾棵,但是有些場景又要必須放在一起,例如基于邏輯卷操作時痹仙;
如果事務(wù)日志所在磁盤崩潰是尔,則數(shù)據(jù)庫數(shù)據(jù)無法保持一致;所以开仰,要把事務(wù)日志磁盤做鏡像拟枚;建議使用raid1薪铜;數(shù)據(jù)文件也很重要建議使用raid10;
- 事務(wù):一組原子性的SQL查詢恩溅,或者多個SQL語句組成了一個獨立的工作單元
- 事務(wù)日志:將隨機寫轉(zhuǎn)換為順序?qū)?br>
innodb_log_files_in_group
:一個日志組內(nèi)有多少個日志文件隔箍,默認2個;
innodb_log_group_home_dir
:日志組目錄路徑脚乡,當前目錄就是datadir指定的路徑
innodb_log_file_size
:每一個InnoDB事務(wù)日志的大小蜒滩,默認5M
innodb_mirrored_log_groups
修改配置文件,重啟生效每窖;這些參數(shù)帮掉,建議在mysql初始化時就要設(shè)置好再啟動弦悉,而不能在啟動后再修改參數(shù)是不理想的做法窒典;
- 事務(wù)日志:將隨機寫轉(zhuǎn)換為順序?qū)?br>
- ACID測試:從四個角度判斷存儲引擎是否支持事務(wù)
- A:automicity,原子性稽莉;整個事務(wù)中的所有操作要么全部成功執(zhí)行瀑志,要么全部失敗后回滾;
- C:consistency污秆,一致性劈猪;數(shù)據(jù)庫總是從一個一致性狀態(tài)轉(zhuǎn)換為另一個一致性狀態(tài);
- I:isolation良拼,隔離性战得;一個事務(wù)所做出的操作在提交之前,是不能為其它事務(wù)所見的庸推,隔離有多種級別常侦,主要是為了并發(fā),隔離級別一個有4個贬媒;
- D:durability聋亡,持久性;事務(wù)一旦提交际乘,其所做的修改就會永久保存于數(shù)據(jù)庫中坡倔;
注意:MyISAM存儲引擎是不支持事務(wù)的,InnoDB支持事務(wù)脖含,所以要想使用事務(wù)得確保使用的是InnoDB等支持事務(wù)的存儲引擎罪塔;
-
mysql默認把每個語句當做一個事務(wù)提交,可以手動關(guān)閉自動提交功能养葵,手動來啟動事務(wù)垢袱;
啟動事務(wù):START TRANSACTION 結(jié)束事務(wù): (1)完成,提交:COMMIT (2)未完成港柜,回滾:ROLLBACK 回滾時如果做過時間點保存可以一點點回滾请契; 事務(wù)支持savepoint SAVEPINIT identifier咳榜;設(shè)置保存點 ROLLBACK TO [SAVEPOINT] identifier;回滾到指定保存點爽锥,默認回滾到最開始處 RELEASE SAVEPOINT identifier涌韩;釋放保存點
示例:
查看是否開啟自動提交:
MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE '%commit%';
+-------------------------------------------+-------+
| Variable_name | Value |
+-------------------------------------------+-------+
| aria_group_commit | none |
| aria_group_commit_interval | 0 |
| autocommit | ON |
| innodb_commit_concurrency | 0 |
| innodb_flush_log_at_trx_commit | 1 |
| innodb_use_global_flush_log_at_trx_commit | ON |
+-------------------------------------------+-------+
autocommit=ON:自動提交,把每一個執(zhí)行的語句當做一個事務(wù)氯夷,執(zhí)行語句就提交臣樱,因為每一次事務(wù)提交都會導(dǎo)致數(shù)據(jù)要從事務(wù)日志緩沖區(qū)寫到事務(wù)日志,隨后還要從事務(wù)日志寫到數(shù)據(jù)文件腮考;這很可能會影響性能雇毫,而且很多時候多個語句才是一個事務(wù);
因此可以使用set修改變量踩蔚,關(guān)閉自動提交功能棚放;
MariaDB [(none)]> SET @@SESSION.autocommit=OFF; #修改session級別的參數(shù),關(guān)閉自動提交
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> SHOW VARIABLES LIKE 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | OFF |
+---------------+-------+
示例:
手動啟動事務(wù):
MariaDB [(none)]> START TRANSACTION;
MariaDB [(none)]> use testdb;
Database changed
MariaDB [testdb]> SELECT * FROM tbl;
+----+-------+
| id | name |
+----+-------+
| 1 | TOM |
| 2 | JERRY |
+----+-------+
2 rows in set (0.00 sec)
MariaDB [testdb]> INSERT INTO tbl (id,name) VALUE (3,'LUCY');
Query OK, 1 row affected (0.01 sec)
MariaDB [testdb]> UPDATE tbl SET name='guojing' WHERE id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MariaDB [testdb]> SELECT * FROM tbl;
+----+---------+
| id | name |
+----+---------+
| 1 | guojing |
| 2 | JERRY |
| 3 | LUCY |
+----+---------+
3 rows in set (0.00 sec)
MariaDB [testdb]> ROLLBACK; #手動回滾馅闽,結(jié)束事務(wù)
Query OK, 0 rows affected (0.01 sec)
MariaDB [testdb]> SELECT * FROM tbl;
+----+-------+
| id | name |
+----+-------+
| 1 | TOM |
| 2 | JERRY |
+----+-------+
2 rows in set (0.00 sec)
示例2:
MariaDB [testdb]> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
MariaDB [testdb]> INSERT INTO tbl VALUE (3,'LUCK'),(4,'MURNN');
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
MariaDB [testdb]> SELECT * FROM tbl;
+----+-------+
| id | name |
+----+-------+
| 1 | TOM |
| 2 | JERRY |
| 3 | LUCK |
| 4 | MURNN |
+----+-------+
4 rows in set (0.00 sec)
MariaDB [testdb]> SAVEPOINT first; #做時間點飘蚯,名稱為first
Query OK, 0 rows affected (0.00 sec)
MariaDB [testdb]> UPDATE tbl SET name='guojing' WHERE id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MariaDB [testdb]> SAVEPOINT second; #做第二個時間保存點,名稱為second
Query OK, 0 rows affected (0.00 sec)
MariaDB [testdb]> INSERT INTO tbl VALUE (5,'HAHA');
Query OK, 1 row affected (0.00 sec)
MariaDB [testdb]> SELECT * FROM tbl;
+----+---------+
| id | name |
+----+---------+
| 1 | guojing |
| 2 | JERRY |
| 3 | LUCK |
| 4 | MURNN |
| 5 | HAHA |
+----+---------+
5 rows in set (0.00 sec)
MariaDB [testdb]> ROLLBACK TO second; #回滾到第二個保存點
Query OK, 0 rows affected (0.00 sec)
MariaDB [testdb]> SELECT * FROM tbl;
+----+---------+
| id | name |
+----+---------+
| 1 | guojing |
| 2 | JERRY |
| 3 | LUCK |
| 4 | MURNN |
+----+---------+
4 rows in set (0.00 sec)
MariaDB [testdb]> ROLLBACK TO first; #回滾到第一個保存點
Query OK, 0 rows affected (0.00 sec)
MariaDB [testdb]> SELECT * FROM tbl;
+----+-------+
| id | name |
+----+-------+
| 1 | TOM |
| 2 | JERRY |
| 3 | LUCK |
| 4 | MURNN |
+----+-------+
4 rows in set (0.00 sec)
MariaDB [testdb]> COMMIT; 手動提交福也,結(jié)束事務(wù)
Query OK, 0 rows affected (0.01 sec)
建議:手動顯示請求和提交事務(wù)局骤,不要使用自動提交功能
事務(wù)的隔離級別:
由低到高,分為4個級別:
第一級別:read-uncommitted;讀未提交--> 會存在臟讀;
看到數(shù)據(jù)可能是未提交的度帮,別人回滾后傻工,看到的數(shù)據(jù)不準確;第二級別:read-committed;讀提交--> 會產(chǎn)生不可重復(fù)讀;
只有別人提交后才能看到數(shù)據(jù),解決了臟讀泣洞;
不可重復(fù)讀,指的是同一事務(wù)中兩次讀取同一數(shù)據(jù)得到內(nèi)容不一樣默色;就是別人沒提交時讀到的內(nèi)容球凰,別人修改數(shù)據(jù)提交后又讀到的,兩次讀取的結(jié)果不同腿宰;這就叫不可重復(fù)讀呕诉;第三級別:repeatable-read;可重讀--> 會產(chǎn)生幻讀吃度;默認級別;
兩次讀取數(shù)據(jù)甩挫,只要自己沒提交,不管別人提沒提交椿每,自己做一快照伊者,如果啟動事務(wù)時有三行數(shù)據(jù)英遭,讀的過程中只要自己不提交只有三行數(shù)據(jù),但是亦渗,外衣別的事務(wù)提交了數(shù)據(jù)挖诸,例如新增了幾個行,那幾行明明在法精,但自己假裝看不見多律,產(chǎn)生幻讀;-
第四級別:serializable搂蜓;可串行化--> 性能較差狼荞;
如果別人沒提交,讀的數(shù)據(jù)是別人沒提交的帮碰,要等待別人的事務(wù)完成才能讀取到相味,有先有后,避免了幻讀收毫;查看默認事務(wù)隔離級別: MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE '%tx%'; +---------------+-----------------+ | Variable_name | Value | +---------------+-----------------+ | tx_isolation | REPEATABLE-READ | +---------------+-----------------+ 設(shè)置隔離級別: MariaDB [(none)]> SET @@global.tx_isolation='READ-COMMITTED'; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE '%tx%'; +---------------+----------------+ | Variable_name | Value | +---------------+----------------+ | tx_isolation | READ-COMMITTED | +---------------+----------------+ 1 row in set (0.00 sec) 查看InnoDB存儲引擎的狀態(tài)信息: MariaDB [testdb]> SHOW ENGINE innodb STATUS\G;
MySQL是通過MVCC機制來實現(xiàn)事務(wù)隔離級別控制的攻走;為什么啟動2個事務(wù)殷勘,基于PREPEATABLE-READ 隔離級別修改數(shù)據(jù)但還能看到之前的數(shù)據(jù)此再,就是因為自己啟動了一個快照,而快照功能的創(chuàng)建玲销,刪除等等都是由事務(wù)功能mysql服務(wù)器自動在服務(wù)器級別進行管理的
示例:兩個線程输拇,分別驗證各個事務(wù)隔離級別的效果
(1)演示讀未提交,兩個線程控制臺均設(shè)置事務(wù)隔離級別為讀未提交,并關(guān)閉事務(wù)自動提交功能
MariaDB [testdb]> SET @@SESSION.tx_isolation='READ-UNCOMMITTED';
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> SET @@SESSION.autocommit=OFF;
Query OK, 0 rows affected (0.00 sec)
兩邊同時啟動事務(wù):
MariaDB [(none)]> START TRANSACTION;
線程1查看:
MariaDB [testdb]> SELECT * FROM tbl;
+----+-------+
| id | name |
+----+-------+
| 1 | TOM |
| 2 | JERRY |
| 3 | LUCK |
| 4 | MURNN |
+----+-------+
4 rows in set (0.00 sec)
線程2插入數(shù)據(jù):
MariaDB [testdb]> INSERT INTO tbl VALUE (5,'haha');
Query OK, 1 row affected (0.00 sec)
線程1再查看:
MariaDB [testdb]> SELECT * FROM tbl;
+----+-------+
| id | name |
+----+-------+
| 1 | TOM |
| 2 | JERRY |
| 3 | LUCK |
| 4 | MURNN |
| 5 | haha |
+----+-------+
5 rows in set (0.00 sec)
線程2:回滾贤斜,結(jié)束事務(wù):
MariaDB [testdb]> ROLLBACK;
Query OK, 0 rows affected (0.01 sec)
線程1再查看:
MariaDB [testdb]> SELECT * FROM tbl;
+----+-------+
| id | name |
+----+-------+
| 1 | TOM |
| 2 | JERRY |
| 3 | LUCK |
| 4 | MURNN |
+----+-------+
4 rows in set (0.00 sec)
MariaDB [testdb]> COMMIT; #提交結(jié)束事務(wù)
Query OK, 0 rows affected (0.00 sec)
示例:演示讀提交
兩個線程都改為讀提交策吠,并啟動事務(wù):
MariaDB [testdb]> SET @@SESSION.tx_isolation='READ-COMMITTED';
MariaDB [testdb]> START TRANSACTION;
線程1啟動查詢:
MariaDB [testdb]> SELECT * FROM tbl;
+----+-------+
| id | name |
+----+-------+
| 1 | TOM |
| 2 | JERRY |
| 3 | LUCK |
| 4 | MURNN |
+----+-------+
4 rows in set (0.01 sec)
線程2插入數(shù)據(jù)未提交:
MariaDB [testdb]> INSERT INTO tbl VALUE (5,'haha');
Query OK, 1 row affected (0.02 sec)
線程1再查看數(shù)據(jù)未變化:
MariaDB [testdb]> SELECT * FROM tbl;
+----+-------+
| id | name |
+----+-------+
| 1 | TOM |
| 2 | JERRY |
| 3 | LUCK |
| 4 | MURNN |
+----+-------+
4 rows in set (0.00 sec)
線程2提交事務(wù):
MariaDB [testdb]> COMMIT;
Query OK, 0 rows affected (0.02 sec)
線程1再查看,數(shù)據(jù)發(fā)生變化
MariaDB [testdb]> SELECT * FROM tbl;
+----+-------+
| id | name |
+----+-------+
| 1 | TOM |
| 2 | JERRY |
| 3 | LUCK |
| 4 | MURNN |
| 5 | haha |
+----+-------+
5 rows in set (0.00 sec)
MariaDB [testdb]> COMMIT; #提交事務(wù)
示例:演示幻讀瘩绒,可重復(fù)讀
兩個線程都修改事務(wù)級別為可重復(fù)讀猴抹,并啟動事務(wù):
mysql> SHOW GLOBAL VARIABLES LIKE '%iso%';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.00 sec)
mysql> SET @@SESSION.autocommit=OFF;
Query OK, 0 rows affected (0.02 sec)
線程1查看:
mysql> SELECT * FROM tbl;
+----+-------+
| id | name |
+----+-------+
| 1 | TOM |
| 2 | JERRY |
| 3 | LUCK |
| 4 | HAHA |
+----+-------+
4 rows in set (0.00 sec)
線程2刪除1行(未提交):
mysql> DELETE FROM tbl WHERE id=2;
Query OK, 1 row affected (0.01 sec)
mysql> SELECT * FROM tbl;
+----+------+
| id | name |
+----+------+
| 1 | TOM |
| 3 | LUCK |
| 4 | HAHA |
+----+------+
3 rows in set (0.00 sec)
線程1查看,未發(fā)生變化:
mysql> SELECT * FROM tbl;
+----+-------+
| id | name |
+----+-------+
| 1 | TOM |
| 2 | JERRY |
| 3 | LUCK |
| 4 | HAHA |
+----+-------+
4 rows in set (0.00 sec)
線程2提交:
mysql> COMMIT;
Query OK, 0 rows affected (0.07 sec)
線程1再查看锁荔,扔然未變化:
mysql> SELECT * FROM tbl;
+----+-------+
| id | name |
+----+-------+
| 1 | TOM |
| 2 | JERRY |
| 3 | LUCK |
| 4 | HAHA |
+----+-------+
4 rows in set (0.00 sec)
線程1提交事務(wù)后再查看數(shù)據(jù)發(fā)生變化:
mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM tbl;
+----+------+
| id | name |
+----+------+
| 1 | TOM |
| 3 | LUCK |
| 4 | HAHA |
+----+------+
3 rows in set (0.00 sec)
示例:演示可串行化
2個線程都設(shè)置事務(wù)隔離級別可串行化:
mysql> SET @@SESSION.transaction_isolation='SERIALIZABLE';
線程1查看:
mysql> SELECT * FROM tbl;
+----+-------+
| id | name |
+----+-------+
| 1 | TOM |
| 3 | LUCK |
| 4 | HAHA |
| 2 | JERRY |
+----+-------+
4 rows in set (0.00 sec)
線程2啟動事務(wù)蟀给,并插入數(shù)據(jù):
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO tbl VALUE (5,'HUANG RONG');
Query OK, 1 row affected (18.31 sec)
線程1啟動事務(wù)并查看,被阻塞:
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM tbl;
線程2提交事務(wù):
mysql> COMMIT;
Query OK, 0 rows affected (0.03 sec)
線程1查看:
mysql> SELECT * FROM tbl;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> SELECT * FROM tbl;
+----+------------+
| id | name |
+----+------------+
| 1 | TOM |
| 3 | LUCK |
| 4 | HAHA |
| 2 | JERRY |
| 5 | HUANG RONG |
+----+------------+
5 rows in set (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)