面試整理-資料庫部分
目錄
1、資料庫學習筆記
1、什麼是儲存過程?有哪些優缺點?與函式有什麼區別?與觸發器有什麼區別?
SQL語句執行的時候要先編譯然後再被執行。在大型資料庫系統中,為了提高效率,將為了完成特定功能的SQL語句集進行編譯優化後,儲存在資料庫伺服器中,使用者通過指定的儲存過程的名字來呼叫執行。儲存過程是一組預編譯的SQL語句。
優點:
- 可以將程式碼封裝起來;
- 儲存在資料庫之中;
- 讓編譯語言進行呼叫;
- 儲存過程是一個預編譯的程式碼塊,執行效率比較高。
- 一個儲存過程替代大量Sql語句,可以降低網路通訊量,提高通訊速率。
缺點:
- 每個資料庫的儲存過程語法都不一樣,十分難以維護。
- 業務邏輯放在資料庫上,難以迭代。
與函式的區別:
- 儲存過程是預編譯的,執行效率比函式高。
- 儲存過程可以不返回任何值,也可以返回多個輸出變數,但函式有且必須返回一個值。
- 儲存過程必須單獨執行,而函式可以嵌入表示式中,使用更靈活。
- 儲存過程主要是用於對邏輯處理的應用或解決,函式主要是一種功能應用或解決。
與觸發器的區別:
儲存過程必須有使用者、應用程式或者觸發器來顯示的呼叫並執行,而觸發器是當特定時間出現的時候,自動執行或者啟用的,與連線用資料庫中的使用者、或者應用程式無關。
2、三個正規化是什麼?
第一正規化:每個屬性不可再分
第二正規化:消除部分依賴,滿足第一正規化,表中的非主屬性必須完全依賴於主鍵(全部主屬性)
第三正規化:消除傳遞依賴,滿足第二正規化,非主屬性必須互不依賴
3、什麼是檢視?檢視的使用場景有哪些?
檢視是一種虛擬的表,具有和物理表相同的功能。可以對檢視進行增,改,查,操作,試圖通常是有一個表或者多個表的行或列的子集。對檢視的修改不影響基本表。它使得我們獲取資料更容易,相比多表查詢。
只暴露部分欄位給訪問者,所以就建一個虛表,就是檢視。
查詢的資料來源於不同的表,而查詢者希望以統一的方式查詢,這樣也可以建立一個檢視,把多個表查詢結果聯合起來,查詢者只需要直接從檢視中獲取資料,不必考慮資料來源於不同表所帶來的差異
4、什麼是觸發器?
觸發器是一種特殊型別的儲存過程,它由事件觸發,而不是程式呼叫或手工啟動。當資料庫有特殊自操作時,對這些操作由資料庫中的事件來觸來自動完成這些SQL語句。使用觸發器可以月來保證資料的有效性和完整性,完成比約束更復雜的資料約束。根據SQL語句的不同,觸發器可分為兩類:DML觸發器和DLL觸發器。
DML觸發器是當資料庫伺服器發生資料操作語言事件時執行的儲存過程,有After和Instead Of兩種觸發器。After觸發器被啟用觸發是在記錄改變之後進行的一種觸發器。Instead Of觸發器是在記錄變更之前,去執行觸發器本身所定義的操作,而不是執行原來SQL語句裡的操作。DLL觸發器是在響應資料定義語言事件時執行的儲存過程。
觸發器主要作用表現在以下幾個方面:
- 增加安全性。
- 利用觸發器記錄所進行的修改以及相關資訊,跟蹤使用者對資料庫的操作,實現審計。
- 維護那些通過建立表時的宣告約束不可能實現的複雜的完整性約束以及對資料庫中特定事件進行監控與響應。
- 實現複雜的非標準的資料庫相關完整性規則、同步實時地複製表中的資料。
- 觸發器是自動的,它們在對錶的資料做了任何修改之後就會被啟用。例如,可以自動計算資料值,如果資料的值達到了一定的要求,則進行特定的處理。以某企業財務管理為例,如果企業的資金鍊出現短缺,並且達到某種程度時,則傳送警告資訊。
引申:觸發器分為事前觸發和事後觸發,兩者有什麼區別?語旬組觸發和行組觸發有什麼區別?
事前觸發發生在事件發生之前驗證一些條件或進行有一些準備工作;事後觸發器發生在事件發生之後,做收尾工作,保證事務的完整性。而事前觸發可以獲得之前和新的欄位值。語句級觸發器可以在語句執行之前或之後執行,而行級觸發在觸發器所影響的每一行觸發一次。
5、什麼是遊標?
在資料庫中,遊標提供了一種對從表中檢索出的資料進行操作的靈活手段。它實際上是一種能從包括多條資料記錄的結果集中每次提取一條記錄的機制。
遊標總是與一條SQL選擇語句相關聯,因為遊標由結果集(可以是零條、一條或由相關的選擇語句檢索出的多條記錄)和結果集中指向特定記錄的遊標位置組成。當決定對結果集進行處理時,必須宣告一個指向該結果集的遊標。
遊標允許應用程式對查詢語句select返回的行結果集中每一行進行相同或不同的操作,而不是一次對整個結果集進行同一種操作。它還提供對基於遊標位置而對錶中資料進行刪除或更新的能力。而且,正是遊標把作為面向集合的資料庫管理系統和麵向行的程式設計兩者聯絡起來,使兩個資料處理方式能夠進行溝通。
遊標的優點有以下兩個方面的內容:
- 在使用遊標的表中,對行提供刪除和更新的能力。
- 遊標將面向集合的資料庫管理系統和麵向行的程式設計連線了起來。
6、SQL
(1)Drop、delete與truncate的區別以及應用場景。
drop table
1)屬於DDL
2)不可回滾
3)不可帶where
4)表內容和結構刪除
5)刪除速度快
truncate table
1)屬於DDL
2)不可回滾
3)不可帶where
4)表內容刪除
5)刪除速度快
delete from
1)屬於DML
2)可回滾
3)可帶where
4)表結構在,表內容要看where執行的情況
5)刪除速度慢,需要逐行刪除
應用場景:
1、 不再需要一張表的時候,用drop
2、 想刪除部分資料行時候,用delete,並且帶上where子句
3、 保留表而刪除所有資料的時候用truncate
(2)SQL約束有幾種?
NOT NULL: 用於控制欄位的內容一定不能為空(NULL)。
UNIQUE: 控制元件欄位內容不能重複,一個表允許有多個 Unique 約束。
PRIMARY KEY: 也是用於控制元件欄位內容不能重複,但它在一個表只允許出現一個。
FOREIGN KEY: 用於預防破壞表之間連線的動作,也能防止非法資料插入外來鍵列,因為它必須是它指向的那個表中的值之一。
CHECK:用於控制欄位的值範圍。
DEFAULT: 用於設定新記錄的預設值。
(3)SQL注入是什麼?如何避免?
- sql注入:使用者輸入的資料,未經檢測,變成了sql語句的一部分被執行,造成意外的結果輸出。
- 避免sql注入:避免資料變成程式碼被執行,對sql語句進行預編譯和查詢引數繫結,在SQL語句中放置佔位符'?',然後將帶有佔位符的SQL語句傳給資料庫編譯,執行的時候才將使用者輸入的資料作為執行的引數傳給資料庫。這樣的操作不僅使得SQL語句在書寫的時候不再需要拼接,看起來也更直接,而且使用者輸入的資料也沒有機會被送到資料庫的SQL直譯器被編譯執行,也不會越權變成程式碼。
- 例項:登入介面使用者名稱輸入:admin' or 1=1 '
7、索引是什麼?有什麼作用以及優缺點?
索引的定義:
索引是與表或檢視關聯的磁碟上結構,即對錶中列值排序的一種結構 ,可以加快從表或檢視中檢索行的速度,執行查詢時不必掃描整個表就能更快速的訪問資料庫中的資訊。
一條索引記錄包含鍵值和邏輯指標。建立索引時,系統分配一個索引頁。在表中插入一行 資料,同時也向該索引頁中插入一行索引記錄。索引記錄包含的索引欄位值比真 實資料量小,節省了空間。
索引的特點:
- 索引一旦建立,*Oracle管理系統會對其進行自動維護*,而且由Oracle管理系統決定何時使用索引。
- 使用者不用再查詢語句中指定使用哪個索引。
- 在定義primary key或unique約束後系統自動在相應的列上建立索引。
- 使用者也能按照自己的需求,對指定單個或多個欄位新增索引。
索引的使用場景:
何時要建立索引:
- 表經常進行SELECT操作
- 表很大(記錄超多),記錄內容分佈範圍很廣。
- 列名經常在WHERE子句或連結條件中出現。
何時不用建立索引:
- 表經常進行INSERT/UPDATE/DELETE操作。
- 表很小。
- 列名不經常作為連線條件或出現在WHERE子句中。
索引優缺點:
- 索引加快資料庫的檢索速度
- 索引降低了插入、刪除、修改等維護任務的速度。
- 唯一索引可以確保每一行資料的唯一性,通過索引,可以在查詢的過程中使用優化隱藏器,提高系統的效能。
- 索引需要佔用物理和資料空間。
索引分類:
- 唯一索引:唯一索引不允許兩行具有相同的索引值。
- 主鍵索引:為表定義一個主鍵將自動建立主鍵索引,主鍵索引是唯一索引的特殊型別。主鍵索引要求主鍵中的每個值是唯一的,並且不能為空。
- 聚簇索引:表中各行的物理順序與鍵值的邏輯(索引)順序相同,每個表只能有一個。
- 非聚集索引:非聚集索引指定表的邏輯順序。資料儲存在一個位置,索引儲存在另一個位置,索引中包含指向資料儲存位置的指標。可以有多個,小於249個。
- 全文索引(倒排索引)
索引的實現方式:
1、B+樹
首先介紹B樹:
B+樹的特點:
- 有n棵子樹的結點中含有n個關鍵字,每個關鍵字不儲存資料,只用來索引,所有資料都儲存在葉子節點。
- 所有的葉子結點中包含了全部關鍵字的資訊,及指向含這些關鍵字記錄的指標,且葉子結點本身依關鍵字的大小自小而大順序連結。
- 所有的非終端結點可以看成是索引部分,結點中僅含其子樹(根結點)中的最大(或最小)關鍵字。
通常在B+樹上有兩個頭指標,一個指向根結點,一個指向關鍵字最小的葉子結點。
與B樹的比較:
- 所有的葉子結點中包含了全部關鍵字的資訊,及指向含有這些關鍵字記錄的指標,且葉子結點本身依關鍵字的大小自小而大的順序連結。(而B 樹的葉子節點並沒有包括全部需要查詢的資訊)
- 所有的非終端結點可以看成是索引部分,結點中僅含有其子樹根結點中最大(或最小)關鍵字。(而B 樹的非終節點也包含需要查詢的有效資訊)
我們經常聽到B+樹就是這個概念,用這個樹的目的和紅黑樹差不多,也是為了儘量保持樹的平衡,當然紅黑樹是二叉樹,但B+樹就不是二叉樹了,節點下面可以有多個子節點,資料庫開發商會設定子節點數的一個最大值,這個值不會太小,所以B+樹一般來說比較矮胖,而紅黑樹就比較瘦高了。ORACLE的預設索引就是這種結構的。
如果經常需要同時對兩個欄位進行AND查詢,那麼使用兩個單獨索引不如建立一個複合索引,因為兩個單獨索引通常資料庫只能使用其中一個,而使用複合索引因為索引本身就對應到兩個欄位上的,效率會有很大提高。
2、雜湊索引
通過雜湊函式來定位的一種索引,不過很少有單獨使用雜湊索引的,反而是雜湊檔案組織用的比較多。
雜湊檔案組織就是根據一個鍵通過雜湊計算把對應的記錄都放到同一個槽中,這樣的話相同的鍵值對應的記錄就一定是放在同一個檔案裡了,也就減少了檔案讀取的次數,提高了效率。
雜湊索引就是根據對應鍵的雜湊碼來找到最終的索引項的技術,其實和B樹就差不多了,也就是一種索引之上的二級輔助索引,我理解雜湊索引都是二級或更高階的稀疏索引,否則桶就太多了,效率也不會很高。
3、點陣圖索引
點陣圖索引是一種針對多個欄位的簡單查詢設計的一種特殊的索引,適用範圍比較小,只適用於欄位值固定並且值的種類很少的情況,比如性別,只能有男和女,或者級別,狀態等等,並且只有在同時對多個這樣的欄位查詢時才能體現出點陣圖的優勢。
點陣圖的基本思想就是對每一個條件都用0或者1來表示,如有5條記錄,性別分別是男,女,男,男,女,那麼如果使用點陣圖索引就會建立兩個點陣圖,對應男的10110和對應女的01001,這樣做有什麼好處呢,就是如果同時對多個這種型別的欄位進行and或or查詢時,可以使用按位與和按位或來直接得到結果了。MySQL不支援。
三種索引實現方式的比較:
- B+樹最常用,效能也不差,用於範圍查詢和單值查詢都可以。特別是範圍查詢,非得用B+樹這種順序的才可以了。
- HASH的如果只是對單值查詢的話速度會比B+樹快一點,但是ORACLE好像不支援HASH索引,只支援HASH表空間。
- 點陣圖的使用情況很侷限,只有很少的情況才能用,一定要確定真正適合使用這種索引才用(值的型別很少並且需要複合查詢,比如性別),否則建立一大堆點陣圖就一點意義都沒有了。
使用索引查詢一定能提高查詢效能嗎?為什麼?
通常,通過索引查詢資料比全表掃描要快。但是我們也必須注意到它的代價。
索引需要空間來儲存,也需要定期維護, 每當有記錄在表中增減或索引列被修改時,索引本身也會被修改。這意味著每條記錄的INSERT,DELETE,UPDATE將為此多付出4,5 次的磁碟I/O.。因為索引需要額外的儲存空間和處理,那些不必要的索引反而會使查詢反應時間變慢.使用索引查詢不一定能提高查詢效能,索引範圍查詢(INDEX RANGE SCAN)適用於兩種情況:
- 基於一個範圍的檢索,一般查詢返回結果集小於表中記錄數的30%。
- 基於非唯一性索引的檢索。
對於建立索引的列,資料是均勻分佈好還是不均勻分佈好?
資料均勻分佈比較好。最好每條記錄的索引列的值各不相同,比如ID,這樣查詢效率最高。比如年齡,對於千萬級的大表,分佈還是太集中了,加上索引也沒有太大用處。
比如有一個欄位是性別,需要加索引嗎?又扯到了點陣圖索引。
不需要。性別不是男就是女,這種列加了索引也沒有什麼用。也可以加點陣圖索引。
8、什麼是事務?
作為單個邏輯工作單元執行的一系列操作,要麼完全地執行,要麼完全地不執行。
ACID資料庫事務正確執行的四個基本要素:
原子性(Atomicity):一個事務(Transaction)中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。
一致性(Consistency):在事務開始之前和事務結束以後,資料庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設規則,這包含資料的精準度、串聯新以及後續資料庫可以自發性地完成預定的工作。A轉賬給B,執行事務之前:A+B=100,執行事務之後:A+B=100
隔離性(Isolation):當兩個或者多個事務併發訪問(此處訪問指查詢和修改的操作)資料庫的同一資料時所表現出的互相關係。事務隔離分為不同的級別,包括讀不提交(Read uncommitted)、讀提交(Read committed)、可重複讀(Repeatable read)和序列化(Serializable)。多個事務併發訪問相互之間不影響,A事務的結果不會覆蓋B事務的結果
永續性(Durability):在事務完成以後,該事務對資料庫所作的更改便持久地儲存在資料庫之中,而且是完全的。事務一旦提交,對資料庫資料的改變就是永久性的
由於一項操作通常會包含許多子操作,而這些子操作可能會因為硬體的損壞或其他因素產生問題,要正確實現ACID並不容易。ACID建議資料庫將所有需要更新以及修改的資料一次操作完畢,但實際上並不可行。
目前主要有兩種方式實現ACID:第一種是(WAL)Write ahead logging,也就是日誌式的方式。第二種是Shadow paging。
Write ahead logging(預寫日誌):
1. 事務所引起的所有改動都要記錄在日誌中,在事務提交完成之前,所有的這些記錄必須被寫入硬碟;
2. 一個數據庫的緩衝頁直到被記入日誌後才能發生修改。直到緩衝頁對應的日誌被寫入硬碟後,該緩衝頁才會存入硬碟;
3. 當緩衝頁被修改和日誌被更新修改時,必須加上互斥鎖,以保證改動被記錄到日誌中的順序與它發生的順序是一致的。
以上規則的結果:
如果一條日誌記錄未被存入硬碟,則它可以被忽略,因為該日誌中包含的改動一定屬於未提交的事務。此外,這樣的日誌不能反映已持久化在資料庫中的改動;
日誌記錄按順序記錄系統的改動。加鎖協議(latch protocol)保證如果有對於同一頁改動的兩條日誌記錄,則兩條記錄的順序反映對頁發生改變的順序。
事務隔離級別:
讀未提交(Read uncommitted):允許讀取還未提交的改變了的資料。可能導致髒、幻、不可重複讀。
讀已提交(Read committed):允許在併發事務已經提交後讀取。可防止髒讀,但是幻讀和不可重複讀仍可發生。
可重複讀(Repeatable read):對相同欄位的多次讀取是一致的,除非資料被事務本身改變。可防止髒、不可重複讀,但是幻讀仍可能發生。
序列化(Serializable):完全服從資料庫四種隔離級別,確保不發生髒、幻、不可重複讀。速度最慢,它是通過完全鎖定在事務中涉及的資料表來完成的,事務按順序序列執行。
不考慮隔離性,會引發一下問題:
髒讀:一個事務讀取了另一個事務改寫但還未提交的資料,如果這些資料被回滾,則讀到的資料是無效的。讀到無效資料,導致查詢結果前後不一致。
不可重複讀:在同一個事務中,讀到另一個事務已經提交更新的資料。讀到更新的資料,導致多次讀取同一個資料返回的結果有所不同。
幻讀:一個事務讀取了幾行記錄後,另一個事務插入一些記錄,幻讀就發生了。在後來的查詢中,第一個事務就會發現有些原來沒有的記錄。讀取到新的記錄
MySQL的預設事務隔離級別是Repeatable read。
9、什麼是共享鎖?互斥鎖?
在資料庫中,鎖主要是對資料進行讀/寫的一種保護機制,從資料庫系統的角度來看,一般可以將鎖分為共享鎖和互斥鎖。共享鎖簡稱S鎖,也叫讀鎖。用於不更改或不更新資料的操作(只讀操作),如select語句。如果事務T對資料A加上共享鎖後,則其他事務只能對A再加共享鎖,不能加排他鎖。共享鎖可阻止其他併發執行的程式獲取重疊的獨佔鎖定,但是允許該程式獲取重疊的共享鎖定。其他使用者可以獲取共享鎖鎖定的資源,但是不能進行修改該共享鎖。在執行select命令時,SQL Server 通常會對物件進行共享鎖鎖定。若事務T對資料D加S鎖,則其他事務只能對D加S 鎖,而不能加X鎖,直至T釋放D上的S鎖;一般要求在讀取資料前要向該資料加共享鎖,所以共享鎖又稱為讀鎖。通常加共享鎖的資料頁被讀取完畢後 ,共享鎖就會立即被釋放。互斥鎖簡稱X鎖,也叫排他鎖,用於資料修改操作,如insert、update或delete。確保不會同時對同一資源進行多重更新。為了保證資料操作的完整性,引入了互斥鎖。用互斥鎖來保證在任意時刻,只能有一個執行緒訪問物件。若事務T對資料D加X鎖,則其他任何事務都不能再對D加任何型別的鎖,直至T釋放D上的X鎖;一般要求在修改資料前要向該資料加排他鎖,所以排他鎖又稱為寫鎖。
而對於鎖的使用,也有一定的限制,需要遵守兩個事項:
1)先鎖後操作;2)事務結束之後必須解鎖。
10、超鍵、候選鍵、主鍵、外來鍵分別是什麼?
超鍵:在關係中能唯一標識元組的屬性集稱為關係模式的超鍵。一個屬性可以為作為一個超鍵,多個屬性組合在一起也可以作為一個超鍵。超鍵包含候選鍵和主鍵。
候選鍵:是最小超鍵,即沒有冗餘元素的超鍵。
主鍵:資料庫表中對儲存資料物件予以唯一和完整標識的資料列或屬性的組合。一個數據列只能有一個主鍵,且主鍵的取值不能缺失,即不能為空值(Null)。
外來鍵:在一個表中存在的另一個表的主鍵稱此表的外來鍵。
11、資料庫運行於哪種狀態下可以防止資料的丟失?
在archivelog mode(歸檔模式)只要其歸檔日誌檔案不丟失,就可以有效地防止資料丟失。
12、varchar和char的區別?
Char是一種固定長度的型別,varchar是一種可變長度的型別。
13、資料庫連線
通過JDBC訪問資料庫包含下面哪幾步?
1. 載入JDBC驅動程式
2. 提供JDBC連線的URL
3. 建立資料庫的連線
4. 建立一個Statement
5. 執行SQL語句
6. 處理結果
7. 關閉JDBC物件
14、資料庫優化的思路
SQL優化:
1、選擇最有效的表名順序
資料庫的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最後的表將被最先處理。
如果三個表是完全無關係的話,將記錄和列名最少的表,寫在最後,然後依次類推,也就是說:選擇記錄條數最少的表放在最後。如果三個表是有關係的話,將引用最多的表,放在最後,然後依次類推,被其他表所引用的表放在最後。
2、WHERE子句中的連結順序
資料庫採用自右而左的順序解析WHERE子句,根據這個原理,表之間的連線必須寫在其他WHERE條件之左,那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的之右。
3、SELECT子句中避免使用*號
4、用TRUCATE替代DELETE
DELETE是一條一條記錄的刪除,而Truncate是將整個表刪除,保留表結構,這樣比DELETE快
5、多使用內部函式提高SQL效率
例如使用mysql的concat()函式會比使用||來進行拼接快,因為concat()函式已經被mysql優化過了。
6、使用表或列的別名
如果表或列的名稱太長了,使用一些簡短的別名也能稍微提高一些SQL的效能。畢竟要掃描的字元長度就變少了
7、多使用commit
comiit會釋放回滾點
8、善用索引
索引就是為了提高我們的查詢資料的,當表的記錄量非常大的時候,我們就可以使用索引了。
9、SQL寫大寫
我們在編寫SQL 的時候,官方推薦的是使用大寫來寫關鍵字,因為Oracle伺服器總是先將小寫字母轉成大寫後,才執行
10、避免在索引上使用NOT
因為Oracle伺服器遇到NOT後,他就會停止目前的工作,轉而執行全表掃描
11、避免在索引上使用計算
WHERE子句中,如果索引列是函式的一部分,優化器將不使用索引而使用全表掃描,這樣會變得變慢
12、用>=替代>
13、用IN替代OR
14、總是使用索引的第一個列
如果索引是建立在多個列上,只有在它的第一個列被WHERE子句引用時,優化器才會選擇使用該索引。 當只引用索引的第二個列時,不引用索引的第一個列時,優化器使用了全表掃描而忽略了索引。(從左到右的使用索引中的欄位,一個查詢可以只使用索引中的一部份,但只能是最左側部分。例如索引是key index (a,b,c)。 可以支援a | a,b| a,b,c 3種組合進行查詢,但不支援 b,c進行查詢 ,當最左側欄位是常量引用時,索引就十分有效。)
資料庫結構優化:
- 正規化優化: 比如消除冗餘(節省空間。。)
- 反正規化優化:比如適當加冗餘等(減少join)
- 拆分表: 垂直拆分和水平拆分
伺服器硬體優化:
提高機器效能。
15、資料庫死鎖如何防止?
1、事務之間對資源的訪問順序的交替
出現原因:
一個使用者A 訪問表A(鎖住了表A),然後又訪問表B;另一個使用者B 訪問表B(鎖住了表B),然後企圖訪問表A;這時使用者A由於使用者B已經鎖住表B,它必須等待使用者B釋放表B才能繼續,同樣使用者B要等使用者A釋放表A才能繼續,這就死鎖就產生了。
解決方案:
這種死鎖比較常見,是由於程式的BUG產生的,除了調整的程式的邏輯沒有其它的辦法。仔細分析程式的邏輯,對於資料庫的多表操作時,儘量按照相同的順序進行處理,儘量避免同時鎖定兩個資源,如操作A和B兩張表時,總是按先A後B的順序處理, 必須同時鎖定兩個資源時,要保證在任何時刻都應該按照相同的順序來鎖定資源
2、併發修改同一條記錄
出現原因:
主要是由於沒有一次性申請夠許可權導致的。
使用者A查詢一條紀錄,然後修改該條紀錄;這時使用者B修改該條紀錄,這時使用者A的事務裡鎖的性質由查詢的共享鎖企圖上升到獨佔鎖,而使用者B裡的獨佔鎖由於A有共享鎖存在所以必須等A釋放掉共享鎖,而A由於B的獨佔鎖而無法上升的獨佔鎖也就不可能釋放共享鎖,於是出現了死鎖。這種死鎖比較隱蔽,但在稍大點的專案中經常發生。
解決方案:
a. 樂觀鎖,實現寫-寫併發
b. 悲觀鎖:使用悲觀鎖進行控制。悲觀鎖大多數情況下依靠資料庫的鎖機制實現,如Oracle的Select … for update語句,以保證操作最大程度的獨佔性。但隨之而來的就是資料庫效能的大量開銷,特別是對長事務而言,這樣的開銷往往無法承受。
3、索引不當導致的死鎖
如果在事務中執行了一條不滿足條件的語句,執行全表掃描,把行級鎖上升為表級鎖,多個這樣的事務執行後,就很容易產生死鎖和阻塞。類似的情況還有當表中的資料量非常龐大而索引建的過少或不合適的時候,使得經常發生全表掃描,最終應用系統會越來越慢,最終發生阻塞或死鎖。
解決方案:
SQL語句中不要使用太複雜的關聯多表的查詢;
使用“執行計劃”對SQL語句進行分析,對於有全表掃描的SQL語句,建立相應的索引進行優化。
如何避免死鎖?
- 以固定的順序訪問表和行。即按順序申請鎖,這樣就不會造成互相等待的場面。
- 大事務拆小。大事務更傾向於死鎖,如果業務允許,將大事務拆小。
- 在同一個事務中,儘可能做到一次鎖定所需要的所有資源,減少死鎖概率。
- 降低隔離級別。如果業務允許,將隔離級別調低也是較好的選擇,比如將隔離級別從RR調整為RC,可以避免掉很多因為gap鎖造成的死鎖。
- 為表新增合理的索引。如果不走索引將會為表的每一行記錄新增上鎖,死鎖的概率大大增大。
16、索引在什麼情況下失效?
原因:
- 對單欄位建立索引,where條件多欄位
- 複合索引失效,where條件沒有按照複合索引的順序排列
- 對索引列運算,運算子包括(+、-、*、/、!、<>、%、like'%_'(%放在前面)、or、in、exist等),比如where a+1=c
- 型別錯誤,欄位型別為varchar,where條件用number
- 對索引使用內部函式,這種情況下應該建立基於函式的索引
- is null 索引失效,is not null 索引有效
- where子句中使用引數,select id from t where [email protected]。
17、Union和union all的區別?
- 兩者都是合併結果集,但是從使用和效率上都有所不同。
- 對重複結果的處理:UNION在進行錶鏈接後會篩選掉重複的記錄,Union All不會去除重複記錄。
- 對排序的處理:Union將會按照欄位的順序進行排序;UNION ALL只是簡單的將兩個結果合併後就返回。
- 從效率上說,UNION ALL 要比UNION快很多,所以,如果可以確認合併的兩個結果集中不包含重複資料且不需要排序時的話,那麼就使用UNION ALL。
18、用distinct和用group by去重,誰的效率更高?
區別:distinct簡單來說就是用來去重的,而group by的設計目的則是用來聚合統計的,兩者在能夠實現的功能上有些相同之處,但應該仔細區分,因為用錯場景的話,效率相差可以倍計。
效率:加了索引之後 distinct 比沒加索引的distinct 快了107倍。加了索引之後 group by 比沒加索引的group by 快了43倍。再來對比 :distinct 和group by不管是加不加索引group by 都比distinct快。因此使用的時候建議選 group by。
19、Mysql的Innodb和MyIASM引擎。
Innodb引擎:
- 支援事務
- 提供了行級鎖和外來鍵約束(鎖的粒度是row)
- 儲存容量為64TB
- 支援雜湊索引,不支援全文索引。
- 啟動比較慢,而且不會儲存表的行數。當進行Select count(*) from table指令的時候,需要進行掃描全表。
注意:Innodb是基於索引來實現行鎖的。
例: select * from tab_with_index where id = 1 for update;
for update 可以根據條件來完成行鎖鎖定,並且 id 是有索引鍵的列,如果 id 不是索引鍵那麼InnoDB將完成表鎖,,併發將無從談起。
MyIASM引擎:
- 不支援事務
- 不支援行級鎖和外來鍵約束(鎖的粒度是table)
- 儲存容量沒有上限
- 支援全文索引,不支援雜湊索引。
- 儲存了表的行數。當進行Select count(*) from table語句時,可以直接的讀取已經儲存的值而不需要進行掃描全表。
應用場景:
- 大容量的資料集時趨向於選擇Innodb。因為它支援事務處理和故障的恢復。Innodb可以利用資料日誌來進行資料的恢復。主鍵的查詢在Innodb也是比較快的。
- 大批量的插入語句時(這裡是INSERT語句)在MyIASM引擎中執行的比較的快,但是UPDATE語句在Innodb下執行的會比較的快,尤其是在併發量大的時候。
兩種引擎所使用的索引的資料結構是什麼?
- 對於MyIASM引擎來說,B+樹的資料結構中儲存的內容實際上是實際資料的地址值。也就是說它的索引和實際資料是分開的,只不過使用索引指向了實際資料。這種索引的模式被稱為非聚集索引。
- 而Innodb引擎的索引的資料結構也是B+樹,只不過資料結構中儲存的都是實際的資料,這種索引有被稱為聚集索引。
20、ROW_NUMBER() OVER函式的基本用法
語法:ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN)
樣例1:
ROW_NUMBER() OVER (ORDER BY xlh DESC)
簡單的說row_number()從1開始,為每一條分組記錄返回一個數字,這裡的ROW_NUMBER() OVER (ORDER BY xlh DESC) 是先把xlh列降序,再為降序以後的沒條xlh記錄返回一個序號。
樣例2:
row_number() OVER (PARTITION BY COL1 ORDER BY COL2) 表示根據COL1分組,在分組內部根據 COL2排序,而此函式計算的值就表示每組內部排序後的順序編號(組內連續的唯一的)。
SELECT *, Row_Number() OVER (partition by deptid ORDER BY salary desc) rank FROM employee