測試面試題集-MySQL數據庫靈魂拷問

1
mysql


什麼是事務?


事務是數據庫操做的最小工做單元,是做爲單個邏輯工做單元執行的一系列操做,這些操做做爲一個總體一塊兒向系統提交,要麼都執行、要麼都不執行,是一組不可再分割的操做集合。sql


通俗理解就是作一件事情的過程,事務封裝了一條dml、或者多條dml語句。這個過程有兩種結果:要麼所有成功、要麼所有失敗。數據庫




2
 什麼是事務的ACID特性?
A=Atomicity ,原子性:事務是數據庫最小邏輯單位。事務中包含的各項操做在一次執行過程當中,只容許出現兩種狀態之一,要麼所有執行成功 ,要麼所有執行失敗。任何一項操做都會致使整個事務的失敗,同時其它已經被執行的操做都將被撤銷並回滾,只有全部的操做所有成功,整個事務纔算是成功完成。

C=Consistency ,一致性:系統老是從一個一致性的狀態轉移到另外一個一致性的狀態。例如從 A 帳戶轉帳到 B 帳戶,不能由於 A 帳戶扣了錢,而 B 帳戶沒有加錢,不管 A 和 B 怎麼轉帳,系統中總額是固定的。若是數據庫系統運行中發生故障,有些事務還沒有完成就被迫中斷,這些未完成事務對數據庫所作的修改有一部分已寫入物理數據庫,這時數據庫就處於一種不正確的狀態,或者說是不一致的狀態。服務器


I=Isolation ,隔離性: 一般來講一個事務在徹底提交以前,對其餘事務是不可見的。也就是說,不一樣的事務併發操做相同的數據時,每一個事務都有各自完整的數據空間。一個事務內部的操做及使用的數據對其它併發事務是隔離的,併發執行的各個事務是不能互相干擾的。網絡


D=Durability ,持久性:事務一旦提交,將永久存在,接下來的其它操做或故障不該該對其執行結果有任何影響。即便服務器系統崩潰或服務器宕機等故障。只要數據庫從新啓動,那麼必定可以將其恢復到事務成功結束後的狀態。併發




3
 事務的隔離級別與對應的問題?

MySQL 的隔離等級對加鎖有影響,因此在分析具體加鎖場景時,首先要肯定當前的隔離等級,分爲如下幾個等級:ide

讀未提交(Read Uncommitted ,簡稱 RU):能夠讀到未提交的讀,基本上不會使用該隔離等級,因此暫時忽略。函數


讀已提交(Read Committed ,簡稱 RC):存在幻讀問題,對當前讀獲取的數據加記錄鎖。高併發


可重複讀(Repeatable Read ,簡稱 RR):不存在幻讀問題,對當前讀獲取的數據加記錄鎖,同時對涉及的範圍加間隙鎖,防止新的數據插入,致使幻讀。優化


序列化(Serializable):從 MVCC 併發控制退化到基於鎖的併發控制,不存在快照讀,都是當前讀,併發效率急劇降低,不建議使用。


隔離級別與對應問題矩陣以下所示:

隔離級別
髒讀
不可重複讀
幻讀
讀未提交



不可重複讀



可重複讀


是(MySQL否)
串行化




注,常見數據庫的默認級別:

  • MySQL 數據庫的默認隔離級別是 Repeatable read (可重複讀)級別。

  • Oracle數據庫中,只支持 Seralizable(順序讀) 和 Read committed(讀已提交)級別,默認的是 Read committed 級別。

  • SQL Server 數據庫中,默認的是 Read committed(讀已提交) 級別。




4
 MySQL是如何解決幻讀的?

事務的隔離級別有4種:讀未提交、讀已提交、可重複讀、串行化,關於在MySQL中InnoDB引擎是如何解決幻讀,一張圖甚過千言萬語:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

綜上,高併發數據庫系統中,爲保證事務與事務之間隔離性和數據一致性,MySQL InnoDB引擎默認是RR的隔離級別,在MySQL 中經過MVCC快照讀和next-key(當前讀)兩種模式解決幻讀問題。




5
 MySQL常見死鎖場景有哪些?


  • 2個事務交叉:同一個事務中出現delete,insert操做;

  • 3個insert事務,一個回滾:三個事務的 insert 語句都是insert ignore into t1(a, b)values("1", "1");

  • 多個事務,間隙鎖形成死鎖:同一個事務中多個update操做致使鎖升級(行鎖升級爲表鎖),併發操做時會致使死鎖;


解決方式:事務拆分,同一個事物中不要出現鎖升級,若是業務需求確實致使有表鎖的出現,直接使用悲觀鎖。




6
 drop、delete與truncate的區別?

drop:drop是DDL,會隱式提交,因此,不能回滾,不會觸發觸發器;drop語句刪除表結構及全部數據,並將表所佔用的空間所有釋放,底層系統文件會變小;drop語句將刪除表的結構所依賴的約束,觸發器,索引,依賴於該表的存儲過程/函數將保留,可是變爲invalid狀態。


truncate:truncate是DDL,會隱式提交,因此,不能回滾,不會觸發觸發器;truncate會刪除表空間,底層系統文件會變小。而且將從新設置高水線和全部的索引,缺省狀況下將空間釋放到minextents個extent,除非使用reuse storage。不會記錄日誌,因此執行速度很快,但不能經過rollback撤消操做,若是一不當心把一個表truncate掉,也是能夠恢復的,只是不能經過rollback來恢復;對於外鍵(foreignkey )約束引用的表,不能使用 truncate table,而應使用不帶 where 子句的 delete 語句;truncatetable不能用於參與了索引視圖的表。


delete:delete是DML,執行delete操做時,每次從表中刪除一行,而且同時將該行的的刪除操做記錄在redo和undo表空間中以便進行回滾(rollback)和重作操做,但要注意表空間要足夠大,須要手動提交(commit)操做才能生效,能夠經過rollback撤消操做;delete可根據條件刪除表中知足條件的數據,若是不指定where子句,那麼刪除表中全部記錄,只刪表數據,刪除操做後,底層系統文件不會變小;delete語句不影響表所佔用的extent,高水線(high watermark)保持原位置不變。


總結:

  • 在速度上,通常來講,drop> truncate > delete。

  • 在使用drop和truncate時必定要注意,雖然能夠恢復,但爲了減小麻煩,仍是要慎重。

  • 若是想刪除部分數據用delete,注意帶上where子句,回滾段要足夠大;若是想刪除表,用drop; 若是想保留表而將全部數據刪除,若是和事務無關,用truncate便可;若是和事務有關,或者想觸發trigger,仍是用delete; 若是是整理表內部的碎片,能夠用truncate跟上reuse stroage,再從新導入/插入數據。



7
 談談對索引的理解?
  • 索引大大減少了服務器須要掃描的數據量;

  • 索引能夠幫助服務器避免排序和臨時表;

  • 索引能夠將隨機IO變成順序IO;


缺點:建立索引和維護索引要耗費時間,這種時間隨着數據量的增長而增長;索引須要佔物理空間,除了數據表佔數據空間以外,每個索引還要佔必定的物理空間,若是要創建聚簇索引,那麼須要的空間就會更大;當對錶中的數據進行增長、刪除和修改的時候,索引也要動態的維護,這樣就下降了數據的維護速度。



8
 哪些狀況可能沒法使用上索引?
  • 類型轉換:當存在索引列的數據類型隱形轉換,則用不上索引,好比列類型是字符串,那必定要在條件中將數據使用引號引用起來,不然不使用索引;

  • 索引列加函數:加了函數沒法使用上索引;

  • 字符校對規則不對;




9
 一個查詢語句只查詢到一條記錄,可是總在掃描數據庫,試分析緣由?
  • 沒有索引或者沒有用到索引(這是查詢慢最多見的問題,是程序設計的缺陷);

  • 沒有建立計算列致使查詢不優化;

  • 查詢出的數據量過大(能夠採用屢次查詢或其餘方法下降數據量);

  • 查詢語句須要優化;

10   若客戶反饋系統慢,如何查找問題? 第一步:查詢應用服務器,數據庫服務器 CPU使用率,CPU負載,帶寬,內存; 第二步:通常是 CPU 太高,且是mysql進程,則進入數據庫,首先查詢活躍線程數,查詢正在執行的sql,順便也去慢查詢日誌文件; 第三步:找到問題sql,分析sql,經過explain分析具體問題(通常都是數據庫有大量計算操做,大量數據查詢返回沒有作分頁處理); 第四步:檢查是否爲網絡問題。
相關文章
相關標籤/搜索