后台开发人员面试内容——数据库(二)
數(shù)據(jù)庫(kù)鎖分類(lèi)
從數(shù)據(jù)庫(kù)系統(tǒng)角度分為三種:排他鎖、共享鎖、更新鎖。?
從程序員角度分為兩種:一種是悲觀鎖,一種樂(lè)觀鎖。
?
1.樂(lè)觀鎖和悲觀鎖
1).樂(lè)觀鎖:每次不加鎖,假設(shè)沒(méi)有沖突去完成某項(xiàng)操作,如果因?yàn)闆_突失敗就重試,直到成功為止。就是當(dāng)去做某個(gè)修改或其他操作的時(shí)候它認(rèn)為不會(huì)有其他線程來(lái)做同樣的操作(競(jìng)爭(zhēng)),這是一種樂(lè)觀的態(tài)度,通常是基于CAS 原子指令來(lái)實(shí)現(xiàn)的。CAS 通常不會(huì)將線程掛起,因此有時(shí)性能會(huì)好一些。樂(lè)觀鎖的一種實(shí)現(xiàn)方式——CAS。
2).悲觀鎖:還是像它的名字一樣,對(duì)于并發(fā)間操作產(chǎn)生的線程安全問(wèn)題持悲觀狀態(tài),悲觀鎖認(rèn)為競(jìng)爭(zhēng)總是會(huì)發(fā)生,因此每次對(duì)某資源進(jìn)行操作時(shí),都會(huì)持有一個(gè)獨(dú)占的鎖,就像synchronized,不管三七二十一,直接上了鎖就操作資源了
CAS是基于沖突檢測(cè)的樂(lè)觀鎖(非阻塞)
lock、synchronized是悲觀鎖,屬于搶占式,會(huì)引起其他線程阻塞。
volatile提供多線程共享變量可見(jiàn)性和禁止指令重排序優(yōu)化
?
2.悲觀鎖按使用性質(zhì)劃分
1)共享鎖(Share Lock)
S鎖,也叫讀鎖。用于所有的只讀數(shù)據(jù)操作。共享鎖是非獨(dú)占的,允許多個(gè)并發(fā)事務(wù)讀取其鎖定的資源
性質(zhì)?
1. 多個(gè)事務(wù)可封鎖同一個(gè)共享頁(yè);?
2. 任何事務(wù)都不能修改該頁(yè);?
3. 通常是該頁(yè)被讀取完畢,S鎖立即被釋放
?
2)排他鎖(Exclusive Lock)
X鎖,也叫寫(xiě)鎖,表示對(duì)數(shù)據(jù)進(jìn)行寫(xiě)操作。如果一個(gè)事務(wù)對(duì)對(duì)象加了排他鎖,其他事務(wù)就不能再給它加任何鎖了。(某個(gè)顧客把試衣間從里面反鎖了,其他顧客想要使用這個(gè)試衣間,就只有等待鎖從里面打開(kāi)了。)?
1. 僅允許一個(gè)事務(wù)封鎖此頁(yè);?
2. 其他任何事務(wù)必須等到X鎖被釋放才能對(duì)該頁(yè)進(jìn)行訪問(wèn);?
3. X鎖一直到事務(wù)結(jié)束才能被釋放。
?
3)更新鎖
U鎖,在修改操作的初始化階段用來(lái)鎖定可能要被修改的資源,這樣可以避免使用共享鎖造成的死鎖現(xiàn)象。
性質(zhì)?
1. 用來(lái)預(yù)定要對(duì)此頁(yè)施加X(jué)鎖,它允許其他事務(wù)讀,但不允許再施加U鎖或X鎖;?
2. 當(dāng)被讀取的頁(yè)要被更新時(shí),則升級(jí)為X鎖;?
3. U鎖一直到事務(wù)結(jié)束時(shí)才能被釋放。
?
3.悲觀鎖按作用范圍劃分為:行鎖、表鎖
1)行鎖
鎖的作用范圍是行級(jí)別。
2)表鎖
鎖的作用范圍是整張表。
數(shù)據(jù)庫(kù)能夠確定那些行需要鎖的情況下使用行鎖,如果不知道會(huì)影響哪些行的時(shí)候就會(huì)使用表鎖。
?
數(shù)據(jù)庫(kù)表與表之間關(guān)系
1.一對(duì)一關(guān)系: 兩個(gè)表,在第一個(gè)表中的某一行只與第二個(gè)表中的一行相關(guān),同時(shí)第二個(gè)表中的某一行,也只與第一個(gè)表中的一行相關(guān),我們稱這兩個(gè)表為一對(duì)一關(guān)系。
情況一:一個(gè)表包含了太多的數(shù)據(jù)列
情況二:將數(shù)據(jù)分離到不同的表,劃分不同的安全級(jí)別。
情況三:將常用數(shù)據(jù)列抽取出來(lái)組成一個(gè)表
?
2.一對(duì)多關(guān)系:
定義:有多張表,第一個(gè)表中的行可以與第二個(gè)表中的一到多個(gè)行相關(guān)聯(lián),但是第二個(gè)表中的一行只能與第一個(gè)表中的一行相關(guān)聯(lián)。
一對(duì)多關(guān)系是最常見(jiàn)的關(guān)系類(lèi)型。
3.多對(duì)多關(guān)系:
定義:有兩個(gè)表,第一個(gè)表的一行可以與第二個(gè)表中的一到多個(gè)行相關(guān)聯(lián),同時(shí),第二個(gè)表中的一行可以與第一個(gè)表中的一到多個(gè)行相關(guān)聯(lián)
?
數(shù)據(jù)庫(kù)索引分類(lèi)
1.定義:
沒(méi)建立索引:默認(rèn)的方式是根據(jù)搜索條件進(jìn)行全表掃描,遇到匹配條件的就加入搜索結(jié)果集合,時(shí)間復(fù)雜度為O(N)
建立索引: 通過(guò)不斷的縮小想要獲得數(shù)據(jù)的范圍來(lái)篩選出最終想要的結(jié)果,同時(shí)把隨機(jī)的事件變成順序的事件(類(lèi)似于書(shū)目錄), 對(duì)某一字段增加索引,查詢時(shí)就會(huì)先去索引列表中一次定位到特定值的行數(shù),大大減少遍歷匹配的行數(shù),所以能明顯增加查詢的速度。?
首先去索引列表中查詢,而我們的索引列表是B類(lèi)樹(shù)的數(shù)據(jù)結(jié)構(gòu),查詢的時(shí)間復(fù)雜度為O(log2N),定位到特定值得行就會(huì)非???#xff0c;所以其查詢速度就會(huì)非???。?
索引是一種數(shù)據(jù)結(jié)構(gòu)。索引本身很大,不可能全部存儲(chǔ)在內(nèi)存中,因此索引以索引表的形式存儲(chǔ)在磁盤(pán)中
作用:提高查詢速度、確保數(shù)據(jù)的唯一性、可以加速表和表之間的連接,實(shí)現(xiàn)表和表之間的參照完整性、使用分組和排序子句進(jìn)行數(shù)據(jù)檢索時(shí),可以減少分組和排序的時(shí)間、全文檢索字段進(jìn)行搜素優(yōu)化
2.分類(lèi):
1)主鍵索引(PRIMAY KEY):
PRIMARY KEY (`id`),
數(shù)據(jù)庫(kù)表經(jīng)常有一列或列組合,其值唯一標(biāo)識(shí)表中的每一行。該列稱為表的主鍵,該索引要求主鍵中的每個(gè)值都唯一。當(dāng)在查詢中使用主鍵索引時(shí),它還允許對(duì)數(shù)據(jù)的快速訪問(wèn)。
2)唯一索引(UNIQUE):
CREATE UNIQUE INDEX indexName ON table(column(length))
表明此索引的每一個(gè)索引值只對(duì)應(yīng)唯一的數(shù)據(jù)記錄,對(duì)于單列惟一性索引,這保證單列不包含重復(fù)的值。對(duì)于多列惟一性索引,保證多個(gè)值的組合不重復(fù)。
3)常規(guī)索引(INDEX)
CREATE INDEX index_name ON table(column(length))
4)全文索引(FULLTEXT)
CREATE FULLTEXT INDEX index_content ON article(content)
查詢時(shí)指定方式:SELECT * FROM tab_name WHERE MATCH (col1,col2) AGAINST (search_word);
5)聚集索引和非聚集索引
聚集索引: 數(shù)據(jù)按索引順序存儲(chǔ),中子結(jié)點(diǎn)存儲(chǔ)真實(shí)的物理數(shù)據(jù)
非聚集索引:存儲(chǔ)指向真正數(shù)據(jù)行的指針
3.實(shí)現(xiàn)方式:
最常用——B+樹(shù)索引
1)B+樹(shù)中間節(jié)點(diǎn)沒(méi)有數(shù)據(jù),所以同樣大小的磁盤(pán)頁(yè)上可以容納更多節(jié)點(diǎn)元素
2)B+樹(shù)的查詢必須最終找到葉子節(jié)點(diǎn),而B(niǎo)-樹(shù)只需要找到匹配的元素即可
3)B-樹(shù)只能依靠繁瑣的中序遍歷,而B(niǎo)+樹(shù)只需要在鏈表上遍歷即可
次之——hash索引
哈希索引就是采用一定的哈希算法,把鍵值換算成新的哈希值,檢索時(shí)不需要類(lèi)似B+樹(shù)那樣從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)逐級(jí)查找,只需一次哈希算法即可立刻定位到相應(yīng)的位置,速度非???/p>
區(qū)別:
1)Hash 索引僅僅能滿足"=",和"<=>"等值查詢,不能使用范圍查詢。
2)Hash 索引無(wú)法被用來(lái)避免數(shù)據(jù)的排序操作。Hash 索引比較的是進(jìn)行 Hash 運(yùn)算之后的 Hash 值, 經(jīng)過(guò)相應(yīng)的 Hash 算法處理之后的 Hash 值的大小關(guān)系,并不能保證和Hash運(yùn)算前完全一樣。
3) Hash 索引不支持多列聯(lián)合索引的最左匹配規(guī)則
4)在有大量重復(fù)鍵值情況下,哈希索引的效率也是極低的,因?yàn)榇嬖谒^的哈希碰撞問(wèn)題
4.索引匹配規(guī)則
最左匹配規(guī)則
5.索引失效:
1)where語(yǔ)句中帶有or, 但是沒(méi)有把or中所有字段加上索引
2)where語(yǔ)句中使用 != 或 <> 操作符
3)where語(yǔ)句中l(wèi)ike查詢以‘%’開(kāi)頭時(shí),不會(huì)使用
4)where語(yǔ)句中使用not?in,not?exist會(huì)讓索引失效
4)多列索引的第一部分沒(méi)有使用索引的話,將不會(huì)使用索引,只要第一列使用了索引,后面的列不帶索引也會(huì)生效
5) 如果列類(lèi)型是字符串,那一定要在條件中將數(shù)據(jù)使用引號(hào)引用起來(lái),否則不會(huì)使用索引
6)當(dāng)全表掃描(未使用索引)比使用索引快時(shí),不會(huì)使用
7)隱式類(lèi)型轉(zhuǎn)換導(dǎo)致索引失效,字符串轉(zhuǎn)int時(shí)
8) 在 where 子句中對(duì)字段進(jìn)行表達(dá)式或函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描
?
內(nèi)連接與外連接
1.內(nèi)連接,也被稱為自然連接,只有兩個(gè)表相匹配的行才能在結(jié)果集中出現(xiàn)。返回的結(jié)果集選取了兩個(gè)表中所有相匹配的數(shù)據(jù),舍棄了不匹配的數(shù)據(jù)。由于內(nèi)連接是從結(jié)果表中刪除與其他連接表中沒(méi)有匹配的所有行,所以內(nèi)連接可能會(huì)造成信息的丟失。內(nèi)連接語(yǔ)法如下:
?
seselect * from t1 inner join t2 on t1.id=t2.id;
?
2.外連接不僅包含符合連接條件的行,還包含左表(左連接時(shí))、右表(右連接時(shí))或兩個(gè)邊接表(全外連接)中的所有數(shù)據(jù)行。 SQL外連接共有三種類(lèi)型:左外連接(關(guān)鍵字為L(zhǎng)EFT OUTER JOIN)、右外連接(關(guān)鍵字為RIGHT OUTER JOIN)和全外連接(關(guān)鍵字為FULL OUTER JOIN)。外連接的用法和內(nèi)連接一樣,只是將INNER JOIN關(guān)鍵字替換為相應(yīng)的外連接關(guān)鍵字即可:
1)左外連接:即以左表為基準(zhǔn),到右表找匹配的數(shù)據(jù),找不到匹配的用NULL 補(bǔ)齊
select * from t1 left join t2 on t1.id=t2.id
1)右外連接:即以右表為基準(zhǔn),到左表找匹配的數(shù)據(jù),找不到匹配的用NULL 補(bǔ)齊
select * from t1 right join t2 on t1.id=t2.id; ID
3)全外連接(FULL JOIN 或 FULL OUTER JOIN):除了顯示符合連接條件的記錄外,在 2 個(gè)表中的其他記錄也顯示出來(lái).
此外,可以用using代替on
a LEFT JOIN b USING (c1,c2,c3)
其作用相當(dāng)于語(yǔ)句:
a LEFT JOIN b ON a.c1=b.c1 AND a.c2=b.c2 AND a.c3=b.c3
?
存儲(chǔ)過(guò)程
SQL語(yǔ)句需要先編譯然后執(zhí)行,而存儲(chǔ)過(guò)程(Stored Procedure)是一組為了完成特定功能的SQL語(yǔ)句集,經(jīng)編譯后存儲(chǔ)在數(shù)據(jù)庫(kù)中,用戶通過(guò)指定存儲(chǔ)過(guò)程的名字并給定參數(shù)(如果該存儲(chǔ)過(guò)程帶有參數(shù))來(lái)調(diào)用執(zhí)行它
語(yǔ)法定義:
DELIMITER //
??CREATE PROCEDURE myproc(OUT s int)
????BEGIN
??????SELECT COUNT(*) INTO s FROM students;
????END
????//
DELIMITER ;
優(yōu)點(diǎn):
1.存儲(chǔ)過(guò)程因?yàn)?SQL 語(yǔ)句已經(jīng)預(yù)編譯過(guò)了,因此運(yùn)行的速度比較快
2.存儲(chǔ)過(guò)程在服務(wù)器端運(yùn)行,減少客戶端的壓力
3.允許模塊化程序設(shè)計(jì),就是說(shuō)只需要?jiǎng)?chuàng)建一次過(guò)程,以后在程序中就可以調(diào)用該過(guò)程任意次,類(lèi)似方法的復(fù)用
4.減少網(wǎng)絡(luò)流量
5. 增強(qiáng)了使用的安全性
缺點(diǎn):調(diào)試麻煩(至少?zèng)]有像開(kāi)發(fā)程序那樣容易),可移植性不靈活(因 為存儲(chǔ)過(guò)程是依賴于具體的數(shù)據(jù)庫(kù))
?
數(shù)據(jù)庫(kù)的三級(jí)范式
第一范式(1NF):數(shù)據(jù)表中的每一列(每個(gè)字段)必須是不可拆分的最小單元,也就是確保每一列的原子性;
第二范式(2NF):滿足1NF后,要求表中的所有列,都必須依賴于主鍵,而不能有任何一列與主鍵沒(méi)有關(guān)系,也就是說(shuō)一個(gè)表只描述一件事情;
第三范式(3NF):必須先滿足第二范式(2NF),要求:表中的每一列只與主鍵直接相關(guān)而不是間接相關(guān),(表中的每一列只能依賴于主鍵)任何非主屬性不依賴于其它非主屬性
?
事物
1.?原子性:一個(gè)事務(wù)(transaction)中的所有操作,要么全部完成,要么全部不完成,不會(huì)結(jié)束在中間某個(gè)環(huán)節(jié)。事務(wù)在執(zhí)行過(guò)程中發(fā)生錯(cuò)誤,會(huì)被回滾(Rollback)到事務(wù)開(kāi) 始前的狀態(tài),就像這個(gè)事務(wù)從沒(méi)有執(zhí)行過(guò)一樣
2. 一致性:在事務(wù)開(kāi)始和完成時(shí),數(shù)據(jù)庫(kù)中的數(shù)據(jù)都保持一致的狀態(tài),數(shù)據(jù)的完整性約束沒(méi)有被破壞。(事務(wù)的執(zhí)行使得數(shù)據(jù)庫(kù)從一種正確狀態(tài)轉(zhuǎn)換成另一種正確狀態(tài))。具體 來(lái)說(shuō)就是,比如表與表之間存在外鍵約束關(guān)系,那么你對(duì)數(shù)據(jù)庫(kù)進(jìn)行的修改操作就必需要 滿足約束條件,即如果你修改了一張表中的數(shù)據(jù),那你還需要修改與之存在外鍵約束關(guān)系 的其他表中對(duì)應(yīng)的數(shù)據(jù),以達(dá)到一致性
3.隔離性:一個(gè)事務(wù)的執(zhí)行不能被其他事務(wù)干擾。為了防止事務(wù)操作間的混淆,必須串行化或序列化請(qǐng) 求,使得在同一時(shí)間僅有一個(gè)請(qǐng)求用于同一數(shù)據(jù)。(在事務(wù)正確提交之前, 不允許把該事務(wù)對(duì)數(shù)據(jù)的任何改變提供給任何其他事務(wù))。(事務(wù)處理過(guò)程中的中間狀態(tài) 對(duì)外部是不可見(jiàn)的)。隔離性通過(guò)鎖就可以實(shí)現(xiàn)
4.持久性:一個(gè)事務(wù)一旦提交,它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變就應(yīng)該是永久性的,并不會(huì)被回滾
BEGIN 或 START TRANSACTION:顯示地開(kāi)啟一個(gè)事務(wù);?
COMMIT:提交事務(wù),并使已對(duì)數(shù)據(jù)庫(kù)進(jìn)行的所有修改稱為永久性的;
ROLLBACK:回滾會(huì)結(jié)束用戶的事務(wù),并撤銷(xiāo)正在進(jìn)行的所有未提交的修改
?
數(shù)據(jù)庫(kù)的隔離性實(shí)現(xiàn)
1.臟讀:是指在一個(gè)事務(wù)處理過(guò)程里讀取了另一個(gè)未提交的事務(wù)中的數(shù)據(jù)。
2.不可重復(fù)讀:是指在對(duì)于數(shù)據(jù)庫(kù)中的某個(gè)數(shù)據(jù),一個(gè)事務(wù)范圍內(nèi)多次查詢卻返回了不同的數(shù)據(jù)值,這是由于在查詢間隔,被另一個(gè)事務(wù)修改并提交了
3.幻讀:是指當(dāng)事務(wù)不是獨(dú)立執(zhí)行時(shí)發(fā)生的一種現(xiàn)象,例如第一個(gè)事務(wù)對(duì)一個(gè)表中的數(shù)據(jù)進(jìn)行了修改,這種修改涉及到表中的全部數(shù)據(jù)行。同時(shí),第二個(gè)事務(wù)也修改這個(gè)表中的數(shù)據(jù),這種修改是向表中插入一行新數(shù)據(jù)。那么,以后就會(huì)發(fā)生操作第一個(gè)事務(wù)的用戶發(fā)現(xiàn)表中還有沒(méi)有修改的數(shù)據(jù)行,就好象發(fā)生了幻覺(jué)一樣
區(qū)別:
1.不可重復(fù)讀和臟讀的區(qū)別是:臟讀是某一事務(wù)讀取了另一個(gè)事務(wù)未提交的臟數(shù)據(jù),而不可重復(fù)讀則是讀取了前一事務(wù)提交的數(shù)據(jù)
2.幻讀和不可重復(fù)讀都是讀取了另一條已經(jīng)提交的事務(wù)(這點(diǎn)就臟讀不同),所不同的是不可重復(fù)讀查詢的都是同一個(gè)數(shù)據(jù)項(xiàng),而幻讀針對(duì)的是一批數(shù)據(jù)整體(比如數(shù)據(jù)的個(gè)數(shù))
?
MySQL數(shù)據(jù)庫(kù)四種隔離級(jí)別:
在MySQL數(shù)據(jù)庫(kù)中默認(rèn)的隔離級(jí)別為Repeatable read (可重復(fù)讀), 在Oracle數(shù)據(jù)庫(kù)中,只支持Serializable (串行化)級(jí)別和Read committed (讀已提交)這兩種級(jí)別,其中默認(rèn)的為Read committed級(jí)別
1.Serializable (串行化):可避免臟讀、不可重復(fù)讀、幻讀的發(fā)生。
2.Repeatable read (可重復(fù)讀):可避免臟讀、不可重復(fù)讀的發(fā)生。
3.Read committed (讀已提交):可避免臟讀的發(fā)生。
4.Read uncommitted (讀未提交):最低級(jí)別,任何情況都無(wú)法保證。
?
判斷表的字段值是否為空
1.查詢字段值為空的語(yǔ)法:where <字段名> is null
2.查詢字段值不為空的語(yǔ)法:where <字段名> is not null 或者where NoT(<字段名> IS?NULL)
?
關(guān)鍵字匯總
alter、update、drop、delete、desc、show、use、truncate、insert?into、as、
distinct、group by、order by、desc、limit、LIKE、in、inner join...on、left(right、full) join....on、union
if、between ... and ....、not、
?
?
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的后台开发人员面试内容——数据库(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 后台开发人员面试内容——操作系统(一)
- 下一篇: 后台开发人员面试内容——Redis非关系