你們好,我是Java最全面試題庫
的提褲姐,今天這篇是數據庫面試題系列的第一篇,主要總結了MySQL相關的面試題;在後續,會沿着第一篇開篇的知識線路一直總結下去,作到日更!若是我能作到百日百更,但願你也能夠跟着百日百刷,一百天養成一個好習慣。mysql
一、from 子句組裝來自不一樣數據源的數據;
二、where 子句基於指定的條件對記錄行進行篩選;
三、group by 子句將數據劃分爲多個分組;
四、使用彙集函數進行計算;
五、使用 having 子句篩選分組;
六、計算全部的表達式;
七、select 的字段;
八、使用 order by 對結果集進行排序。面試
外鏈接:算法
數據則顯示相應字段的數據,若是不匹配則顯示爲 null。sql
數據則顯示相應字段的數據,若是不匹配則顯示爲 null。數據庫
全鏈接:
先以左表進行左外鏈接,再以右表進行右外鏈接緩存
內鏈接:
顯示錶之間有鏈接匹配的全部行。安全
sql注入
經過在 Web 表單中輸入(惡意)SQL 語句獲得一個存在安全漏洞的網站上的數據庫,而不是按照設計者意圖去執行 SQL 語句。
舉例:當執行的 sql 爲 select * from user where username = "admin" or "a"="a"
時,sql 語句恆成立,參數 admin 毫無心義。服務器
防止 sql 注入的方式:網絡
一、當只要一行數據時使用 limit 1
查詢時若是已知會獲得一條數據,這種狀況下加上 limit 1 會增長性能。由於 mysql 數據庫引擎會在找到一條結果中止搜索,而不是繼續查詢下一條是否符合標準直到全部記錄查詢完畢。多線程
二、選擇正確的數據庫引擎
Mysql 中有兩個引擎 MyISAM
和 InnoDB
,每一個引擎有利有弊。
①MyISAM 適用於一些大量查詢的應用,但對於有大量寫功能的應用不是很好。甚至你只須要update 一個字段整個表都會被鎖起來。而別的進程就算是讀操做也不行要等到當前 update 操做完成以後才能繼續進行。另外,MyISAM 對於 select count(*)這類操做是超級快的。
②InnoDB 的趨勢會是一個很是複雜的存儲引擎,對於一些小的應用會比 MyISAM 還慢,可是支持「行鎖」,因此在寫操做比較多的時候會比較優秀。而且,它支持不少的高級應用,例如:事務。
not exists
代替 not in
Not exists 用到了鏈接可以發揮已經創建好的索引的做用,not in 不能使用索引。Not in 是最慢的方式要同每條記錄比較,在數據量比較大的操做時不建議使用這種方式。
如:in not in is null is not null <>
等
某個字段總要拿來搜索,爲其創建索引:
Mysql 中使用 alter table 語句來爲表中的字段添加索引:alter table 代表 add index (字段名)
;
1.InnoDB 存儲引擎
InnoDB 是事務型數據庫的首選引擎,支持事務安全表(ACID),支持行鎖定和外鍵,InnoDB 是默認的MySQL引擎。
2.MyISAM 存儲引擎
MyISAM 基於 ISAM 存儲引擎,並對其進行擴展。它是在 Web、數據倉儲和其餘應用環境下最常使用的存儲引擎之一。MyISAM 擁有較高的插入、查詢速度,但不支持事物。
3.MEMORY 存儲引擎
MEMORY 存儲引擎將表中的數據存儲到內存中,未查詢和引用其餘表數據提供快速訪問。
4.NDB 存儲引擎
DB 存儲引擎是一個集羣存儲引擎,相似於 Oracle 的 RAC,但它是 Share Nothing 的架構,所以能提供更高級別的高可用性和可擴展性。NDB 的特色是數據所有放在內存中,所以經過主鍵查找很是快。
關於 NDB,有一個問題須要注意,它的鏈接(join)操做是在 MySQL 數據庫層完成,不是在存儲引擎層完成,這意味着,複雜的 join 操做須要巨大的網絡開銷,查詢速度會很慢。
5.Memory (Heap) 存儲引擎
Memory 存儲引擎(以前稱爲 Heap)將表中數據存放在內存中,若是數據庫重啓或崩潰,數據丟失,所以它很是適合存儲臨時數據。
6.Archive 存儲引擎
正如其名稱所示,Archive 很是適合存儲歸檔數據,如日誌信息。它只支持 INSERT 和 SELECT 操做,其設計的主要目的是提供高速的插入和壓縮功能。
7.Federated 存儲引擎
Federated 存儲引擎不存放數據,它至少指向一臺遠程 MySQL 數據庫服務器上的表,很是相似於 Oracle 的透明網關。
8.Maria 存儲引擎
Maria 存儲引擎是新開發的引擎,其設計目標是用來取代原有的 MyISAM 存儲引擎,從而成爲 MySQL 默認
的存儲引擎。
上述引擎中,InnoDB 是事務安全的存儲引擎,設計上借鑑了不少 Oracle 的架構思想,通常而言,在 OLTP
應用中,InnoDB 應該做爲核心應用表的首先存儲引擎。InnoDB 是由第三方的 Innobase Oy 公司開發,現已被Oracle 收購,創始人是 Heikki Tuuri,芬蘭赫爾辛基人,和著名的 Linux 創始人 Linus 是校友。
數據庫事務 transanction 正確執行的四個基本要素。ACID,原子性(Atomicity)、一致性(Correspondence)、隔離性(Isolation)、持久性(Durability)。 原子性
:整個事務中的全部操做,要麼所有完成,要麼所有不完成,不可能停滯在中間某個環節。事務在執
行過程當中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務歷來沒有執行過同樣。一致性
:在事務開始以前和事務結束之後,數據庫的完整性約束沒有被破壞。隔離性
:隔離狀態執行事務,使它們好像是系統在給定時間內執行的惟一操做。若是有兩個事務,運行在相
同的時間內,執行 相同的功能,事務的隔離性將確保每一事務在系統中認爲只有該事務在使用系統。這種屬性有時稱爲串行化,爲了防止事務操做間的混淆, 必須串行化或序列化請 求,使得在同一時間僅有一個請求用於同一數據。持久性
:在事務完成之後,該事務所對數據庫所做的更改便持久的保存在數據庫之中,並不會被回滾。
1.避免在 WHERE 子句中使用 !=
或 <>
操做符,不然將引擎放棄使用索引而進行全表掃描。優化器將沒法經過索引來肯定將要命中的行數,所以須要搜索該表的全部行。
2.避免在 WHERE 子句中使用 OR 來鏈接條件,不然將致使引擎放棄使用索引而進行全表掃描,如:SELECT id FROM t WHERE num = 10 OR num = 20
。
3.避免在 WHERE 子句中對字段進行表達式操做,這將致使引擎放棄使用索引而進行全表掃描。
4.避免在 WHERE 子句中對字段進行函數操做,這將致使引擎放棄使用索引而進行全表掃描。
5.LIKE 查詢,%
不能在前,由於沒法使用索引。若是須要模糊匹配,可使用全文索引。
一、若是咱們定義了主鍵(PRIMARY KEY),那麼InnoDB會選擇主鍵做爲彙集索引。
若是沒有顯式定義主鍵,則InnoDB會選擇第一個不包含有NULL值的惟一索引做爲主鍵索引。
若是也沒有這樣的惟一索引,則InnoDB會選擇內置6字節長的ROWID做爲隱含的彙集索引(ROWID隨着行記錄的寫入而主鍵遞增,這個ROWID不像ORACLE的ROWID那樣可引用,是隱含的)。
二、數據記錄自己被存於主索引(一顆B+Tree)的葉子節點上,這就要求同一個葉子節點內(大小爲一個內存頁或磁盤頁)的各條數據記錄按主鍵順序存放。
所以每當有一條新的記錄插入時,MySQL會根據其主鍵將其插入適當的節點和位置,若是頁面達到裝載因子(InnoDB默認爲15/16),則開闢一個新的頁(節點)
三、若是表使用自增主鍵,那麼每次插入新的記錄,記錄就會順序添加到當前索引節點的後續位置,當一頁寫滿,就會自動開闢一個新的頁。
四、若是使用非自增主鍵(若是身份證號或學號等),因爲每次插入主鍵的值近似於隨機,所以每次新紀錄都要被插到現有索引頁得中間某個位置,此時MySQL不得不爲了將新記錄插到合適位置而移動數據,甚至目標頁面可能已經被回寫到磁盤上而從緩存中清掉,此時又要從磁盤上讀回來,這增長了不少開銷,同時頻繁的移動、分頁操做形成了大量的碎片,獲得了不夠緊湊的索引結構,後續不得不經過OPTIMIZE TABLE
來重建表並優化填充頁面。
該隔離級別是 MySQL 默認的隔離級別
,在同一個事務裏,select 的結果是事務開始時時間點的狀態,所以,一樣的 select 操做讀到的結果會是一致的,可是,會有幻讀現象。
MySQL 的 InnoDB 引擎能夠經過 next-key locks
機制來避免幻讀。 InnoDB 存儲引擎使用三種行鎖的算法用來知足相關事務隔離級別的要求:
Record Locks
該鎖爲索引記錄上的鎖,若是表中沒有定義索引,InnoDB 會默認爲該表建立一個隱藏的聚簇索引,並使用該索引鎖定記錄。
Gap Locks
該鎖會鎖定一個範圍,可是不括記錄自己。能夠經過修改隔離級別爲 READ COMMITTED
或者配置 innodb_locks_unsafe_for_binlog
參數爲 ON
。
Next-key Locks
該鎖就是 Record Locks
和 Gap Locks
的組合,即鎖定一個範圍而且鎖定該記錄自己。InnoDB 使用 Next-key Locks
解決幻讀問題。須要注意的是,若是索引有惟一屬性,則 InnnoDB 會自動將 Next-key Locks 降級爲 Record Locks。
舉例:若是一個索引有 1, 3, 5 三個值,則該索引鎖定的區間爲 (-∞,1], (1,3], (3,5], (5,+ ∞)。
一、Master 上面的 binlog dump
線程,該線程負責將 master 的 binlog event
傳到 slave
。
二、Slave 上面的 IO 線程,該線程負責接收 Master 傳過來的 binlog,並寫入 relay log
。
三、Slave 上面的 SQL 線程,該線程負責讀取 relay log
並執行。
四、若是是多線程複製,不管是 5.6 庫級別的假多線程仍是 MariaDB 或者 5.7 的真正的多線程複製, SQL 線程只作 coordinator ,只負責把 relay log
中的 binlog
讀出來而後交給 worker
線程, woker 線程負責具體 binlog event
的執行。
一、InnoDB支持事務
,MyISAM不支持
對於InnoDB每一條SQL語言都默認封裝成事務,自動提交,這樣會影響速度,因此最好把多條SQL語言放在begin和commit之間,組成一個事務;
二、InnoDB支持外鍵
,而MyISAM不支持。對一個包含外鍵的InnoDB錶轉爲MYISAM會失敗;
三、InnoDB是彙集索引
,數據文件是和索引綁在一塊兒的,必需要有主鍵,經過主鍵索引效率很高。
可是輔助索引須要兩次查詢,先查詢到主鍵,而後再經過主鍵查詢到數據。所以主鍵不該該過大,由於主鍵太大,其餘索引也都會很大。
而MyISAM是非彙集索引,數據文件是分離的,索引保存的是數據文件的指針。主鍵索引和輔助索引是獨立的。
四、InnoDB不保存表的具體行數,執行select count(*) from table
時須要全表掃描。而MyISAM用一個變量保存了整個表的行數,執行上述語句時只須要讀出該變量便可,速度很快;
五、Innodb不支持全文索引
,而MyISAM支持全文索引
,查詢效率上MyISAM要高;
Read Uncommitted(讀取未提交內容)
在該隔離級別,全部事務均可以看到其餘未提交事務的執行結果。本隔離級別不多用於實際應用,由於它的性能也不比其餘級別好多少。讀取未提交的數據,也被稱之爲髒讀(Dirty Read)。
Read Committed(讀取提交內容)
這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它知足了隔離的簡單定義:一個事務只能看見已經提交事務所作的改變。這種隔離級別 也支持所謂的不可重複讀(Nonrepeatable Read),由於同一事務的其餘實例在該實例處理其間可能會有新的commit,因此同一select可能返回不一樣結果。
Repeatable Read(可重讀)
這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在併發讀取數據時,會看到一樣的數據行。不過理論上,這會致使另外一個棘手的問題:幻讀 (Phantom Read)。簡單的說,幻讀指當用戶讀取某一範圍的數據行時,另外一個事務又在該範圍內插入了新行,當用戶再讀取該範圍的數據行時,會發現有新的「幻影」 行。
InnoDB和Falcon存儲引擎經過多版本併發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。
Serializable(可串行化)
這是最高的隔離級別,它經過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡言之,它是在每一個讀的數據行上加上共享鎖。在這個級別,可能致使大量的超時現象和鎖競爭。
mvcc根據undo log來實現
RR級別下,事務中的第一個SELECT
請求才開始建立read view
;
RC級別下,事務中每次SELECT
請求都會從新建立read view
;
ReadView 中是當前活躍的事務 ID 列表,稱之爲 m_ids
,其中最小值爲 up_limit_id
,最大值爲 low_limit_id
,事務 ID 是事務開啓時 InnoDB 分配的,其大小決定了事務開啓的前後順序,所以咱們能夠經過 ID 的大小關係來決定版本記錄的可見性,具體判斷流程以下:
trx_id 小於 m_ids 中的最小值 up_limit_id
,說明生成該版本的事務在 ReadView 生成前就已經提交了,因此該版本能夠被當前事務訪問。trx_id 大於 m_ids 列表中的最大值 low_limit_id
,說明生成該版本的事務在生成 ReadView 後才生成,因此該版本不能夠被當前事務訪問。須要根據 Undo Log 鏈找到前一個版本,而後根據該版本的 DB_TRX_ID 從新判斷可見性。trx_id 屬性值在 m_ids 列表中最大值和最小值之間(包含)
,那就須要判斷一下 trx_id 的值是否是在 m_ids 列表中。若是在,說明建立 ReadView 時生成該版本所屬事務仍是活躍的,所以該版本不能夠被訪問,須要查找 Undo Log 鏈獲得上一個版本,而後根據該版本的 DB_TRX_ID 再從頭計算一次可見性;若是不在,說明建立 ReadView 時生成該版本的事務已經被提交,該版本能夠被訪問。此時通過一系列判斷咱們已經獲得了這條記錄相對 ReadView 來講的可見結果。此時,若是這條記錄的 delete_flag 爲 true,說明這條記錄已被刪除,不返回。不然說明此記錄能夠安全返回給客戶端。
一、有一個參數是innodb_read_ahead_threshold
,他的默認值是56
,意思就是若是順序的訪問了一個區裏的多個數據頁,訪問的數據頁的數量超過了這個閾值,此時就會觸發預讀機制,把下一個相鄰區中的全部數據頁都加載到緩存裏去
二、若是Buffer Pool裏緩存了一個區裏的13個連續的數據頁,並且這些數據頁都是比較頻繁會被訪問的,此時就會 直接觸發預讀機制,把這個區裏的其餘的數據頁都加載到緩存裏去 這個機制是經過參數innodb_random_read_ahead
來控制的,他默認是OFF,也就是這個規則是關閉的
三、全表掃描
statement
,statement模式下,記錄單元爲語句。即每個sql形成的影響會記錄。因爲sql的執行是有上下文的,所以在保存的時候須要保存相關的信息,同時還有一些使用了函數之類的語句沒法被記錄複製。row
,row級別下,記錄單元爲每一行的改動,基本是能夠所有記下來可是因爲不少操做,會致使大量行的改動(好比alter table),所以這種模式的文件保存的信息太多,日誌量太大。mixed
,一種折中的方案,普通操做使用statement記錄,當沒法使用statement的時候使用row。