天天看點

matlab 寫入 MYSQL_阿裡18道常見的MySQL面試題,含解析 - Java鬥帝之路

1、事務具有四個特征

事務就是一組原子性的操作,這些操作要麼全部發生,要麼全部不發生。事務把資料庫從一種一緻性狀态轉換成另一種一緻性狀态。

  • 原子性。事務是資料庫的邏輯工作機關,事務中包含的各操作要麼都做,要麼都不做
  • 一緻性。事 務執行的結果必須是使資料庫從一個一緻性狀态變到另一個一緻性狀态。是以當資料庫隻包含成功事務送出的結果時,就說資料庫處于一緻性狀态。如果資料庫系統 運作中發生故障,有些事務尚未完成就被迫中斷,這些未完成事務對資料庫所做的修改有一部分已寫入實體資料庫,這時資料庫就處于一種不正确的狀态,或者說是 不一緻的狀态。
  • 隔離性。一個事務的執行不能其它事務幹擾。即一個事務内部的//操作及使用的資料對其它并發事務是隔離的,并發執行的各個事務之間不能互相幹擾。
  • 持續性。也稱永久性,指一個事務一旦送出,它對資料庫中的資料的改變就應該是永久性的。接下來的其它操作或故障不應該對其執行結果有任何影響。

2、 Mysql的四種隔離級别以及帶來的問題

  • Read Uncommitted(讀取未送出内容)

在該隔離級别,所有事務都可以看到其他未送出事務的執行結果。本隔離級别很少用于實際應用,因為它的性能也不比其他級别好多少。讀取未送出的資料,也被稱之為髒讀(Dirty Read)。

這是大多數資料庫系統的預設隔離級别(但不是MySQL預設的)。它滿足了隔離的簡單定義:一個事務隻能看見已經送出事務所做的改變。這種隔離級别 也支援所謂 的 不可重複讀(Nonrepeatable Read),因為同一事務的其他執行個體在該執行個體處理其間可能會有新的commit,是以同一select可能傳回不同結果。

這是MySQL的預設事務隔離級别,它確定同一事務的多個執行個體在并發讀取資料時,會看到同樣的資料行。不過理論上,這會導緻另一個棘手的問題:幻讀 (Phantom Read)。

通過強制事務排序,使之不可能互相沖突,進而解決幻讀問題。簡言之,它是在每個讀的資料行上加上共享鎖。在這個級别,可能導緻大量的逾時現象和鎖競争。

matlab 寫入 MYSQL_阿裡18道常見的MySQL面試題,含解析 - Java鬥帝之路

【拓展】

1、髒讀:事務A讀取了事務B更新的資料,然後B復原操作,那麼A讀取到的資料是髒資料

2、不可重複讀:事務 A 多次讀取同一資料,事務 B 在事務A多次讀取的過程中,對資料作了更新并送出,導緻事務A多次讀取同一資料時,結果 不一緻。

3、幻讀:系統管理者A将資料庫中所有學生的成績從具體分數改為ABCDE等級,但是系統管理者B就在這個時候插入了一條具體分數的記錄,當系統管理者A改結束後發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。

不可重複讀側重于修改,幻讀側重于新增或删除(多了或少量行),髒讀是一個事務復原影響另外一個事務。

InnoDB 預設隔離級别為repeatable read,但是通過next-key lock 解決了幻讀,保證了ACID

3、 MySQL支援哪些存儲引擎?

MySQL支援多種存儲引擎,比如InnoDB,MyISAM,Memory,Archive等等.在大多數的情況下,直接選擇使用InnoDB引擎都是最合适的,InnoDB也是MySQL的預設存儲引擎。

MyISAM 和 InnoDB 的差別有哪些:

  • InnoDB支援事務,MyISAM不支援
  • InnoDB支援外鍵,而MyISAM不支援
  • InnoDB是聚集索引,資料檔案是和索引綁在一起的,必須要有主鍵,通過主鍵索引效率很高;MyISAM是非聚集索引,資料檔案是分離的,索引儲存的是資料檔案的指針,主鍵索引和輔助索引是獨立的。
  • Innodb不支援全文索引,而MyISAM支援全文索引,查詢效率上MyISAM要高;
  • InnoDB不儲存表的具體行數,MyISAM用一個變量儲存了整個表的行數。
  • MyISAM采用表級鎖(table-level locking);InnoDB支援行級鎖(row-level locking)和表級鎖,預設為行級鎖。

4 、聚簇索引

在B+樹的索引中,葉子節點可能存儲了目前的key值,也可能存儲了目前的key值以及整行的資料,這就是聚簇索引和非聚簇索引. 在InnoDB中,隻有主鍵索引是聚簇索引,如果沒有主鍵,則挑選一個唯一鍵建立聚簇索引.如果沒有唯一鍵,則隐式的生成一個鍵來建立聚簇索引。

當查詢使用聚簇索引時,在對應的葉子節點,可以擷取到整行資料,是以不用再次進行回表查詢.

那非聚簇索引一定會回表查詢嗎?

不一定,這涉及到查詢語句所要求的字段是否全部命中了索引,如果全部命中了索引,那麼就不必再進行回表查詢。比如:

SELECT id FROM t_user WHERE id =1;

5、MySQL中的varchar和char有什麼差別.

char是一個定長字段,假如申請了

char(10)

的空間,那麼無論實際存儲多少内容.該字段都占用10個字元,而varchar是變長的,也就是說申請的隻是最大長度,占用的空間為實際字元長度+1,最後一個字元存儲使用了多長的空間.

在檢索效率上來講,char > varchar,是以在使用中,如果确定某個字段的值的長度,可以使用char,否則應該盡量使用varchar.例如存儲使用者MD5加密後的密碼,則應該使用char。

6、超大分頁怎麼處理?

資料庫層面,這也是我們主要集中關注的(雖然收效沒那麼大),類似于

select * from table where age > 20 limit 1000000

,10這種查詢其實也是有可以優化的餘地的. 這條語句需要load1000000資料然後基本上全部丢棄,隻取10條當然比較慢. 當時我們可以修改為

select * from table where id in (select id from table where age > 20 limit 1000000,10)

.這樣雖然也load了一百萬的資料,但是由于索引覆寫,要查詢的所有字段都在索引中,是以速度會很快。

7. 什麼是存儲過程?有哪些優缺點?

存儲過程是一些預編譯的SQL語句。

1、更加直白的了解:存儲過程可以說是一個記錄集,它是由一些T-SQL語句組成的代碼塊,這些T-SQL語句代碼像一個方法一樣實作一些功能(對單表或多表的增删改查),然後再給這個代碼塊取一個名字,在用到這個功能的時候調用他就行了。 2、存儲過程是一個預編譯的代碼塊,執行效率比較高,一個存儲過程替代大量T_SQL語句 ,可以降低網絡通信量,提高通信速率,可以一定程度上確定資料安全

但是,在網際網路項目中,其實是不太推薦存儲過程的,比較出名的就是阿裡的《Java開發手冊》中禁止使用存儲過程,我個人的了解是,在網際網路項目中,疊代太快,項目的生命周期也比較短,人員流動相比于傳統的項目也更加頻繁,在這樣的情況下,存儲過程的管理确實是沒有那麼友善,同時,複用性也沒有寫在服務層那麼好。

8、B+樹索引 和 哈希索引、B樹 的差別

b樹:葉子節點跟非葉子節點都儲存資料,有序數組+平衡多叉樹

b+樹:隻有在葉子節點儲存資料,有序數組連結清單+平衡多叉樹。

hash索引:Hash 索引僅僅能滿足"=",和"<=>"等值查詢,不能使用範圍查詢。哈希索引就是采用一定的雜湊演算法,把鍵值換算成新的哈希值,檢索時不需要類似B+樹那樣從根節點到葉子節點逐級查找,隻需一次雜湊演算法即可立刻定位到相應的位置,速度非常快,但是Hash 索引在任何時候都不能避免表掃描。

B+樹索引的關鍵字檢索效率比較平均,不像B樹那樣波動幅度大,在有大量重複鍵值情況下,哈希索引的效率也是極低的,因為存在所謂的哈希碰撞問題。

B+樹隻要周遊葉子節點就可以實作整棵樹的周遊。而且在資料庫中基于範圍的查詢是非常頻繁的,而B樹不支援這樣的操作(或者說效率太低)。

9、事務的實作原理

事務是基于重做日志檔案(redo log)和復原日志(undo log)實作的。

每送出一個事務必須先将該事務的所有日志寫入到重做日志檔案進行持久化,資料庫就可以通過重做日志來保證事務的原子性和持久性。

每當有修改事務時,還會産生undo log,如果需要復原,則根據undo log 的反向語句進行邏輯操作,比如insert 一條記錄就delete 一條記錄。undo log 主要實作資料庫的一緻性。

10、drop、delete與truncate的差別

  • drop直接删掉表有關的一切(資料/結構/限制…),不會記錄日志,為DDL(Data Definition Language,資料庫定義語言)操作。
  • truncate 删除表中所有資料(再插入時自增長id又從1開始),該操作也不會記錄日志是以比較快,為DDL操作。隻能删table。
  • DELETE語句執行删除的過程是每次從表中删除一行,需要記錄日志,比較慢,可以加where 語句,為DML(Data Manipulation Language, 資料操縱語言)。

速度上drop > truncate > delete

11、 MySQL執行查詢的過程

  1. 用戶端通過TCP連接配接發送連接配接請求到mysql連接配接器,連接配接器會對該請求進行權限驗證及連接配接資源配置設定
  2. 查緩存。(當判斷緩存是否命中時,MySQL不會進行解析查詢語句,而是直接使用SQL語句和用戶端發送過來的其他原始資訊。是以,任何字元上的不同,例如空格、注解等都會導緻緩存的不命中。)
  3. 文法分析(SQL文法是否寫錯了)。 如何把語句給到預處理器,檢查資料表和資料列是否存在,解析别名看是否存在歧義。
  4. 優化。是否使用索引,生成執行計劃。
  5. 交給執行器,将資料儲存到結果集中,同時會逐漸将資料緩存到查詢緩存中,最終将結果集傳回給用戶端。
matlab 寫入 MYSQL_阿裡18道常見的MySQL面試題,含解析 - Java鬥帝之路

更新語句執行會複雜一點。需要檢查表是否有排它鎖,寫binlog,刷盤,是否執行commit。

12、哪些情況需要建立索引?

  1. 主鍵自動建立唯一索引
  2. 頻繁作為查詢條件的字段
  3. 查詢中與其他表關聯的字段,外鍵關系建立索引
  4. 單鍵/組合索引的選擇問題,高并發下傾向建立組合索引
  5. 查詢中排序的字段,排序字段通過索引通路大幅提高排序速度
  6. 查詢中統計或分組字段

13、哪些情況不要建立索引?

  1. 表記錄太少
  2. 經常增删改的表
  3. 資料重複且分布均勻的表字段,隻應該為最經常查詢和最經常排序的資料列建立索引(如果某個資料類包含太多的重複資料,建立索引沒有太大意義)
  4. 頻繁更新的字段不适合建立索引(會加重IO負擔)
  5. where條件裡用不到的字段不建立索引

14、百萬級别或以上的資料如何删除

關于索引:由于索引需要額外的維護成本,因為索引檔案是單獨存在的檔案,是以當我們對資料的增加,修改,删除,都會産生額外的對索引檔案的操作,這些操作需要消耗額外的IO,會降低增/改/删的執行效率。是以,在我們删除資料庫百萬級别資料的時候,查詢MySQL官方手冊得知删除資料的速度和建立的索引數量是成正比的。

  1. 是以我們想要删除百萬資料的時候可以先删除索引(此時大概耗時三分多鐘)
  2. 然後删除其中無用資料(此過程需要不到兩分鐘)
  3. 删除完成後重新建立索引(此時資料較少了)建立索引也非常快,約十分鐘左右。
  4. 與之前的直接删除絕對是要快速很多,更别說萬一删除中斷,一切删除會復原。那更是坑了。

15、索引

MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效擷取資料的資料結構。我們可以簡單了解為:快速查找排好序的一種資料結構。Mysql索引主要有兩種結構:B+Tree索引和Hash索引。

索引一般分為:

  • 普通索引:對關鍵字沒有限制
  • 唯一索引:要求記錄提供的關鍵字不能重複
  • 主鍵索引:要求關鍵字唯一且不為null

删除索引文法:

16、MySQL的binlog有有幾種錄入格式?分别有什麼差別?

有三種格式,statement,row和mixed.

  • statement模式下,記錄單元為語句.即每一個sql造成的影響會記錄.由于sql的執行是有上下文的,是以在儲存的時候需要儲存相關的資訊,同時還有一些使用了函數之類的語句無法被記錄複制.
  • row級别下,記錄單元為每一行的改動,基本是可以全部記下來但是由于很多操作,會導緻大量行的改動(比如alter table),是以這種模式的檔案儲存的資訊太多,日志量太大。
  • mixed. 一種折中的方案,普通操作使用statement記錄,當無法使用statement的時候使用row. 此外,新版的MySQL中對row級别也做了一些優化,當表結構發生變化的時候,會記錄語句而不是逐行記錄.

17、為啥要使用not null?

MySQL中not null其實占空間的,空值才是不占空間的,但這不是禁止使用null的重點。

  • (1)所有使用NULL值的情況,都可以通過一個有意義的值的表示,這樣有利于代碼的可讀性和可維護性,并能從限制上增強業務資料的規範性。
  • (2)NULL值到非NULL的更新無法做到原地更新,更容易發生索引分裂,進而影響性能。

注意:但把NULL列改為NOT NULL帶來的性能提示很小,除非确定它帶來了問題,否則不要把它當成優先的優化措施,最重要的是使用的列的類型的适當性。

  • (3)NULL值在timestamp類型下容易出問題,特别是沒有啟用參數explicit_defaults_for_timestamp
  • (4)NOT IN、!= 等負向條件查詢在有 NULL 值的情況下傳回永遠為空結果,查詢容易出錯。

18、如何檢視慢SQL?

MySQL為我們提供了 explain 關鍵字來直覺的檢視一條SQL的執行計劃。

例如執行:

matlab 寫入 MYSQL_阿裡18道常見的MySQL面試題,含解析 - Java鬥帝之路

執行計劃:

matlab 寫入 MYSQL_阿裡18道常見的MySQL面試題,含解析 - Java鬥帝之路

(1)id

SELECT識别符, 這個不重要。

(2)select_type

SIMPLE: 訓示非子查詢和union的簡單查詢。

PRIMARY:最外面的SELECT。

UNION:UNION中的第二個或後面的SELECT語句

(3)table

輸出的行所引用的表。

(4)type

聯接類型。下面給出各種聯接類型,按照從最佳類型到最壞類型進行排序:

system:表僅有一行(=系統表)。這是const聯接類型的一個特例。

const:表最多有一個比對行,它将在查詢開始時被讀取。因為僅有一行,在這行的列值可被優化器剩餘部分認為是常數。const表很快,因為它們隻讀取一次!

eq_ref:對于每個來自于前面的表的行組合,從該表中讀取一行。這可能是最好的聯接類型,除了const類型。

ref:對于每個來自于前面的表的行組合,所有有比對索引值的行将從這張表中讀取。

ref_or_null:該聯接類型如同ref,但是添加了MySQL可以專門搜尋包含NULL值的行。

index_merge:該聯接類型表示使用了索引合并優化方法。

unique_subquery:該類型替換了下面形式的IN子查詢的ref: value IN (SELECT primary_key FROM single_table WHERE some_expr) unique_subquery是一個索引查找函數,可以完全替換子查詢,效率更高。

index_subquery:該聯接類型類似于unique_subquery。可以替換IN子查詢,但隻适合下列形式的子查詢中的非唯一索引: value IN (SELECT key_column FROM single_table WHERE some_expr)

range:隻檢索給定範圍的行,使用一個索引來選擇行。

index:該聯接類型與ALL相同,除了隻有索引樹被掃描。這通常比ALL快,因為索引檔案通常比資料檔案小。

ALL:對于每個來自于先前的表的行組合,進行完整的表掃描,說明查詢就需要優化了。

一般來說,得保證查詢至少達到range級别,最好能達到ref。

(5)possible_keys

表示查詢時,可能使用的索引,但是不一定使用了這個索引。

(6)key

實際上是使用的索引

如果沒有選擇索引,鍵是NULL。PRIMARY表示使用了主鍵索引。

可以看到上面 t_images 這個表沒有命中索引。

(7)key_len

顯示MySQL決定使用的鍵長度。如果key是NULL,則長度為NULL。在不損失精确性的情況下,長度越短越好。

(8)ref

表示上述表的連接配接比對條件,即哪些列或常量被用于查找索引列上的值,這裡是const 表示,左連接配接是使用了索引。

(9) rows

很重要的一個字段。mysql 查詢優化器根據統計資訊,估算 sql 要查找到結果集需要掃描讀取的資料行數,這個值非常直覺的顯示 sql 效率好壞, 原則上 rows 越少越好。

可以看到上面t_images 這個表掃描了41673行。

(10)extra

explain 中的很多額外的資訊會在 extra 字段顯示, 常見的有以下幾種内容:

  • using filesort :表示 mysql 需額外的排序操作,不能通過索引順序達到排序效果。一般有 using filesort都建議優化去掉,因為這樣的查詢 cpu 資源消耗大。
  • using index:覆寫索引掃描,表示查詢在索引樹中就可查找所需資料,不用掃描表資料檔案,往往說明性能不錯。
  • using temporary:查詢有使用臨時表, 一般出現于排序, 分組和多表 join 的情況, 查詢效率不高,建議優化。
  • using where :表名使用了where過濾。

這隻是面試題的一部分,完整整套面試PDF版,隻需關注公衆号【Java鬥帝】回複“666”即可免費擷取;

matlab 寫入 MYSQL_阿裡18道常見的MySQL面試題,含解析 - Java鬥帝之路
matlab 寫入 MYSQL_阿裡18道常見的MySQL面試題,含解析 - Java鬥帝之路

看完三件事❤️

如果你覺得這篇内容對你還蠻有幫助,我想邀請你幫我三個小忙:

  1. 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。
  2. 關注公衆号 『 Java鬥帝 』,不定期分享原創知識。
  3. 同時公衆号内回複“666”即可免費領取1000道網際網路面試題

繼續閱讀