資料庫面試題以及優化整理
1:什麼是事務?什麼是鎖?**
事務:就是被繫結在一起作為一個邏輯工作單元的SQL語句分組,
如果任何一個語句操作失敗那麼整個操作就被失敗,
以後操作就會回滾到操作前狀態,或者是上有個節點。
為了確保要麼執行,要麼不執行,就可以使用事務。
要將有組語句作為事務考慮,就需要通過ACID測試,即(事務四大特性)原子性,一致性,隔離性和永續性。
鎖:在所以的DBMS中,鎖是實現事務的關鍵,鎖可以保證事務的完整性和併發性。與現實生活中鎖一樣,它可以使某些資料的擁有者,在某段時間內不能使用某些資料或資料結構。當然鎖還分級別的。
⑴ 原子性(Atomicity)
原子性是指事務包含的所有操作要麼全部成功,要麼全部失敗回滾,這和前面兩篇部落格介紹事務的功能是一樣的概念,因此事務的操作如果成功就必須要完全應用到資料庫,如果操作失敗則不能對資料庫有任何影響。
⑵ 一致性(Consistency)
一致性是指事務必須使資料庫從一個一致性狀態變換到另一個一致性狀態,也就是說一個事務執行之前和執行之後都必須處於一致性狀態。
拿轉賬來說,假設使用者A和使用者B兩者的錢加起來一共是5000,那麼不管A和B之間如何轉賬,轉幾次賬,事務結束後兩個使用者的錢相加起來應該還得是5000,這就是事務的一致性。
⑶ 隔離性(Isolation)
隔離性是當多個使用者併發訪問資料庫時,比如操作同一張表時,資料庫為每一個使用者開啟的事務,不能被其他事務的操作所幹擾,多個併發事務之間要相互隔離。
即要達到這麼一種效果:對於任意兩個併發的事務T1和T2,在事務T1看來,T2要麼在T1開始之前就已經結束,要麼在T1結束之後才開始,這樣每個事務都感覺不到有其他事務在併發地執行。
關於事務的隔離性資料庫提供了多種隔離級別,稍後會介紹到。
⑷ 永續性(Durability)
永續性是指一個事務一旦被提交了,那麼對資料庫中的資料的改變就是永久性的,即便是在資料庫系統遇到故障的情況下也不會丟失提交事務的操作。
例如我們在使用JDBC操作資料庫時,在提交事務方法後,提示使用者事務操作完成,當我們程式執行完成直到看到提示後,就可以認定事務以及正確提交,即使這時候資料庫出現了問題,也必須要將我們的事務完全執行完成,否則就會造成我們看到提示事務處理完畢,但是資料庫因為故障而沒有執行事務的重大錯誤。
以上介紹完事務的四大特性(簡稱ACID),現在重點來說明下事務的隔離性,當多個執行緒都開啟事務操作資料庫中的資料時,資料庫系統要能進行隔離操作,以保證各個執行緒獲取資料的準確性,在介紹資料庫提供的各種隔離級別之前,我們先看看如果不考慮事務的隔離性,會發生的幾種問題:
1,髒讀
髒讀是指在一個事務處理過程裡讀取了另一個未提交的事務中的資料。
當一個事務正在多次修改某個資料,而在這個事務中這多次的修改都還未提交,這時一個併發的事務來訪問該資料,就會造成兩個事務得到的資料不一致。例如:使用者A向用戶B轉賬100元,對應SQL命令如下
update account set money=money+100 where name=’B’; (此時A通知B)
update account set money=money - 100 where name=’A’;
當只執行第一條SQL時,A通知B檢視賬戶,B發現確實錢已到賬(此時即發生了髒讀),而之後無論第二條SQL是否執行,只要該事務不提交,則所有操作都將回滾,那麼當B以後再次檢視賬戶時就會發現錢其實並沒有轉。
2,不可重複讀
不可重複讀是指在對於資料庫中的某個資料,一個事務範圍內多次查詢卻返回了不同的資料值,這是由於在查詢間隔,被另一個事務修改並提交了。
例如事務T1在讀取某一資料,而事務T2立馬修改了這個資料並且提交事務給資料庫,事務T1再次讀取該資料就得到了不同的結果,傳送了不可重複讀。
不可重複讀和髒讀的區別是,髒讀是某一事務讀取了另一個事務未提交的髒資料,而不可重複讀則是讀取了前一事務提交的資料。
在某些情況下,不可重複讀並不是問題,比如我們多次查詢某個資料當然以最後查詢得到的結果為主。但在另一些情況下就有可能發生問題,例如對於同一個資料A和B依次查詢就可能不同,A和B就可能打起來了……
3,虛讀(幻讀)
幻讀是事務非獨立執行時發生的一種現象。例如事務T1對一個表中所有的行的某個資料項做了從“1”修改為“2”的操作,這時事務T2又對這個表中插入了一行資料項,而這個資料項的數值還是為“1”並且提交給資料庫。而操作事務T1的使用者如果再檢視剛剛修改的資料,會發現還有一行沒有修改,其實這行是從事務T2中新增的,就好像產生幻覺一樣,這就是發生了幻讀。
幻讀和不可重複讀都是讀取了另一條已經提交的事務(這點就髒讀不同),所不同的是不可重複讀查詢的都是同一個資料項,而幻讀針對的是一批資料整體(比如資料的個數)。
現在來看看MySQL資料庫為我們提供的四種隔離級別:
① Serializable (序列化):可避免髒讀、不可重複讀、幻讀的發生。
② Repeatable read (可重複讀):可避免髒讀、不可重複讀的發生。
③ Read committed (讀已提交):可避免髒讀的發生。
④ Read uncommitted (讀未提交):最低級別,任何情況都無法保證。
以上四種隔離級別最高的是Serializable級別,最低的是Read uncommitted級別,當然級別越高,執行效率就越低。像Serializable這樣的級別,就是以鎖表的方式(類似於Java多執行緒中的鎖)使得其他的執行緒只能在鎖外等待,所以平時選用何種隔離級別應該根據實際情況。在MySQL資料庫中預設的隔離級別為Repeatable read (可重複讀)。
在MySQL資料庫中,支援上面四種隔離級別,預設的為Repeatable read (可重複讀);而在Oracle資料庫中,只支援Serializable (序列化)級別和Read committed (讀已提交)這兩種級別,其中預設的為Read committed級別。
在MySQL資料庫中檢視當前事務的隔離級別:
select @@tx_isolation;
在MySQL資料庫中設定事務的隔離 級別:
set [glogal | session] transaction isolation level 隔離級別名稱;
set tx_isolation=’隔離級別名稱;’
事務的作用和使用
事務(Transaction)是併發控制的單位,是使用者定義的一個操作序列。這些操作要麼都做,要麼都不做,是一個不可分割的工作單位。通過事務,SQL Server能將邏輯相關的一組操作繫結在一起,以便伺服器保持資料的完整性。主要用於一些對操作過程的完整性比較高的程式。比如銀行系統,使用者在轉賬的過程中程式出現錯誤,但是這個轉賬操作沒有完成。那麼這個操作就被退回。</pre>
併發和並行
你吃飯吃到一半,電話來了,你一直到吃完了以後才去接,這就說明你不支援併發也不支援並行。
你吃飯吃到一半,電話來了,你停了下來接了電話,接完後繼續吃飯,這說明你支援併發。
你吃飯吃到一半,電話來了,你一邊打電話一邊吃飯,這說明你支援並行。
併發的關鍵是你有處理多個任務的能力,不一定要同時。
並行的關鍵是你有同時處理多個任務的能力。
2:什麼叫檢視?遊標是什麼?
檢視:是一種虛擬的表,具有和物理表相同的功能。可以對檢視進行增,改,查,操作,
檢視通常是有一個表或者多個表的行或列的子集。
對檢視的修改會影響基本表。
它使得我們獲取資料更容易,相比多表查詢。
遊標:是對查詢出來的結果集作為一個單元來有效的處理。遊標可以定在該單元中的特定行,從結果集的當前行檢索一行或多行。可以對結果集當前行做修改。一般不使用遊標,但是需要逐條處理資料的時候,遊標顯得十分重要。
3、檢視的優缺點
優點:
1)對資料庫的訪問,因為檢視可以有選擇性的選取資料庫裡的一部分。
2 )使用者通過簡單的查詢可以從複雜查詢中得到結果。
3 )維護資料的獨立性,試圖可從多個表檢索資料。
4 )對於相同的資料可產生不同的檢視。
缺點:
效能:查詢檢視時,必須把檢視的查詢轉化成對基本表的查詢,如果這個檢視是由一個複雜的多表查詢所定義,那麼,那麼就無法更改資料
4、列舉幾種表連線方式,有什麼區別?
內連線、自連線、外連線(左、右、全)、交叉連線
內連線:只有兩個元素表相匹配的才能在結果集中顯示。
外連線: 左外連線:左邊為驅動表,驅動表的資料全部顯示,匹配表的不匹配的不會顯示。 右外連線:右邊為驅動表,驅動表的資料全部顯示,匹配表的不匹配的不會顯示。 全外連線:連線的表中不匹配的資料全部會顯示出來。
交叉連線: 笛卡爾效應,顯示的結果是連結表數的乘積。
5、在資料庫中查詢語句速度很慢,如何優化?
1.建索引
2.減少表之間的關聯
3.優化sql,儘量讓sql很快定位資料,不要讓sql做全表查詢,應該走索引,把資料 量大的表排在前面
4.簡化查詢欄位,沒用的欄位不要,儘量返回少量資料
5.儘量用PreparedStatement來查詢,不要用Statement
6、資料庫三正規化是什麼?
◆ 第一正規化(1NF):強調的是列的原子性,即列不能夠再分成其他幾列。
考慮這樣一個表:【聯絡人】(姓名,性別,電話)
如果在實際場景中,一個聯絡人有家庭電話和公司電話,那麼這種表結構設計就沒有達到 1NF。要符合 1NF 我們只需把列(電話)拆分,即:【聯絡人】(姓名,性別,家庭電話,公司電話)。1NF 很好辨別,但是 2NF 和 3NF 就容易搞混淆。
◆ 第二正規化(2NF):首先是 1NF,另外包含兩部分內容,一是表必須有一個主鍵;二是沒有包含在主鍵中的列必須完全依賴於主鍵,而不能只依賴於主鍵的一部分。
考慮一個訂單明細表:【OrderDetail】(OrderID,ProductID,UnitPrice,Discount,Quantity,ProductName)。
因為我們知道在一個訂單中可以訂購多種產品,所以單單一個 OrderID 是不足以成為主鍵的,主鍵應該是(OrderID,ProductID)。顯而易見 Discount(折扣),Quantity(數量)完全依賴(取決)於主鍵(OderID,ProductID),而 UnitPrice,ProductName 只依賴於 ProductID。所以 OrderDetail 表不符合 2NF。不符合 2NF 的設計容易產生冗餘資料。
可以把【OrderDetail】表拆分為【OrderDetail】(OrderID,ProductID,Discount,Quantity)和【Product】(ProductID,UnitPrice,ProductName)來消除原訂單表中UnitPrice,ProductName多次重複的情況。
◆ 第三正規化(3NF):首先是 2NF,另外非主鍵列必須直接依賴於主鍵,不能存在傳遞依賴。即不能存在:非主鍵列 A 依賴於非主鍵列 B,非主鍵列 B 依賴於主鍵的情況。
考慮一個訂單表【Order】(OrderID,OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity)主鍵是(OrderID)。
第二正規化(2NF)和第三正規化(3NF)的概念很容易混淆,區分它們的關鍵點在於,2NF:非主鍵列是否完全依賴於主鍵,還是依賴於主鍵的一部分;3NF:非主鍵列是直接依賴於主鍵,還是直接依賴於非主鍵列。
7、表和檢視的關係
檢視其實就是一條查詢sql語句,用於顯示一個或多個表或其他檢視中的相關資料。 表就是關係資料庫中實際儲存資料用的。