https://www.jianshu.com/p/c189439fb32emysql
1、MySQL架構ios
和其它數據庫相比,MySQL有點不同凡響,它的架構能夠在多種不一樣場景中應用併發揮良好做用。主要體如今存儲引擎的架構上,插件式的存儲引擎架構將查詢處理和其它的系統任務以及數據的存儲提取相分離。這種架構能夠根據業務的需求和實際須要選擇合適的存儲引擎。程序員
❝面試
畫出 MySQL 架構圖,這種變態問題都能問的出來算法
MySQL 的查詢流程具體是?or 一條SQL語句在MySQL中如何執行的?sql
客戶端請求 ---> 鏈接器(驗證用戶身份,給予權限) ---> 查詢緩存(存在緩存則直接返回,不存在則執行後續操做) ---> 分析器(對SQL進行詞法分析和語法分析操做) ---> 優化器(主要對執行的sql優化選擇最優的執行方案方法) ---> 執行器(執行時會先看用戶是否有執行權限,有才去使用這個引擎提供的接口) ---> 去引擎層獲取數據返回(若是開啓查詢緩存則會緩存查詢結果)圖:極客時間數據庫
❝緩存
說說MySQL有哪些存儲引擎?都有哪些區別?安全
存儲引擎是MySQL的組件,用於處理不一樣表類型的SQL操做。不一樣的存儲引擎提供不一樣的存儲機制、索引技巧、鎖定水平等功能,使用不一樣的存儲引擎,還能夠得到特定的功能。性能優化
使用哪種引擎能夠靈活選擇,一個數據庫中多個表能夠使用不一樣引擎以知足各類性能和實際需求,使用合適的存儲引擎,將會提升整個數據庫的性能 。
MySQL服務器使用可插拔的存儲引擎體系結構,能夠從運行中的 MySQL 服務器加載或卸載存儲引擎 。
-- 查看支持的存儲引擎 SHOW ENGINES -- 查看默認存儲引擎 SHOW VARIABLES LIKE 'storage_engine' --查看具體某一個表所使用的存儲引擎,這個默認存儲引擎被修改了! show create table tablename --準確查看某個數據庫中的某一表所使用的存儲引擎 show table status like 'tablename' show table status from database where name="tablename"
-- 建表時指定存儲引擎。默認的就是INNODB,不須要設置 CREATE TABLE t1 (i INT) ENGINE = INNODB; CREATE TABLE t2 (i INT) ENGINE = CSV; CREATE TABLE t3 (i INT) ENGINE = MEMORY; -- 修改存儲引擎 ALTER TABLE t ENGINE = InnoDB; -- 修改默認存儲引擎,也能夠在配置文件my.cnf中修改默認引擎 SET default_storage_engine=NDBCLUSTER;
默認狀況下,每當 CREATE TABLE 或 ALTER TABLE 不能使用默認存儲引擎時,都會生成一個警告。爲了防止在所需的引擎不可用時出現使人困惑的意外行爲,能夠啓用 NO_ENGINE_SUBSTITUTION SQL 模式。若是所需的引擎不可用,則此設置將產生錯誤而不是警告,而且不會建立或更改表
常見的存儲引擎就 InnoDB、MyISAM、Memory、NDB。
InnoDB 如今是 MySQL 默認的存儲引擎,支持事務、行級鎖定和外鍵
在 MySQL中創建任何一張數據表,在其數據目錄對應的數據庫目錄下都有對應表的 .frm 文件,.frm 文件是用來保存每一個數據表的元數據(meta)信息,包括表結構的定義等,與數據庫存儲引擎無關,也就是任何存儲引擎的數據表都必須有.frm文件,命名方式爲 數據表名.frm,如user.frm。
查看MySQL 數據保存在哪裏:show variables like 'data%'
MyISAM 物理文件結構爲:
InnoDB 物理文件結構爲:
❝
ps:正經公司,這些都有專業運維去作,數據備份、恢復啥的,讓我一個 Javaer 搞這的話,加錢不?
對比項MyISAMInnoDB主外鍵不支持支持事務不支持支持行表鎖表鎖,即便操做一條記錄也會鎖住整個表,不適合高併發的操做行鎖,操做時只鎖某一行,不對其它行有影響,適合高併發的操做緩存只緩存索引,不緩存真實數據不只緩存索引還要緩存真實數據,對內存要求較高,並且內存大小對性能有決定性的影響表空間小大關注點性能事務默認安裝是是
❝
一張表,裏面有ID自增主鍵,當insert了17條記錄以後,刪除了第15,16,17條記錄,再把Mysql重啓,再insert一條記錄,這條記錄的ID是18仍是15 ?
若是表的類型是MyISAM,那麼是18。由於MyISAM表會把自增主鍵的最大ID 記錄到數據文件中,重啓MySQL自增主鍵的最大ID也不會丟失;
若是表的類型是InnoDB,那麼是15。由於InnoDB 表只是把自增主鍵的最大ID記錄到內存中,因此重啓數據庫或對錶進行OPTION操做,都會致使最大ID丟失。
❝
哪一個存儲引擎執行 select count(*) 更快,爲何?
MyISAM更快,由於MyISAM內部維護了一個計數器,能夠直接調取。
InnoDB 中 count(*) 語句是在執行的時候,全表掃描統計總數量,因此當數據愈來愈大時,語句就愈來愈耗時了,爲何 InnoDB 引擎不像 MyISAM 引擎同樣,將總行數存儲到磁盤上?這跟 InnoDB 的事務特性有關,因爲多版本併發控制(MVCC)的緣由,InnoDB 表「應該返回多少行」也是不肯定的。
主要包括如下五大類:
❝
CHAR 和 VARCHAR 的區別?
char是固定長度,varchar長度可變:
char(n) 和 varchar(n) 中括號中 n 表明字符的個數,並不表明字節個數,好比 CHAR(30) 就能夠存儲 30 個字符。
存儲時,前者無論實際存儲數據的長度,直接按 char 規定的長度分配存儲空間;然後者會根據實際存儲的數據分配最終的存儲空間
相同點:
不一樣點:
char是適合存儲很短的、通常固定長度的字符串。例如,char很是適合存儲密碼的MD5值,由於這是一個定長的值。對於很是短的列,char比varchar在存儲空間上也更有效率。
❝
列的字符串類型能夠是什麼?
字符串類型是:SET、BLOB、ENUM、CHAR、CHAR、TEXT、VARCHAR
❝
BLOB和TEXT有什麼區別?
BLOB是一個二進制對象,能夠容納可變數量的數據。有四種類型的BLOB:TINYBLOB、BLOB、MEDIUMBLO和 LONGBLOB
TEXT是一個不區分大小寫的BLOB。四種TEXT類型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。
BLOB 保存二進制數據,TEXT 保存字符數據。
❝
說說你對 MySQL 索引的理解?
數據庫索引的原理,爲何要用 B+樹,爲何不用二叉樹?
彙集索引與非彙集索引的區別?
InnoDB引擎中的索引策略,瞭解過嗎?
建立索引的方式有哪些?
聚簇索引/非聚簇索引,mysql索引底層實現,爲何不用B-tree,爲何不用hash,葉子結點存放的是數據仍是指向數據的內存地址,使用索引須要注意的幾個地方?
建立:
建立索引:CREATE [UNIQUE] INDEX indexName ON mytable(username(length));若是是CHAR,VARCHAR類型,length能夠小於字段實際長度;若是是BLOB和TEXT類型,必須指定 length。
修改表結構(添加索引):ALTER table tableName ADD [UNIQUE] INDEX indexName(columnName)
刪除:DROP INDEX [indexName] ON mytable;
查看:SHOW INDEX FROM table_name\G --能夠經過添加 \G 來格式化輸出信息。
使用ALERT命令
ALTER TABLE tbl_name ADD PRIMARY KEY (column_list): 該語句添加一個主鍵,這意味着索引值必須是惟一的,且不能爲NULL。
ALTER TABLE tbl_name ADD UNIQUE index_name (column_list 這條語句建立索引的值必須是惟一的(除了NULL外,NULL可能會出現屢次)。
ALTER TABLE tbl_name ADD INDEX index_name (column_list) 添加普通索引,索引值可出現屢次。
ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list)該語句指定了索引爲 FULLTEXT ,用於全文索引。
❝
爲何MySQL 索引中用B+tree,不用B-tree 或者其餘樹,爲何不用 Hash 索引
聚簇索引/非聚簇索引,MySQL 索引底層實現,葉子結點存放的是數據仍是指向數據的內存地址,使用索引須要注意的幾個地方?
使用索引查詢必定能提升查詢的性能嗎?爲何?
首先要明白索引(index)是在存儲引擎(storage engine)層面實現的,而不是server層面。不是全部的存儲引擎都支持全部的索引類型。即便多個存儲引擎支持某一索引類型,它們的實現和行爲也可能有所差異。
MyISAM 和 InnoDB 存儲引擎,都使用 B+Tree的數據結構,它相對與 B-Tree結構,全部的數據都存放在葉子節點上,且把葉子節點經過指針鏈接到一塊兒,造成了一條數據鏈表,以加快相鄰數據的檢索效率。
先了解下 B-Tree 和 B+Tree 的區別
B-Tree是爲磁盤等外存儲設備設計的一種平衡查找樹。
系統從磁盤讀取數據到內存時是以磁盤塊(block)爲基本單位的,位於同一個磁盤塊中的數據會被一次性讀取出來,而不是須要什麼取什麼。
InnoDB 存儲引擎中有頁(Page)的概念,頁是其磁盤管理的最小單位。InnoDB 存儲引擎中默認每一個頁的大小爲16KB,可經過參數 innodb_page_size 將頁的大小設置爲 4K、8K、16K,在 MySQL 中可經過以下命令查看頁的大小:show variables like 'innodb_page_size';
而系統一個磁盤塊的存儲空間每每沒有這麼大,所以 InnoDB 每次申請磁盤空間時都會是若干地址連續磁盤塊來達到頁的大小 16KB。InnoDB 在把磁盤數據讀入到磁盤時會以頁爲基本單位,在查詢數據時若是一個頁中的每條數據都能有助於定位數據記錄的位置,這將會減小磁盤I/O次數,提升查詢效率。
B-Tree 結構的數據可讓系統高效的找到數據所在的磁盤塊。爲了描述 B-Tree,首先定義一條記錄爲一個二元組[key, data] ,key爲記錄的鍵值,對應表中的主鍵值,data 爲一行記錄中除主鍵外的數據。對於不一樣的記錄,key值互不相同。
一棵m階的B-Tree有以下特性:
B-Tree 中的每一個節點根據實際狀況能夠包含大量的關鍵字信息和分支,以下圖所示爲一個 3 階的 B-Tree:
圖片:DobbinSoong
每一個節點佔用一個盤塊的磁盤空間,一個節點上有兩個升序排序的關鍵字和三個指向子樹根節點的指針,指針存儲的是子節點所在磁盤塊的地址。兩個關鍵詞劃分紅的三個範圍域對應三個指針指向的子樹的數據的範圍域。以根節點爲例,關鍵字爲17和35,P1指針指向的子樹的數據範圍爲小於17,P2指針指向的子樹的數據範圍爲17~35,P3指針指向的子樹的數據範圍爲大於35。
模擬查找關鍵字29個過程:
分析上面過程,發現須要3次磁盤I/O操做,和3次內存查找操做。因爲內存中的關鍵字是一個有序表結構,能夠利用二分法查找提升效率。而3次磁盤I/O操做是影響整個B-Tree查找效率的決定因素。B-Tree相對於AVLTree縮減了節點個數,使每次磁盤I/O取到內存的數據都發揮了做用,從而提升了查詢效率。
B+Tree 是在 B-Tree 基礎上的一種優化,使其更適合實現外存儲索引結構,InnoDB 存儲引擎就是用 B+Tree 實現其索引結構。
從上一節中的B-Tree結構圖中能夠看到每一個節點中不只包含數據的key值,還有data值。而每個頁的存儲空間是有限的,若是data數據較大時將會致使每一個節點(即一個頁)能存儲的key的數量很小,當存儲的數據量很大時一樣會致使B-Tree的深度較大,增大查詢時的磁盤I/O次數,進而影響查詢效率。在B+Tree中,全部數據記錄節點都是按照鍵值大小順序存放在同一層的葉子節點上,而非葉子節點上只存儲key值信息,這樣能夠大大加大每一個節點存儲的key值數量,下降B+Tree的高度。
B+Tree相對於B-Tree有幾點不一樣:
將上一節中的B-Tree優化,因爲B+Tree的非葉子節點只存儲鍵值信息,假設每一個磁盤塊能存儲4個鍵值及指針信息,則變成B+Tree後其結構以下圖所示:
一般在B+Tree上有兩個頭指針,一個指向根節點,另外一個指向關鍵字最小的葉子節點,並且全部葉子節點(即數據節點)之間是一種鏈式環結構。所以能夠對B+Tree進行兩種查找運算:一種是對於主鍵的範圍查找和分頁查找,另外一種是從根節點開始,進行隨機查找。
可能上面例子中只有22條數據記錄,看不出B+Tree的優勢,下面作一個推算:
InnoDB存儲引擎中頁的大小爲16KB,通常表的主鍵類型爲INT(佔用4個字節)或BIGINT(佔用8個字節),指針類型也通常爲4或8個字節,也就是說一個頁(B+Tree中的一個節點)中大概存儲16KB/(8B+8B)=1K個鍵值(由於是估值,爲方便計算,這裏的K取值爲103)。也就是說一個深度爲3的B+Tree索引能夠維護103 * 10^3 * 10^3 = 10億 條記錄。
實際狀況中每一個節點可能不能填充滿,所以在數據庫中,B+Tree的高度通常都在2-4層。MySQL的InnoDB存儲引擎在設計時是將根節點常駐內存的,也就是說查找某一鍵值的行記錄時最多隻須要1~3次磁盤I/O操做。
B+Tree性質
MyISAM引擎的索引文件和數據文件是分離的。MyISAM引擎索引結構的葉子節點的數據域,存放的並非實際的數據記錄,而是數據記錄的地址。索引文件與數據文件分離,這樣的索引稱爲"非聚簇索引"。MyISAM的主索引與輔助索引區別並不大,只是主鍵索引不能有重複的關鍵字。
在MyISAM中,索引(含葉子節點)存放在單獨的.myi文件中,葉子節點存放的是數據的物理地址偏移量(經過偏移量訪問就是隨機訪問,速度很快)。
主索引是指主鍵索引,鍵值不可能重複;輔助索引則是普通索引,鍵值可能重複。
經過索引查找數據的流程:先從索引文件中查找到索引節點,從中拿到數據的文件指針,再到數據文件中經過文件指針定位了具體的數據。輔助索引相似。
InnoDB引擎索引結構的葉子節點的數據域,存放的就是實際的數據記錄(對於主索引,此處會存放表中全部的數據記錄;對於輔助索引此處會引用主鍵,檢索的時候經過主鍵到主鍵索引中找到對應數據行),或者說,InnoDB的數據文件自己就是主鍵索引文件,這樣的索引被稱爲「聚簇索引」,一個表只能有一個聚簇索引。
咱們知道InnoDB索引是彙集索引,它的索引和數據是存入同一個.idb文件中的,所以它的索引結構是在同一個樹節點中同時存放索引和數據,以下圖中最底層的葉子節點有三行數據,對應於數據表中的id、stu_id、name數據項。
在Innodb中,索引分葉子節點和非葉子節點,非葉子節點就像新華字典的目錄,單獨存放在索引段中,葉子節點則是順序排列的,在數據段中。Innodb的數據文件能夠按照表來切分(只須要開啓innodb_file_per_table),切分後存放在xxx.ibd中,默認不切分,存放在xxx.ibdata中。
此次咱們以示例中學生表中的name列創建輔助索引,它的索引結構跟主鍵索引的結構有很大差異,在最底層的葉子結點有兩行數據,第一行的字符串是輔助索引,按照ASCII碼進行排序,第二行的整數是主鍵的值。
這就意味着,對name列進行條件搜索,須要兩個步驟:
① 在輔助索引上檢索name,到達其葉子節點獲取對應的主鍵;
② 使用主鍵在主索引上再進行對應的檢索操做
這也就是所謂的「回表查詢」
InnoDB 索引結構須要注意的點
正如咱們上面介紹 InnoDB 存儲結構,索引與數據是共同存儲的,無論是主鍵索引仍是輔助索引,在查找時都是經過先查找到索引節點才能拿到相對應的數據,若是咱們在設計表結構時沒有顯式指定索引列的話,MySQL 會從表中選擇數據不重複的列創建索引,若是沒有符合的列,則 MySQL 自動爲 InnoDB 表生成一個隱含字段做爲主鍵,而且這個字段長度爲6個字節,類型爲整型。
❝
那爲何推薦使用整型自增主鍵而不是選擇UUID?
❝
爲何非主鍵索引結構葉子節點存儲的是主鍵值?
保證數據一致性和節省存儲空間,能夠這麼理解:商城系統訂單表會存儲一個用戶ID做爲關聯外鍵,而不推薦存儲完整的用戶信息,由於當咱們用戶表中的信息(真實名稱、手機號、收貨地址···)修改後,不須要再次維護訂單表的用戶數據,同時也節省了存儲空間。
空間索引是MyISAM的一種特殊索引類型,主要用於地理空間數據類型
❝
爲何Mysql索引要用B+樹不是B樹?
用B+樹不用B樹考慮的是IO對性能的影響,B樹的每一個節點都存儲數據,而B+樹只有葉子節點才存儲數據,因此查找相同數據量的狀況下,B樹的高度更高,IO更頻繁。數據庫索引是存儲在磁盤上的,當數據量大時,就不能把整個索引所有加載到內存了,只能逐一加載每個磁盤頁(對應索引樹的節點)。其中在MySQL底層對B+樹進行進一步優化:在葉子節點中是雙向鏈表,且在鏈表的頭結點和尾節點也是循環指向的。
❝
面試官:爲什麼不採用Hash方式?
由於Hash索引底層是哈希表,哈希表是一種以key-value存儲數據的結構,因此多個數據在存儲關係上是徹底沒有任何順序關係的,因此,對於區間查詢是沒法直接經過索引查詢的,就須要全表掃描。因此,哈希索引只適用於等值查詢的場景。而B+ Tree是一種多路平衡查詢樹,因此他的節點是自然有序的(左子節點小於父節點、父節點小於右子節點),因此對於範圍查詢的時候不須要作全表掃描。
哈希索引不支持多列聯合索引的最左匹配規則,若是有大量重複鍵值得狀況下,哈希索引的效率會很低,由於存在哈希碰撞問題。
覆蓋索引(Covering Index),或者叫索引覆蓋, 也就是平時所說的不須要回表操做
❝
count(*) 和 count(1)和count(列名)區別 ps:這道題說法有點多
執行效果上:
執行效率上:
❝
MySQL中 in和 exists 的區別?
SELECT * FROM A WHERE A.id IN (SELECT id FROM B); SELECT * FROM A WHERE EXISTS (SELECT * from B WHERE B.id = A.id);
若是查詢的兩個表大小至關,那麼用in和exists差異不大。
若是兩個表中一個較小,一個是大表,則子查詢表大的用exists,子查詢表小的用in:
❝
UNION和UNION ALL的區別?
UNION和UNION ALL都是將兩個結果集合併爲一個,兩個要聯合的SQL語句 字段個數必須同樣,並且字段類型要「相容」(一致);
❝
mysql 的內鏈接、左鏈接、右鏈接有什麼區別?
什麼是內鏈接、外鏈接、交叉鏈接、笛卡爾積呢?
❝
事務的隔離級別有哪些?MySQL的默認隔離級別是什麼?
什麼是幻讀,髒讀,不可重複讀呢?
MySQL事務的四大特性以及實現原理
MVCC熟悉嗎,它的底層原理?
MySQL 事務主要用於處理操做量大,複雜度高的數據。好比說,在人員管理系統中,你刪除一我的員,你即須要刪除人員的基本資料,也要刪除和該人員相關的信息,如信箱,文章等等,這樣,這些數據庫操做語句就構成一個事務!
事務是由一組SQL語句組成的邏輯處理單元,具備4個屬性,一般簡稱爲事務的ACID屬性。
併發事務處理帶來的問題
幻讀和不可重複讀的區別:
併發事務處理帶來的問題的解決辦法:
「更新丟失」一般是應該徹底避免的。但防止更新丟失,並不能單靠數據庫事務控制器來解決,須要應用程序對要更新的數據加必要的鎖來解決,所以,防止更新丟失應該是應用的責任。
「髒讀」 、 「不可重複讀」和「幻讀」 ,其實都是數據庫讀一致性問題,必須由數據庫提供必定的事務隔離機制來解決:
一種是加鎖:在讀取數據前,對其加鎖,阻止其餘事務對數據進行修改。
另外一種是數據多版本併發控制(MultiVersion Concurrency Control,簡稱 MVCC 或 MCC),也稱爲多版本數據庫:不用加任何鎖, 經過必定機制生成一個數據請求時間點的一致性數據快照 (Snapshot), 並用這個快照來提供必定級別 (語句級或事務級) 的一致性讀取。從用戶的角度來看,好象是數據庫能夠提供同一數據的多個版本。
數據庫事務的隔離級別有4種,由低到高分別爲
查看當前數據庫的事務隔離級別:
show variables like 'tx_isolation'
下面經過事例一一闡述在事務的併發操做中可能會出現髒讀,不可重複讀,幻讀和事務隔離級別的聯繫。
數據庫的事務隔離越嚴格,併發反作用越小,但付出的代價就越大,由於事務隔離實質上就是使事務在必定程度上「串行化」進行,這顯然與「併發」是矛盾的。同時,不一樣的應用對讀一致性和事務隔離程度的要求也是不一樣的,好比許多應用對「不可重複讀」和「幻讀」並不敏感,可能更關心數據併發訪問的能力。
讀未提交,就是一個事務能夠讀取另外一個未提交事務的數據。
事例:老闆要給程序員發工資,程序員的工資是3.6萬/月。可是發工資時老闆不當心按錯了數字,按成3.9萬/月,該錢已經打到程序員的戶口,可是事務尚未提交,就在這時,程序員去查看本身這個月的工資,發現比往常多了3千元,覺得漲工資了很是高興。可是老闆及時發現了不對,立刻回滾差點就提交了的事務,將數字改爲3.6萬再提交。
分析:實際程序員這個月的工資仍是3.6萬,可是程序員看到的是3.9萬。他看到的是老闆還沒提交事務時的數據。這就是髒讀。
那怎麼解決髒讀呢?Read committed!讀提交,能解決髒讀問題。
讀提交,顧名思義,就是一個事務要等另外一個事務提交後才能讀取數據。
事例:程序員拿着信用卡去享受生活(卡里固然是隻有3.6萬),當他埋單時(程序員事務開啓),收費系統事先檢測到他的卡里有3.6萬,就在這個時候!!程序員的妻子要把錢所有轉出充當家用,並提交。當收費系統準備扣款時,再檢測卡里的金額,發現已經沒錢了(第二次檢測金額固然要等待妻子轉出金額事務提交完)。程序員就會很鬱悶,明明卡里是有錢的…
分析:這就是讀提交,如有事務對數據進行更新(UPDATE)操做時,讀操做事務要等待這個更新操做事務提交後才能讀取數據,能夠解決髒讀問題。但在這個事例中,出現了一個事務範圍內兩個相同的查詢卻返回了不一樣數據,這就是不可重複讀。
那怎麼解決可能的不可重複讀問題?Repeatable read !
重複讀,就是在開始讀取數據(事務開啓)時,再也不容許修改操做。MySQL的默認事務隔離級別
事例:程序員拿着信用卡去享受生活(卡里固然是隻有3.6萬),當他埋單時(事務開啓,不容許其餘事務的UPDATE修改操做),收費系統事先檢測到他的卡里有3.6萬。這個時候他的妻子不能轉出金額了。接下來收費系統就能夠扣款了。
分析:重複讀能夠解決不可重複讀問題。寫到這裏,應該明白的一點就是,不可重複讀對應的是修改,即UPDATE操做。可是可能還會有幻讀問題。由於幻讀問題對應的是插入INSERT操做,而不是UPDATE操做。
何時會出現幻讀?
事例:程序員某一天去消費,花了2千元,而後他的妻子去查看他今天的消費記錄(全表掃描FTS,妻子事務開啓),看到確實是花了2千元,就在這個時候,程序員花了1萬買了一部電腦,即新增INSERT了一條消費記錄,並提交。當妻子打印程序員的消費記錄清單時(妻子事務提交),發現花了1.2萬元,彷佛出現了幻覺,這就是幻讀。
那怎麼解決幻讀問題?Serializable!
Serializable 是最高的事務隔離級別,在該級別下,事務串行化順序執行,能夠避免髒讀、不可重複讀與幻讀。簡單來講,Serializable會在讀取的每一行數據上都加鎖,因此可能致使大量的超時和鎖爭用問題。這種事務隔離級別效率低下,比較耗數據庫性能,通常不使用。
事務隔離級別讀數據一致性髒讀不可重複讀幻讀讀未提交(read-uncommitted)最低級被,只能保證不讀取物理上損壞的數據是是是讀已提交(read-committed)語句級否是是可重複讀(repeatable-read)事務級否否是串行化(serializable)最高級別,事務級否否否
須要說明的是,事務隔離級別和數據訪問的併發性是對立的,事務隔離級別越高併發性就越差。因此要根據具體的應用來肯定合適的事務隔離級別,這個地方沒有萬能的原則。
MySQL InnoDB 存儲引擎的默認支持的隔離級別是 REPEATABLE-READ(可重讀)。咱們能夠經過SELECT @@tx_isolation;命令來查看,MySQL 8.0 該命令改成SELECT @@transaction_isolation;
這裏須要注意的是:與 SQL 標準不一樣的地方在於InnoDB 存儲引擎在 REPEATABLE-READ(可重讀)事務隔離級別下使用的是Next-Key Lock 算法,所以能夠避免幻讀的產生,這與其餘數據庫系統(如 SQL Server)是不一樣的。因此說InnoDB 存儲引擎的默認支持的隔離級別是 REPEATABLE-READ(可重讀)已經能夠徹底保證事務的隔離性要求,即達到了 SQL標準的 SERIALIZABLE(可串行化)隔離級別,並且保留了比較好的併發性能。
由於隔離級別越低,事務請求的鎖越少,因此大部分數據庫系統的隔離級別都是READ-COMMITTED(讀已提交):,可是你要知道的是InnoDB 存儲引擎默認使用 REPEATABLE-READ(可重讀)並不會有任何性能損失。
MySQL的大多數事務型存儲引擎實現都不是簡單的行級鎖。基於提高併發性考慮,通常都同時實現了多版本併發控制(MVCC),包括Oracle、PostgreSQL。只是實現機制各不相同。
能夠認爲 MVCC 是行級鎖的一個變種,但它在不少狀況下避免了加鎖操做,所以開銷更低。雖然實現機制有所不一樣,但大都實現了非阻塞的讀操做,寫操做也只是鎖定必要的行。
MVCC 的實現是經過保存數據在某個時間點的快照來實現的。也就是說無論須要執行多長時間,每一個事物看到的數據都是一致的。
典型的MVCC實現方式,分爲樂觀(optimistic)併發控制和悲觀(pressimistic)併發控制。下邊經過 InnoDB的簡化版行爲來講明 MVCC 是如何工做的。
InnoDB 的 MVCC,是經過在每行記錄後面保存兩個隱藏的列來實現。這兩個列,一個保存了行的建立時間,一個保存行的過時時間(刪除時間)。固然存儲的並非真實的時間,而是系統版本號(system version number)。每開始一個新的事務,系統版本號都會自動遞增。事務開始時刻的系統版本號會做爲事務的版本號,用來和查詢到的每行記錄的版本號進行比較。
REPEATABLE READ(可重讀)隔離級別下MVCC如何工做:
SELECTInnoDB會根據如下兩個條件檢查每行記錄:只有符合上述兩個條件的纔會被查詢出來
InnoDB只查找版本早於當前事務版本的數據行,這樣能夠確保事務讀取的行,要麼是在開始事務以前已經存在要麼是事務自身插入或者修改過的
行的刪除版本號要麼未定義,要麼大於當前事務版本號,這樣能夠確保事務讀取到的行在事務開始以前未被刪除
INSERT:InnoDB爲新插入的每一行保存當前系統版本號做爲行版本號
DELETE:InnoDB爲刪除的每一行保存當前系統版本號做爲行刪除標識
UPDATE:InnoDB爲插入的一行新紀錄保存當前系統版本號做爲行版本號,同時保存當前系統版本號到原來的行做爲刪除標識
保存這兩個額外系統版本號,使大多數操做都不用加鎖。使數據操做簡單,性能很好,而且也能保證只會讀取到符合要求的行。不足之處是每行記錄都須要額外的存儲空間,須要作更多的行檢查工做和一些額外的維護工做。
MVCC 只在 COMMITTED READ(讀提交)和REPEATABLE READ(可重複讀)兩種隔離級別下工做。
InnoDB 使用日誌來減小提交事務時的開銷。由於日誌中已經記錄了事務,就無須在每一個事務提交時把緩衝池的髒塊刷新(flush)到磁盤中。
事務修改的數據和索引一般會映射到表空間的隨機位置,因此刷新這些變動到磁盤須要不少隨機 IO。
InnoDB 假設使用常規磁盤,隨機IO比順序IO昂貴得多,由於一個IO請求須要時間把磁頭移到正確的位置,而後等待磁盤上讀出須要的部分,再轉到開始位置。
InnoDB 用日誌把隨機IO變成順序IO。一旦日誌安全寫到磁盤,事務就持久化了,即便斷電了,InnoDB能夠重放日誌而且恢復已經提交的事務。
InnoDB 使用一個後臺線程智能地刷新這些變動到數據文件。這個線程能夠批量組合寫入,使得數據寫入更順序,以提升效率。
事務日誌能夠幫助提升事務效率:
目前來講,大多數存儲引擎都是這樣實現的,咱們一般稱之爲預寫式日誌(Write-Ahead Logging),修改數據須要寫兩次磁盤。
事務的實現是基於數據庫的存儲引擎。不一樣的存儲引擎對事務的支持程度不同。MySQL 中支持事務的存儲引擎有 InnoDB 和 NDB。
事務的實現就是如何實現ACID特性。
事務的隔離性是經過鎖實現,而事務的原子性、一致性和持久性則是經過事務日誌實現 。
❝
事務是如何經過日誌來實現的,說得越深刻越好。
事務日誌包括:重作日誌redo和回滾日誌undo
二種日誌都可以視爲一種恢復操做,redo_log是恢復提交事務修改的頁操做,而undo_log是回滾行記錄到特定版本。兩者記錄的內容也不一樣,redo_log是物理日誌,記錄頁的物理修改操做,而undo_log是邏輯日誌,根據每行記錄進行記錄。
❝
又引出個問題:你知道MySQL 有多少種日誌嗎?
❝
分佈式事務相關問題,可能還會問到 2PC、3PC,,,
分佈式事務的實現方式有不少,既能夠採用 InnoDB 提供的原生的事務支持,也能夠採用消息隊列來實現分佈式事務的最終一致性。這裏咱們主要聊一下 InnoDB 對分佈式事務的支持。
MySQL 從 5.0.3 InnoDB 存儲引擎開始支持XA協議的分佈式事務。一個分佈式事務會涉及多個行動,這些行動自己是事務性的。全部行動都必須一塊兒成功完成,或者一塊兒被回滾。
在MySQL中,使用分佈式事務涉及一個或多個資源管理器和一個事務管理器。
如圖,MySQL 的分佈式事務模型。模型中分三塊:應用程序(AP)、資源管理器(RM)、事務管理器(TM):
分佈式事務採用兩段式提交(two-phase commit)的方式:
❝
數據庫的樂觀鎖和悲觀鎖?
MySQL 中有哪幾種鎖,列舉一下?
MySQL中InnoDB引擎的行鎖是怎麼實現的?
MySQL 間隙鎖有沒有了解,死鎖有沒有了解,寫一段會形成死鎖的 sql 語句,死鎖發生瞭如何解決,MySQL 有沒有提供什麼機制去解決死鎖
鎖是計算機協調多個進程或線程併發訪問某一資源的機制。
在數據庫中,除傳統的計算資源(如CPU、RAM、I/O等)的爭用之外,數據也是一種供許多用戶共享的資源。數據庫鎖定機制簡單來講,就是數據庫爲了保證數據的一致性,而使各類共享資源在被併發訪問變得有序所設計的一種規則。
打個比方,咱們到淘寶上買一件商品,商品只有一件庫存,這個時候若是還有另外一我的買,那麼如何解決是你買到仍是另外一我的買到的問題?這裏確定要用到事物,咱們先從庫存表中取出物品數量,而後插入訂單,付款後插入付款表信息,而後更新商品數量。在這個過程當中,使用鎖能夠對有限的資源進行保護,解決隔離和併發的矛盾。
從對數據操做的類型分類:
從對數據操做的粒度分類:
爲了儘量提升數據庫的併發度,每次鎖定的數據範圍越小越好,理論上每次只鎖定當前操做的數據的方案會獲得最大的併發度,可是管理鎖是很耗資源的事情(涉及獲取,檢查,釋放鎖等動做),所以數據庫系統須要在高併發響應和系統性能兩方面進行平衡,這樣就產生了「鎖粒度(Lock granularity)」的概念。
適用:從鎖的角度來講,表級鎖更適合於以查詢爲主,只有少許按索引條件更新數據的應用,如Web應用;而行級鎖則更適合於有大量按索引條件併發更新少許不一樣數據,同時又有併發查詢的應用,如一些在線事務處理(OLTP)系統。
行鎖表鎖頁鎖MyISAM
√
BDB
√√InnoDB√√
Memory
√
MyISAM 的表鎖有兩種模式:
MyISAM 表的讀操做與寫操做之間,以及寫操做之間是串行的。當一個線程得到對一個表的寫鎖後, 只有持有鎖的線程能夠對錶進行更新操做。其餘線程的讀、 寫操做都會等待,直到鎖被釋放爲止。
默認狀況下,寫鎖比讀鎖具備更高的優先級:當一個鎖釋放時,這個鎖會優先給寫鎖隊列中等候的獲取鎖請求,而後再給讀鎖隊列中等候的獲取鎖請求。
InnoDB 實現瞭如下兩種類型的行鎖:
爲了容許行鎖和表鎖共存,實現多粒度鎖機制,InnoDB 還有兩種內部使用的意向鎖(Intention Locks),這兩種意向鎖都是表鎖:
索引失效會致使行鎖變表鎖。好比 vchar 查詢不寫單引號的狀況。
樂觀鎖與悲觀鎖是兩種併發控制的思想,可用於解決丟失更新問題
樂觀鎖會「樂觀地」假定大機率不會發生併發更新衝突,訪問、處理數據過程當中不加鎖,只在更新數據時再根據版本號或時間戳判斷是否有衝突,有則處理,無則提交事務。用數據版本(Version)記錄機制實現,這是樂觀鎖最經常使用的一種實現方式
悲觀鎖會「悲觀地」假定大機率會發生併發更新衝突,訪問、處理數據前就加排他鎖,在整個數據處理過程當中鎖定數據,事務提交或回滾後才釋放鎖。另外與樂觀鎖相對應的,悲觀鎖是由數據庫本身實現了的,要用的時候,咱們直接調用數據庫的相關語句就能夠了。
❝
select for update有什麼含義,會鎖表仍是鎖行仍是其餘
for update 僅適用於InnoDB,且必須在事務塊(BEGIN/COMMIT)中才能生效。在進行事務操做時,經過「for update」語句,MySQL會對查詢結果集中每行數據都添加排他鎖,其餘線程對該記錄的更新與刪除操做都會阻塞。排他鎖包含行鎖、表鎖。
InnoDB這種行鎖實現特色意味着:只有經過索引條件檢索數據,InnoDB才使用行級鎖,不然,InnoDB將使用表鎖!假設有個表單 products ,裏面有id跟name二個欄位,id是主鍵。
SELECT * FROM products WHERE id='3' FOR UPDATE; SELECT * FROM products WHERE id='3' and type=1 FOR UPDATE;
SELECT * FROM products WHERE id='-1' FOR UPDATE;
SELECT * FROM products WHERE name='Mouse' FOR UPDATE;
SELECT * FROM products WHERE id<>'3' FOR UPDATE;
SELECT * FROM products WHERE id LIKE '3' FOR UPDATE;
注1: FOR UPDATE僅適用於InnoDB,且必須在交易區塊(BEGIN/COMMIT)中才能生效。注2: 要測試鎖定的情況,能夠利用MySQL的Command Mode ,開二個視窗來作測試。
❝
MySQL 遇到過死鎖問題嗎,你是如何解決的?
死鎖產生:
檢測死鎖:數據庫系統實現了各類死鎖檢測和死鎖超時的機制。InnoDB存儲引擎能檢測到死鎖的循環依賴並當即返回一個錯誤。
死鎖恢復:死鎖發生之後,只有部分或徹底回滾其中一個事務,才能打破死鎖,InnoDB目前處理死鎖的方法是,將持有最少行級排他鎖的事務進行回滾。因此事務型應用程序在設計時必須考慮如何處理死鎖,多數狀況下只須要從新執行因死鎖回滾的事務便可。
外部鎖的死鎖檢測:發生死鎖後,InnoDB 通常都能自動檢測到,並使一個事務釋放鎖並回退,另外一個事務得到鎖,繼續完成事務。但在涉及外部鎖,或涉及表鎖的狀況下,InnoDB 並不能徹底自動檢測到死鎖, 這須要經過設置鎖等待超時參數 innodb_lock_wait_timeout 來解決
死鎖影響性能:死鎖會影響性能而不是會產生嚴重錯誤,由於InnoDB會自動檢測死鎖情況並回滾其中一個受影響的事務。在高併發系統上,當許多線程等待同一個鎖時,死鎖檢測可能致使速度變慢。有時當發生死鎖時,禁用死鎖檢測(使用innodb_deadlock_detect配置選項)可能會更有效,這時能夠依賴innodb_lock_wait_timeout設置進行事務回滾。
MyISAM避免死鎖:
InnoDB避免死鎖:
若是出現死鎖,能夠用 show engine innodb status;命令來肯定最後一個死鎖產生的緣由。返回結果中包括死鎖相關事務的詳細信息,如引起死鎖的 SQL 語句,事務已經得到的鎖,正在等待什麼鎖,以及被回滾的事務等。據此能夠分析死鎖產生的緣由和改進措施。
❝
平常工做中你是怎麼優化SQL的?
SQL優化的通常步驟是什麼,怎麼看執行計劃(explain),如何理解其中各個字段的含義?
如何寫sql可以有效的使用到複合索引?
一條sql執行過長的時間,你如何優化,從哪些方面入手?
什麼是最左前綴原則?什麼是最左匹配原則?
業務需求對MySQL的影響(合適合度)
存儲定位對MySQL的影響
系統各類配置及規則數據
活躍用戶的基本信息數據
活躍用戶的個性化定製信息數據
準實時的統計信息數據
其餘一些訪問頻繁但變動較少的數據
二進制多媒體數據
流水隊列數據
超大文本數據
不適合放進MySQL的數據
須要放進緩存的數據
Schema設計對系統的性能影響
儘可能減小對數據庫訪問的請求
儘可能減小無用數據的查詢請求
硬件環境對系統性能的影響
在優化MySQL時,一般須要對數據庫進行分析,常見的分析手段有慢查詢日誌,EXPLAIN 分析查詢,profiling分析以及show命令查詢系統狀態及系統變量,經過定位分析性能的瓶頸,才能更好的優化數據庫系統的性能。
咱們能夠經過 show 命令查看 MySQL 狀態及變量,找到系統的瓶頸:
Mysql> show status ——顯示狀態信息(擴展show status like ‘XXX’) Mysql> show variables ——顯示系統變量(擴展show variables like ‘XXX’) Mysql> show innodb status ——顯示InnoDB存儲引擎的狀態 Mysql> show processlist ——查看當前SQL執行,包括執行狀態、是否鎖表等 Shell> mysqladmin variables -u username -p password——顯示系統變量 Shell> mysqladmin extended-status -u username -p password——顯示狀態信息
是什麼:使用 Explain 關鍵字能夠模擬優化器執行SQL查詢語句,從而知道 MySQL 是如何處理你的 SQL 語句的。分析你的查詢語句或是表結構的性能瓶頸
能幹嘛:
怎麼玩:
expalin
各字段解釋
id(select 查詢的序列號,包含一組數字,表示查詢中執行select子句或操做表的順序)
id相同,執行順序從上往下
id全不一樣,若是是子查詢,id的序號會遞增,id值越大優先級越高,越先被執行
id部分相同,執行順序是先按照數字大的先執行,而後數字相同的按照從上往下的順序執行
select_type(查詢類型,用於區別普通查詢、聯合查詢、子查詢等複雜查詢)
SIMPLE :簡單的select查詢,查詢中不包含子查詢或UNION
PRIMARY:查詢中若包含任何複雜的子部分,最外層查詢被標記爲PRIMARY
SUBQUERY:在select或where列表中包含了子查詢
DERIVED:在from列表中包含的子查詢被標記爲DERIVED,MySQL會遞歸執行這些子查詢,把結果放在臨時表裏
UNION:若第二個select出如今UNION以後,則被標記爲UNION,若UNION包含在from子句的子查詢中,外層select將被標記爲DERIVED
UNION RESULT:從UNION表獲取結果的select
table(顯示這一行的數據是關於哪張表的)
type(顯示查詢使用了那種類型,從最好到最差依次排列 system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL )tip: 通常來講,得保證查詢至少達到range級別,最好到達ref
system:表只有一行記錄(等於系統表),是 const 類型的特例,平時不會出現
const:表示經過索引一次就找到了,const 用於比較 primary key 或 unique 索引,由於只要匹配一行數據,因此很快,如將主鍵置於 where 列表中,mysql 就能將該查詢轉換爲一個常量
eq_ref:惟一性索引掃描,對於每一個索引鍵,表中只有一條記錄與之匹配,常見於主鍵或惟一索引掃描
ref:非惟一性索引掃描,範圍匹配某個單獨值得全部行。本質上也是一種索引訪問,他返回全部匹配某個單獨值的行,然而,它可能也會找到多個符合條件的行,多以他應該屬於查找和掃描的混合體
range:只檢索給定範圍的行,使用一個索引來選擇行。key列顯示使用了哪一個索引,通常就是在你的where語句中出現了between、<、>、in等的查詢,這種範圍掃描索引比全表掃描要好,由於它只需開始於索引的某一點,而結束於另外一點,不用掃描所有索引
index:Full Index Scan,index於ALL區別爲index類型只遍歷索引樹。一般比ALL快,由於索引文件一般比數據文件小。(也就是說雖然all和index都是讀全表,但index是從索引中讀取的,而all是從硬盤中讀的)
ALL:Full Table Scan,將遍歷全表找到匹配的行
possible_keys(顯示可能應用在這張表中的索引,一個或多個,查詢涉及到的字段若存在索引,則該索引將被列出,但不必定被查詢實際使用)
key
實際使用的索引,若是爲NULL,則沒有使用索引
查詢中若使用了覆蓋索引,則該索引和查詢的 select 字段重疊,僅出如今key列表中
explain-key
key_len
表示索引中使用的字節數,可經過該列計算查詢中使用的索引的長度。在不損失精確性的狀況下,長度越短越好
key_len顯示的值爲索引字段的最大可能長度,並不是實際使用長度,即key_len是根據表定義計算而得,不是經過表內檢索出的
ref(顯示索引的哪一列被使用了,若是可能的話,是一個常數。哪些列或常量被用於查找索引列上的值)
rows(根據表統計信息及索引選用狀況,大體估算找到所需的記錄所須要讀取的行數)
Extra(包含不適合在其餘列中顯示但十分重要的額外信息)
using filesort: 說明mysql會對數據使用一個外部的索引排序,不是按照表內的索引順序進行讀取。mysql中沒法利用索引完成的排序操做稱爲「文件排序」。常見於order by和group by語句中
Using temporary:使用了臨時表保存中間結果,mysql在對查詢結果排序時使用臨時表。常見於排序order by和分組查詢group by。
using index:表示相應的select操做中使用了覆蓋索引,避免訪問了表的數據行,效率不錯,若是同時出現using where,代表索引被用來執行索引鍵值的查找;不然索引被用來讀取數據而非執行查找操做
using where:使用了where過濾
using join buffer:使用了鏈接緩存
impossible where:where子句的值老是false,不能用來獲取任何元祖
select tables optimized away:在沒有group by子句的狀況下,基於索引優化操做或對於MyISAM存儲引擎優化COUNT(*)操做,沒必要等到執行階段再進行計算,查詢執行計劃生成的階段即完成優化
distinct:優化distinct操做,在找到第一匹配的元祖後即中止找一樣值的動做
case:
explain-demo
MySQL 的慢查詢日誌是 MySQL 提供的一種日誌記錄,它用來記錄在 MySQL 中響應時間超過閾值的語句,具體指運行時間超過 long_query_time 值的 SQL,則會被記錄到慢查詢日誌中。
查看開啓狀態
SHOW VARIABLES LIKE '%slow_query_log%'
開啓慢查詢日誌
mysql> set global slow_query_log='ON'; mysql> set global slow_query_log_file='/var/lib/mysql/hostname-slow.log'; mysql> set global long_query_time=2;
也可set文件位置,系統會默認給一個缺省文件host_name-slow.log
使用set操做開啓慢查詢日誌只對當前數據庫生效,若是MySQL重啓則會失效。
[mysqld] slow_query_log = ON slow_query_log_file = /var/lib/mysql/hostname-slow.log long_query_time = 3
注:log-slow-queries 參數爲慢查詢日誌存放的位置,通常這個目錄要有 MySQL 的運行賬號的可寫權限,通常都將這個目錄設置爲 MySQL 的數據存放目錄;long_query_time=2 中的 2 表示查詢超過兩秒才記錄;在my.cnf或者 my.ini 中添加 log-queries-not-using-indexes 參數,表示記錄下沒有使用索引的查詢。
能夠用 select sleep(4) 驗證是否成功開啓。
在生產環境中,若是手工分析日誌,查找、分析SQL,仍是比較費勁的,因此MySQL提供了日誌分析工具mysqldumpslow。
經過 mysqldumpslow --help 查看操做幫助信息
也可以使用 pt-query-digest 分析 RDS MySQL 慢查詢日誌
經過慢日誌查詢能夠知道哪些 SQL 語句執行效率低下,經過 explain 咱們能夠得知 SQL 語句的具體執行狀況,索引使用等,還能夠結合Show Profile命令查看執行狀態。
Show Profile 是 MySQL 提供能夠用來分析當前會話中語句執行的資源消耗狀況。能夠用於SQL的調優的測量
默認狀況下,參數處於關閉狀態,並保存最近15次的運行結果
分析步驟mysql> show profiles; +----------+------------+---------------------------------+ | Query_ID | Duration | Query | +----------+------------+---------------------------------+ | 1 | 0.00385450 | show variables like "profiling" | | 2 | 0.00170050 | show variables like "profiling" | | 3 | 0.00038025 | select * from t_base_user | +----------+------------+---------------------------------+
converting HEAP to MyISAM 查詢結果太大,內存都不夠用了往磁盤上搬了。
create tmp table 建立臨時表,這個要注意
Copying to tmp table on disk 把內存臨時表複製到磁盤
locked
診斷SQL,show profile cpu,block io for query id(上一步前面的問題SQL數字號碼)
平常開發須要注意的結論
是否支持,看看當前的mysql版本是否支持mysql>Show variables like 'profiling'; --默認是關閉,使用前須要開啓
開啓功能,默認是關閉,使用前須要開啓mysql>set profiling=1;
運行SQL
查看結果
❝
查詢中哪些狀況不會使用索引?
通常性建議
永遠小標驅動大表(小的數據集驅動大的數據集)
slect * from A where id in (select id from B)`等價於 #等價於 select id from B select * from A where A.id=B.id
當 B 表的數據集必須小於 A 表的數據集時,用 in 優於 exists
select * from A where exists (select 1 from B where B.id=A.id) #等價於 select * from A select * from B where B.id = A.id`
當 A 表的數據集小於B表的數據集時,用 exists優於用 in
注意:A表與B表的ID字段應創建索引。
order by關鍵字優化
order by子句,儘可能使用 Index 方式排序,避免使用 FileSort 方式排序
MySQL 支持兩種方式的排序,FileSort 和 Index,Index效率高,它指 MySQL 掃描索引自己完成排序,FileSort 效率較低;
ORDER BY 知足兩種狀況,會使用Index方式排序;①ORDER BY語句使用索引最左前列 ②使用where子句與ORDER BY子句條件列組合知足索引最左前列
儘量在索引列上完成排序操做,遵守索引建的最佳最前綴
若是不在索引列上,filesort 有兩種算法,mysql就要啓動雙路排序和單路排序
雙路排序:MySQL 4.1以前是使用雙路排序,字面意思就是兩次掃描磁盤,最終獲得數據
單路排序:從磁盤讀取查詢須要的全部列,按照order by 列在 buffer對它們進行排序,而後掃描排序後的列表進行輸出,效率高於雙路排序
優化策略
增大sort_buffer_size參數的設置
增大max_lencth_for_sort_data參數的設置
GROUP BY關鍵字優化
MySQL 支持的數據類型很是多,選擇正確的數據類型對於獲取高性能相當重要。無論存儲哪一種類型的數據,下面幾個簡單的原則都有助於作出更好的選擇。
通常狀況下咱們建立的表對應一組存儲文件,使用MyISAM存儲引擎時是一個.MYI和.MYD文件,使用Innodb存儲引擎時是一個.ibd和.frm(表結構)文件。
當數據量較大時(通常千萬條記錄級別以上),MySQL的性能就會開始降低,這時咱們就須要將數據分散到多組存儲文件,保證其單個文件的執行效率
能幹嗎
怎麼玩
首先查看當前數據庫是否支持分區
分區類型及操做
看上去分區表很帥氣,爲何大部分互聯網仍是更多的選擇本身分庫分表來水平擴展咧?
❝
隨着業務的發展,業務愈來愈複雜,應用的模塊愈來愈多,總的數據量很大,高併發讀寫操做均超過單個數據庫服務器的處理能力怎麼辦?
這個時候就出現了數據分片,數據分片指按照某個維度將存放在單一數據庫中的數據分散地存放至多個數據庫或表中。數據分片的有效手段就是對關係型數據庫進行分庫和分表。
區別於分區的是,分區通常都是放在單機裏的,用的比較多的是時間範圍分區,方便歸檔。只不過度庫分表須要代碼實現,分區則是mysql內部實現。分庫分表和分區並不衝突,能夠結合使用。