數據庫原理--面試知識點

很詳細的文章,來自https://blog.csdn.net/xiaomingdetianxia/article/details/72475924

1.存儲過程

是什麼?

我們常用的關係型數據庫是MySQL,操作數據庫的語言一般爲SQL語句,SQL在執行的時候需要要先編譯,然後執行,而存儲過程(Stored Procedure)是一組爲了完成某種特定功能的SQL語句集,經編譯後存儲在數據庫中,用戶通過指定存儲過程的名字並給定參數(如果該存儲過程帶有參數)來調用執行它。

一個存儲過程是一個可編程的函數,它在數據庫中創建並保存。它可以有SQL語句和一些特殊的控制結構組成。當希望在不同的應用程序或平臺上執行相同的函數,或者封裝特定功能時,存儲過程是非常有用的。數據庫中的存儲過程可以看做是對面向對象方法的模擬,它允許控制數據的訪問方式。

優點

(1)存儲過程增強了SQL語言的功能和靈活性:存儲過程可以用流控制語句編寫,有很強的靈活性,可以完成複雜的判斷和較複雜的運算。
(2)存儲過程允許標準組件式編程:存儲過程被創建後,可以在程序中被多次調用,而不必重新編寫該存儲過程的SQL語句。而且可以隨時對存儲過程進行修改,對應用程序源代碼毫無影響。
(3)存儲過程能實現較快的執行速度:如果某一操作包含大量的Transaction-SQL代碼或分別被多次執行,那麼存儲過程要比批處理的執行速度快很多。因爲存儲過程是預編譯的。在首次運行一個存儲過程時,優化器對其進行分析優化,並且給出最終被存儲在系統表中的執行計劃。而批處理的Transaction-SQL語句在每次運行時都要進行編譯和優化,速度相對要慢一些。
(4)存儲過程能減少網絡流量:針對同一個數據庫對象的操作(如查詢、修改),如果這一操作所涉及的Transaction-SQL語句被組織成存儲過程,那麼當在客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句,從而大大增加了網絡流量並降低了網絡負載。
(5)存儲過程可被作爲一種安全機制來充分利用:系統管理員通過執行某一存儲過程的權限進行限制,能夠實現對相應的數據的訪問權限的限制,避免了非授權用戶對數據的訪問,保證了數據的安全。

2.索引

是什麼?

索引(Index)是幫助MySQL高效獲取數據的數據結構;在數據之外,數據庫系統還維護着滿足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,可以在這些數據結構上實現高級查找算法,提高查詢速度,這種數據結構,就是索引。

索引存儲分類

索引是在MySQL的存儲引擎層中實現的,而不是在服務層實現的。所以各種存儲引擎支持的索引並不相同,MySQL目前提供了以下4種索引。

B-Tree 索引:最常見的索引類型,大部分引擎都支持B樹索引。
HASH 索引:只有Memory引擎支持,使用場景簡單。
R-Tree 索引(空間索引):空間索引是MyISAM的一種特殊索引類型,主要用於地理空間數據類型。
Full-text (全文索引):全文索引也是MyISAM的一種特殊索引類型,主要用於全文索引,InnoDB從MySQL5.6版本提供對全文索引的支持。

B-TREE索引類型

普通索引
這是最基本的索引類型,而且它沒有唯一性之類的限制,可以通過以下幾種方式創建:
(1)創建索引: CREATE INDEX 索引名 ON 表名(列名1,列名2,…);
(2)修改表: ALTER TABLE 表名 ADD INDEX 索引名 (列名1,列名2,…);
(3)創建表時指定索引:CREATE TABLE 表名 ( […], INDEX 索引名 (列名1,列名 2,…) );
UNIQUE索引
表示唯一的,不允許重複的索引,若某一字段的信息不能重複(例如身份證號),可以將該字段的索引設置爲unique:
(1)創建索引:CREATE UNIQUE INDEX 索引名 ON 表名(列名1,列名2,…);
(2)修改表:ALTER TABLE 表名ADD UNIQUE 索引名 (列名1,列名2,…);
(3)創建表時指定索引:CREATE TABLE 表名( […], UNIQUE 索引名 (列名1,列名2,…));
主鍵:PRIMARY KEY索引
主鍵是一種唯一性索引,但它必須指定爲“PRIMARY KEY”。可以將其理解爲 索引名固定爲 PRIMARY KEY 的 UNIQUE索引。
(1)主鍵一般在創建表的時候指定:“CREATE TABLE 表名( […], PRIMARY KEY (列的列表) ); ”。
(2)但是,我們也可以通過修改表的方式加入主鍵:“ALTER TABLE 表名 ADD PRIMARY KEY (列的列表); ”。
每個表只能有一個主鍵。 (主鍵相當於聚合索引,是查找最快的索引)
注:不能用CREATE INDEX語句創建PRIMARY KEY索引

常用語法

設置索引
在執行CREATE TABLE語句時可以創建索引,也可以單獨用CREATE INDEX或ALTER TABLE來爲數據表增加索引。

1.ALTER TABLE - ALTER TABLE可以用來創建普通索引、UNIQUE索引或PRIMARY KEY索引。

ALTER TABLE table_name ADD INDEX index_name (column_list)

ALTER TABLE table_name ADD UNIQUE index_name (column_list)

ALTER TABLE table_name ADD PRIMARY KEY (column_list)
  • 1
  • 2
  • 3
  • 4
  • 5

2.CREATE INDEX - CREATE INDEX可對錶增加普通索引或UNIQUE索引。

CREATE INDEX index_name ON table_name (column_list)

CREATE UNIQUE INDEX index_name ON table_name (column_list)
  • 1
  • 2
  • 3

刪除索引
可利用ALTER TABLE或DROP INDEX語句來刪除索引。類似於CREATE INDEX語句,DROP INDEX可以在ALTER TABLE內部作爲一條語句處理,語法如下。

DROP INDEX index_name ON talbe_name

ALTER TABLE table_name DROP INDEX index_name

ALTER TABLE table_name DROP PRIMARY KEY
  • 1
  • 2
  • 3
  • 4
  • 5

其中,前兩條語句是等價的,刪除掉table_name中名爲index_name的索引。
第3條語句只在刪除PRIMARY KEY索引時使用,因爲一個表只可能有一個PRIMARY KEY索引,因此不需要指定索引名。如果沒有創建PRIMARY KEY索引,但表具有一個或多個UNIQUE索引,則MySQL將刪除第一個UNIQUE索引。

如果從表中刪除了某列,則索引會受到影響。對於多列組合的索引,如果刪除其中的某列,則該列也會從索引中刪除。如果刪除組成索引的所有列,則整個索引將被刪除。

查看索引

mysql> show index from tblname;
  • 1

設置索引的原則

  1. 較頻繁的作爲查詢條件的字段應該創建索引
  2. 唯一性太差的字段不適合單獨創建索引,即使頻繁作爲查詢條件
  3. 更新非常頻繁的字段不適合創建索引
  4. 不會出現在 WHERE 子句中的字段不該創建索引
  5. 索引的選擇性較低不宜建索引
    注:所謂索引的選擇性(Selectivity),是指不重複的索引值(也叫基數,Cardinality)與表記錄數的比值,顯然選擇性的取值範圍爲(0, 1]:
SELECT count(DISTINCT(column_name))/count(*) AS Selectivity FROM table_name;
  • 1

索引的弊端

索引是有代價的:索引文件本身要消耗存儲空間,同時索引會加重插入、刪除和修改記錄時的負擔,另外,MySQL在運行時也要消耗資源維護索引,因此索引並不是越多越好。

參考1

3.B+ 樹

這裏寫圖片描述
如上圖,是一顆b+樹,淺藍色的塊我們稱之爲一個磁盤塊,可以看到每個磁盤塊包含幾個數據項(深藍色所示)和指針(黃色所示),如磁盤塊1包含數據項17和35,包含指針P1、P2、P3,P1表示小於17的磁盤塊,P2表示在17和35之間的磁盤塊,P3表示大於35的磁盤塊。真實的數據存在於葉子節點即3、5、9、10、13、15、28、29、36、60、75、79、90、99。非葉子節點不存儲真實的數據,只存儲指引搜索方向的數據項,如17、35並不真實存在於數據表中。

b+樹的查找過程

如圖所示,如果要查找數據項29,那麼首先會把磁盤塊1由磁盤加載到內存,此時發生一次IO,在內存中用二分查找確定29在17和35之間,鎖定磁盤塊1的P2指針,內存時間因爲非常短(相比磁盤的IO)可以忽略不計,通過磁盤塊1的P2指針的磁盤地址把磁盤塊3由磁盤加載到內存,發生第二次IO,29在26和30之間,鎖定磁盤塊3的P2指針,通過指針加載磁盤塊8到內存,發生第三次IO,同時內存中做二分查找找到29,結束查詢,總計三次IO。真實的情況是,3層的b+樹可以表示上百萬的數據,如果上百萬的數據查找只需要三次IO,性能提高將是巨大的,如果沒有索引,每個數據項都要發生一次IO,那麼總共需要百萬次的IO,顯然成本非常非常高。

b+樹性質

1.通過上面的分析,我們知道IO次數取決於b+樹的高度h,假設當前數據表的數據量爲N,每個磁盤塊的數據項的數量是m,則有h=㏒(m+1)N,當數據量N一定的情況下,m越大,h越小;而m = 磁盤塊的大小 / 數據項的大小,磁盤塊的大小也就是一個數據頁的大小,是固定的,如果數據項佔的空間越小,數據項的數量越多,樹的高度越低。這就是爲什麼每個數據項,即索引字段要儘量的小,比如int佔4字節,要比bigint8字節少一半。這也是爲什麼b+樹要求把真實的數據放到葉子節點而不是內層節點,一旦放到內層節點,磁盤塊的數據項會大幅度下降,導致樹增高。當數據項等於1時將會退化成線性表。
2.當b+樹的數據項是複合的數據結構的時候,比如(name,age,sex),b+樹是按照從左到右的順序來建立搜索樹的,比如當(張三,20,F)這樣的數據來檢索的時候,b+樹會優先比較name來確定下一步的所搜方向,如果name相同再依次比較age和sex,最後得到檢索的數據;但當(20,F)這樣的沒有name的數據來的時候,b+樹就不知道下一步該查哪個節點,因爲建立搜索樹的時候name就是第一個比較因子,必須要先根據name來搜索才能知道下一步去哪裏查詢。比如當(張三,F)這樣的數據來檢索時,b+樹可以用name來指定搜索方向,但下一個字段age的缺失,所以只能把名字等於張三的數據都找到,然後再匹配性別是F的數據了, 這個是非常重要的性質,即索引的最左匹配特性。

參考2

4.事務

是什麼?

事務(Transaction)是併發控制的基本單位。所謂的事務,它是一個操作序列,由一條或者多條sql語句組成,這些操作要麼都執行,要麼都不執行,它是一個不可分割的工作單位。

ACID特性

事務應該具有4個屬性:原子性、一致性、隔離性、持久性。

原子性(Atomicity):指整個數據庫事務是不可分割的工作單位。只有事務中所有的數據庫操作都執行成功,整個事務的執行纔算成功。事務中任何一個sql語句執行失敗,那麼已經執行成功的sql語句也必須撤銷,數據庫狀態應該退回到執行事務前的狀態。
一致性(Consistency):事務應確保數據庫的狀態從一個一致狀態轉變爲另一個一致狀態。一致狀態的含義是數據庫中的數據應滿足完整性約束,也就是說在事務開始之前和事務結束以後,數據庫的完整性約束沒有被破壞
隔離性(Isolation):隔離性也叫做併發控制、可串行化或者鎖。事務的隔離性要求每個讀寫事務的對象與其它事務的操作對象能相互分離,即該事務提交前對其它事務都不可見,這通常使用鎖來實現多個事務併發執行時,一個事務的執行不應影響其他事務的執行。
持久性(Durability):表示事務一旦提交了,其結果就是永久性的,也就是數據就已經寫入到數據庫了,如果發生了宕機等事故,數據庫也能將數據恢復。

事務的分類

事務分爲一下5類:

  1. 扁平事務;
  2. 帶有保存點的扁平事務;
  3. 鏈事務;
  4. 嵌套事務;
  5. 分佈式事務。

扁平事務
扁平事務是最簡單的一種,也是實際開發中使用的最多的一種事務。在這種事務中,所有操作都處於同一層次,最常見的方式如下:

 BEGIN WORK
     Operation 1
     Operation 2
     Operation 3
     ...
     Operation N
 COMMIT WORK
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

或者:

BEGIN WORK
     Operation 1
     Operation 2
     Operation 3
     ...
     Operation N
     (Error Occured)
 ROLLBACK WORK
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

扁平事務很簡單,但有一個主要缺點是不能提交或回滾事務的某一部分,或者分幾個獨立的步驟去提交。
比如有這樣的一個例子,我從呼和浩特去深圳,爲了便宜,我可能這麼幹:

 BEGIN WORK
     Operation1:呼和浩特---火車--->北京
     Operation2:北京---飛機--->深圳
 ROLLBACK WORK
  • 1
  • 2
  • 3
  • 4

但是,如果在Operation1中,從呼和浩特到北京的火車晚點了,錯過了航班,怎麼辦?
因爲扁平事務的特性,那我就需要回滾,我需要再回到呼和浩特,這樣做的成本太高,所以就有了下面的第二種事務——帶有保存點的扁平事務。

帶有保存點的扁平事務
這種事務除了支持扁平事務支持的操作外,允許在事務執行過程中回滾到同一事務中較早的一個狀態,這是因爲可能某些事務在執行過程中出現的錯誤並不會對所有的操作都無效,放棄整個事務不合乎要求,開銷也太大。保存點用來通知系統應該記住事務當前的狀態,以便以後發生錯誤時,事務能回到該狀態。

鏈事務
鏈事務,就是指回滾時,只能恢復到最近一個保存點;而帶有保存點的扁平事務則可以回滾到任意正確的保存點。

嵌套事務

通過下面實例來說明什麼叫嵌套事務

BEGIN WORK
     SubTransaction1:
             BEGIN WORK
                 SubOperationX
             COMMIT WORK
     SubTransaction2:
             BEGIN WORK
                 SubOperationY
             COMMIT WORK
     ...
     SubTransactionN:
             BEGIN WORK
                 SubOperationN
             COMMIT WORK
 COMMIT WORK
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

這就是嵌套事務,在事務中再嵌套事務,位於根節點的事務稱爲頂層事務。事務的前驅稱爲父事務,事務的下一層稱爲子事務。

子事務既可以提交也可以回滾,但是它的提交操作並不馬上生效,除非由其父事務提交。因此就可以確定,任何子事務都在頂層事務提交後才真正的被提交了。同理,任意一個事務的回滾都會引起它的所有子事務一同回滾。

分佈式事務
分佈式事務通常是指在一個分佈式環境下運行的扁平事務,因此需要根據數據所在位置訪問網絡中的不同節點,比如:通過建設銀行向招商銀行轉賬,建設銀行和招商銀行肯定用的不是同一個數據庫,同時二者的數據庫也不在一個網絡節點上,那麼當用戶跨行轉賬,就是通過分佈式事務來保證數據的ACID的。

在MySQL中使用事務

在MySQL命令行的默認設置下,事務都是自動提交的,即執行SQL語句後就會馬上執行COMMIT操作。因此要顯示地開啓一個事務須使用命令BEGIN或START TRANSACTION,或者執行命令SET AUTOCOMMIT=0,用來禁止使用當前會話的自動提交。

來看看我們可以使用哪些事務控制語句。

  • BEGIN或START TRANSACTION;顯示地開啓一個事務;
  • COMMIT;也可以使用COMMIT WORK,不過二者是等價的。COMMIT會提交事務,並使已對數據庫進行的所有修改稱爲永久性的;
  • ROLLBACK;有可以使用ROLLBACK WORK,不過二者是等價的。回滾會結束用戶的事務,並撤銷正在進行的所有未提交的修改;
  • SAVEPOINT identifier;SAVEPOINT允許在事務中創建一個保存點,一個事務中可以有多個SAVEPOINT;
  • RELEASE SAVEPOINT identifier;刪除一個事務的保存點,當沒有指定的保存點時,執行該語句會拋出一個異常;
  • ROLLBACK TO identifier;把事務回滾到標記點;
  • SET TRANSACTION;用來設置事務的隔離級別。

事務的隔離級別

在數據庫操作中,爲了有效保證併發讀取數據的正確性,提出的事務隔離級別。
InnoDB存儲引擎提供事務的隔離級別有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。這些隔離級別之間的區別如下:
這裏寫圖片描述

髒讀:一個事務讀取到了另外一個事務沒有提交的數據;
比如:事務T1更新了一行記錄的內容,但是並沒有提交所做的修改。事務T2讀取到了T1更新後的行,然後T1執行回滾操作,取消了剛纔所做的修改。現在T2所讀取的行就無效了;
不可重複讀:在同一事務中,兩次讀取同一數據,得到內容不同;
比如:事務T1讀取一行記錄,緊接着事務T2修改了T1剛纔讀取的那一行記錄。然後T1又再次讀取這行記錄,發現與剛纔讀取的結果不同。這就稱爲“不可重複”讀,因爲T1原來讀取的那行記錄已經發生了變化;
幻讀:同一事務中,用同樣的操作讀取兩次,得到的記錄數不相同;
比如:事務T1讀取一條指定的WHERE子句所返回的結果集。然後事務T2新插入 一行記錄,這行記錄恰好可以滿足T1所使用的查詢條件中的WHERE子句的條件。然後T1又使用相同的查詢再次對錶進行檢索,但是此時卻看到了事務T2剛纔插入的新行。這個新行就稱爲“幻像”,因爲對T1來說這一行就像突然出現的一樣。
隔離級別越低,事務請求的鎖越少或保持鎖的時間就越短。InnoDB存儲引擎默認的支持隔離級別是REPEATABLE READ;在這種默認的事務隔離級別下已經能完全保證事務的隔離性要求,即達到SQL標準的SERIALIZABLE級別隔離。

我們可以可以用SET TRANSACTION語句改變單個會話或者所有新進連接的隔離級別。它的語法如下:

5.視圖

視圖是一種虛擬的表,具有和物理表相同的功能,可以對視圖進行增,改,查操作,視圖通常是有一個表或者多個表的行或列的子集,對視圖的修改不影響基本表,它使得我們獲取數據更容易,相比多表查詢。

6.超鍵 候選鍵 主鍵 外鍵

超鍵:在關係中能唯一標識元組(數據庫中的一條記錄)的屬性集稱爲關係模式的超鍵。一個屬性可以爲作爲一個超鍵,多個屬性組合在一起也可以作爲一個超鍵。超鍵包含候選鍵和主鍵。
候選鍵:是最小超鍵,即沒有冗餘元素的超鍵。
主鍵:數據庫表中對儲存數據對象予以唯一和完整標識的數據列或屬性的組合,用戶選作元組標識的一個侯選鍵稱爲主鍵。一個數據列只能有一個主鍵,且主鍵的取值不能缺失,即不能爲空值(Null)。
外鍵:在一個表中存在的另一個表的主鍵稱此表的外鍵,外鍵主要是用來描述兩個表的關係。

7.三個範式

第一範式(1NF):數據庫表中的字段都是單一屬性的,不可再分。這個單一屬性由基本類型構成,包括整型、實數、字符型、邏輯型、日期型等。

第二範式(2NF):數據庫表中不存在非關鍵字段對任一候選關鍵字段的部分函數依賴(部分函數依賴指的是存在組合關鍵字中的某些字段決定非關鍵字段的情況),也即所有非關鍵字段都完全依賴於任意一組候選關鍵字。
第三範式(3NF):在第二範式的基礎上,數據表中如果不存在非關鍵字段對任一候選關鍵字段的傳遞函數依賴則符合第三範式。所謂傳遞函數依賴,指的是如 果存在”A → B → C”的決定關係,則C傳遞函數依賴於A。因此,滿足第三範式的數據庫表應該不存在如下依賴關係: 關鍵字段 → 非關鍵字段 x → 非關鍵字段y。

8.E-R圖

是什麼?

E-R圖也稱實體-聯繫圖(Entity Relationship Diagram),提供了表示實體類型、屬性和聯繫的方法,用來描述現實世界的概念模型。

E-R方法是“實體-聯繫方法”(Entity-Relationship Approach)的簡稱。它是描述現實世界概念結構模型的有效方法,是表示概念模型的一種方式,用矩形表示實體型,矩形框內寫明實體名;用橢圓表示實體的屬性,並用無向邊將其與相應的實體型連接起來;用菱形表示實體型之間的聯繫,在菱形框內寫明聯繫名,並用無向邊分別與有關實體型連接起來,同時在無向邊旁標上聯繫的類型(1:1,1:n或m:n)。

構成

在ER圖中有如下四個成分:
矩形框:表示實體,在框中記入實體名。
菱形框:表示聯繫,在框中記入聯繫名。
橢圓形框:表示實體或聯繫的屬性,將屬性名記入框中。對於主屬性名,則在其名稱下劃一下劃線。
連線:實體與屬性之間;實體與聯繫之間;聯繫與屬性之間用直線相連,並在直線上標註聯繫的類型。(對於一對一聯繫,要在兩個實體連線方向各寫1; 對於一對多聯繫,要在一的一方寫1,多的一方寫N;對於多對多關係,則要在兩個實體連線方向各寫N,M。)

實體型(Entity):具有相同屬性的實體具有相同的特徵和性質,用實體名及其屬性名集合來抽象和刻畫同類實體;在E-R圖中用矩形表示,矩形框內寫明實體名;比如學生張三丰、學生李尋歡都是實體。如果是弱實體的話,在矩形外面再套實線矩形。
屬性(Attribute):實體所具有的某一特性,一個實體可由若干個屬性來刻畫。在E-R圖中用橢圓形表示,並用無向邊將其與相應的實體連接起來;比如學生的姓名、學號、性別、都是屬性。如果是多值屬性的話,在橢圓形外面再套實線橢圓,如果是派生屬性則用虛線橢圓表示。
聯繫(Relationship):聯繫也稱關係,信息世界中反映實體內部或實體之間的聯繫。實體內部的聯繫通常是指組成實體的各屬性之間的聯繫;實體之間的聯繫通常是指不同實體集之間的聯繫。在E-R圖中用菱形表示,菱形框內寫明聯繫名,並用無向邊分別與有關實體連接起來,同時在無向邊旁標上聯繫的類型(1 : 1,1 : n或m : n),比如老師給學生授課存在授課關係,學生選課存在選課關係。如果是弱實體的聯繫則在菱形外面再套菱形。

聯繫可分爲以下 3 種類型:
(1) 一對一聯繫(1 ∶1)
例如,一個班級有一個班長,而每個班長只在一個班級任職,則班級與班長的聯繫是一對一的。
(2) 一對多聯繫(1 ∶N)
例如,某校教師與課程之間存在一對多的聯繫“教”,即每位教師可以教多門課程,但是每門課程只能由一位教師來教。
(3) 多對多聯繫(M ∶N)
例如,學生與課程間的聯繫(“學 ”)是多對多的,即一個學生可以學多門課程,而每門課程可以有多個學生來學。聯繫也可能有屬性。例如,學生“ 學” 某門課程所取得的成績,既不是學生的屬性也不是課程的屬性。由於“ 成績” 既依賴於某名特定的學生又依賴於某門特定的課程,所以它是學生與課程之間的聯繫“ 學”的屬性。

作圖步驟

⑴確定所有的實體集合
⑵選擇實體集應包含的屬性
⑶確定實體集之間的聯繫
⑷確定實體集的關鍵字,用下劃線在屬性上表明關鍵字的屬性組合
⑸確定聯繫的類型,在用線將表示聯繫的菱形框聯繫到實體集時,在線旁註明聯繫的類型。

實例:
ER圖實例

參考3

參考4

9.處理重複記錄的常用操作

(1)查找表中多餘的重複記錄,重複記錄是根據單個字段(column_name)來判斷。

select * from table_name where column_name in (select column_name from table_name group by column_name having count(column_name) > 1)
  • 1

(2)刪除表中多餘的重複記錄,重複記錄是根據單個字段(column_name)來判斷,只留有id最小的記錄。

delete from table_name where column_name in (select b.column_name from (select column_name from table_name group by column_name having count(column_name)>1)b);
  • 1

(3)查找表中多餘的重複記錄(多個字段)。

select * from table_name a where (a.column_name1,a.column_name2) in (select column_name1,column_name2 from vitae group by column_name1,column_name2 having count(*) > 1)
  • 1

(4)刪除表中多餘的重複記錄(多個字段),只留有rowid最小的記錄 。

delete from table_name a where (a.column_name1,a.column_name2) in (select column_name1,column_name2 from table_name group by column_name1,column_name2 having count(*) > 1) and rowid not in (select min(rowid) from table_name group by column_name1,column_name2 having count(rowid)>1)
  • 1

10.批處理

MySQL 支持以批處理的方式執行一批SQL語句,例如:

create table test(id int,name varchar(20));
insert into test values(1,'watson');
  • 1
  • 2

batchfile.txt裏包含下面的一些SQL 語句,此文件在linux系統中的路徑/home/wming/batchfile.txt:

insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
insert into test select * from test;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

執行上面的文件,test 表在 MyZone 數據庫中:

mysql -uroot -p -D MyZone < /home/wming/batchfile.txt
  • 1

上面的例子通過批處理執行插入語句,下面的例子是通過批處理執行查詢語句:

此時的batchfile2.txt裏含有query的信息:

select * from test limit 200;
insert into test select * from test;
insert into test select * from test;
  • 1
  • 2
  • 3

下面的mysql0716.out就記錄了 select * from test limit 200 查詢語句的結果集。

mysql -uroot -p -D MyZone < /home/wming/batchfile2.txt >/home/wming/mysql0716.out
  • 1

11.MyISAM與InnoDB的區別是什麼?

1、存儲結構

MyISAM:每個MyISAM表在磁盤上存儲成三個文件,文件的名字以表的名字開始,擴展名指出文件類型:.frm文件存儲表定義;數據文件的擴展名爲.MYD (MYData);索引文件的擴展名是.MYI (MYIndex)。
InnoDB:所有的表都保存在同一個數據文件中(也可能是多個文件,或者是獨立的表空間文件),InnoDB表的大小隻受限於操作系統文件的大小,一般爲2GB。

2、存儲空間

MyISAM:可被壓縮,存儲空間較小。支持三種不同的存儲格式:靜態表(默認,但是注意數據末尾不能有空格,會被去掉)、動態表、壓縮表。
InnoDB:需要更多的內存和存儲,它會在主內存中建立其專用的緩衝池用於高速緩衝數據和索引。

3、可移植性、備份及恢復

MyISAM:數據是以文件的形式存儲,所以在跨平臺的數據轉移中會很方便。在備份和恢復時可單獨針對某個表進行操作。
InnoDB:免費的方案可以是拷貝數據文件、備份 binlog,或者用 mysqldump,在數據量達到幾十G的時候就相對痛苦了。

4、事務支持

MyISAM:強調的是性能,每次查詢具有原子性,其執行數度比InnoDB類型更快,但是不提供事務支持。
InnoDB:支持事務,外部鍵等高級數據庫功能。 具有事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表。

這一點是非常重要。事務是一種高級的處理方式,如在一些列增刪改中只要哪個出錯還可以回滾還原,而MyISAM就不可以了。

5、AUTO_INCREMENT

MyISAM:可以和其他字段一起建立聯合索引。引擎的自動增長列必須是索引,如果是組合索引,自動增長可以不是第一列,他可以根據前面幾列進行排序後遞增。
InnoDB: InnoDB中必須包含只有該字段的索引。引擎的自動增長列必須是索引,如果是組合索引也必須是組合索引的第一列。

6、表鎖差異

MyISAM:只支持表級鎖,用戶在操作myisam表時,select,update,delete,insert語句都會給表自動加鎖,如果加鎖以後的表滿足insert併發的情況下,可以在表的尾部插入新的數據。
InnoDB:支持事務和行級鎖,是innodb的最大特色。行鎖大幅度提高了多用戶併發操作的性能。但是InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的。

7、 全文索引

MyISAM:支持 FULLTEXT類型的全文索引。
InnoDB:不支持FULLTEXT類型的全文索引,但是innodb可以使用sphinx插件支持全文索引,並且效果更好。

8、表主鍵

MyISAM:允許沒有任何索引和主鍵的表存在,索引都是保存行的地址。
InnoDB:如果沒有設定主鍵或者非空唯一索引,就會自動生成一個6字節的主鍵(用戶不可見),數據是主索引的一部分,附加索引保存的是主索引的值。

9、 表的具體行數

MyISAM:保存有表的總行數,如果select count() from table;會直接取出出該值。
InnoDB:沒有保存表的總行數,如果使用select count() from table;就會遍歷整個表,消耗相當大,但是在加了wehre條件後,myisam和innodb處理的方式都一樣。

10、CURD操作

MyISAM:如果執行大量的SELECT,MyISAM是更好的選擇。
InnoDB:如果你的數據執行大量的INSERT或UPDATE,出於性能方面的考慮,應該使用InnoDB表。DELETE 從性能上InnoDB更優,但DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除,在innodb上如果要清空保存有大量數據的表,最好使用truncate table這個命令。

11、 外鍵

MyISAM:不支持
InnoDB:支持
通過上述的分析,基本上可以考慮使用InnoDB來替代MyISAM引擎了,原因是InnoDB自身很多良好的特點,比如事務支持、存儲 過程、視圖、行級鎖定等等,在併發很多的情況下,相信InnoDB的表現肯定要比MyISAM強很多。另外,任何一種表都不是萬能的,只用恰當的針對業務類型來選擇合適的表類型,才能最大的發揮MySQL的性能優勢。如果不是很複雜的Web應用,非關鍵應用,還是可以繼續考慮MyISAM的,這個具體視情況而定。
參考

12. 樂觀鎖 與 悲觀鎖

數據庫管理系統(DBMS)中的併發控制的任務是確保在多個事務同時存取數據庫中同一數據時不破壞事務的隔離性和一致性以及數據庫的統一性。

樂觀併發控制(樂觀鎖)和悲觀併發控制(悲觀鎖)是併發控制採用的主要技術手段。

無論是悲觀鎖還是樂觀鎖,都是人們定義出來的概念,可以認爲是一種思想。其實不僅僅是關係型數據庫系統中有樂觀鎖和悲觀鎖的概念,像memcache、hibernate、tair等都有類似的概念。

針對不同的業務場景,應該選用不同的併發控制方式。所以,不要把樂觀併發控制和悲觀併發控制狹義的理解爲僅在DBMS中存在的概念,更不要把他們和數據庫中提供的鎖機制(行鎖、表鎖、排他鎖、共享鎖)混爲一談。其實,在DBMS中,悲觀鎖正是利用數據庫本身提供的鎖機制來實現的。

悲觀鎖

在關係數據庫管理系統裏,悲觀併發控制(又名“悲觀鎖”,Pessimistic Concurrency Control,縮寫“PCC”)是一種併發控制的方法。它可以阻止一個事務以影響其他用戶的方式來修改數據。如果一個事務執行的操作在某行數據上應用了鎖,那只有當這個事務把鎖釋放,其他事務才能夠執行與該鎖衝突的操作。

悲觀併發控制主要用於數據爭用激烈的環境,以及發生併發衝突時使用鎖保護數據的成本要低於回滾事務的成本的環境中。

悲觀鎖:正如其名,它指的是對數據被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度(悲觀),因此,在整個數據處理過程中,將數據處於鎖定狀態。 悲觀鎖的實現,往往依靠數據庫提供的鎖機制 (也只有數據庫層提供的鎖機制才能真正保證數據訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無法保證外部系統不會修改數據)。

悲觀鎖的流程:
1.在對某一記錄進行修改前,先嚐試爲該記錄加上排他鎖(exclusive locking)。
2.如果加鎖失敗,說明該記錄正在被修改,那麼當前操作可能要等待或者拋出異常, 具體響應方式由開發者根據實際情況決定。
3.如果成功加鎖,那麼就可以對記錄做修改,事務完成後就會解鎖了。
4.其間如果有其他事務要對該記錄做修改或加排他鎖,都會等待該事務將該記錄解鎖或直接拋出異常。

MySQL InnoDB中使用悲觀鎖

注意:要使用悲觀鎖,必須先關閉mysql數據庫的自動提交功能,因爲MySQL默認使用autocommit模式,也就是說,當你執行一個更新操作後,MySQL會立刻將結果進行提交。

set autocommit=0;
  • 1
//0.開始事務
begin;/begin work;/start transaction; (三者選一就可以)
//1.查詢出商品信息
select status from t_goods where id=1 for update;
//2.根據商品信息生成訂單
insert into t_orders (id,goods_id) values (null,1);
//3.修改商品status爲2
update t_goods set status=2;
//4.提交事務
commit;/commit work;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

上面的查詢語句中,我們使用了select…for update的方式,這樣就通過開啓排他鎖的方式實現了悲觀鎖。此時在t_goods表中,id爲1的 那條數據就被我們鎖定了,其它事務必須等本次事務提交之後才能對該記錄進行操作。這樣我們可以保證當前的數據不會被其它事務修改。

注意:上面提到,使用select…for update會把數據給鎖住,不過我們需要注意一下鎖的級別,MySQL InnoDB默認爲行級鎖。行級鎖都是基於索引的,如果一條SQL語句沒有用到索引是不會使用行級鎖的,會使用表級鎖把整張表鎖住,這點需要注意。

優點與不足:
優點:悲觀併發控制實際上是採用“先取鎖再訪問”的保守策略,爲數據處理的安全性提供了保證;
缺點:在效率方面,處理加鎖的機制會讓數據庫產生額外的開銷,同時會增加產生死鎖的機率;另外,在只讀型事務中由於不會產生衝突,也沒必要使用鎖,這樣做只會增加系統負載;還會降低並行性,一個事務如果鎖定了某行數據,其他事務就必須等待該事務處理完纔可以處理那行數

樂觀鎖

在關係數據庫管理系統裏,樂觀併發控制(又名“樂觀鎖”,Optimistic Concurrency Control,縮寫“OCC”)是一種併發控制的方法。它假設多用戶併發的事務在處理數據時不會彼此互相影響,各事務能夠在不產生鎖的情況下處理各自影響的那部分數據。在提交數據更新之前,每個事務會先檢查在該事務讀取數據後,有沒有其他事務對該數據做過修改。如果其他事務更新過該數據的話,正在提交的事務會進行回滾。樂觀事務控制最早是由孔祥重(H.T.Kung)教授提出。

樂觀鎖( Optimistic Locking )是相對悲觀鎖而言,樂觀鎖假設數據一般情況下不會造成衝突,所以在事務對數據進行提交更新的時候,纔會正式對數據的衝突與否進行檢測,如果發現衝突了,則返回錯誤信息,讓用戶決定如何去做。

相對於悲觀鎖,在對數據庫進行處理的時候,樂觀鎖並不會使用數據庫提供的鎖機制,一般用記錄數據版本的方式實現樂觀鎖。

數據版本:爲數據增加的一個版本標識。當讀取數據時,將版本標識的值一同讀出,數據每更新一次,便對版本標識進行一次更新。當事務提交更新的時候,需要判斷數據庫表對應記錄的當前版本信息與第一次取出來的版本標識是否一致,如果數據庫表當前版本號與第一次取出來的版本標識值相等,則予以更新,否則認爲是過期數據。

實現數據版本有兩種方式,第一種是使用版本號,第二種是使用時間戳。

使用版本號實現樂觀鎖

使用版本號時,可以在數據初始化時指定一個版本號,每次對數據的更新操作都對版本號執行+1操作。並判斷當前版本號是不是該數據的最新的版本號。

1.查詢出商品信息
select (status,status,version) from t_goods where id=#{id}
2.根據商品信息生成訂單
3.修改商品status爲2
update t_goods 
set status=2,version=version+1
where id=#{id} and version=#{version};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

樂觀併發控制假設事務之間的數據競爭(data race)概率比較小,因此儘可能直接做下去,直到提交的時候纔去鎖定,所以不會產生任何鎖和死鎖。但如果直接簡單這麼做,還是有可能會遇到不可預期的結果,例如兩個事務都讀取了數據庫的某一行,經過修改以後寫回數據庫,這時就遇到了問題。

13.左 右 連接 全連接 內連接

可參考

本文參考自網絡,知識在於分享!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章