1. 程式人生 > >面試常考知識點—資料庫

面試常考知識點—資料庫

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)

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)

刪除索引
可利用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

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

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

檢視索引

mysql> show index from tblname;

設定索引的原則

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

索引的弊端

索引是有代價的:索引檔案本身要消耗儲存空間,同時索引會加重插入、刪除和修改記錄時的負擔,另外,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

或者:

BEGIN WORK
     Operation 1
     Operation 2
     Operation 3
     ...
     Operation N
     (Error Occured)
 ROLLBACK WORK

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

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

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

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

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

巢狀事務

通過下面例項來說明什麼叫巢狀事務

BEGIN WORK
     SubTransaction1:
             BEGIN WORK
                 SubOperationX
             COMMIT WORK
     SubTransaction2:
             BEGIN WORK
                 SubOperationY
             COMMIT WORK
     ...
     SubTransactionN:
             BEGIN WORK
                 SubOperationN
             COMMIT WORK
 COMMIT WORK

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

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

分散式事務
分散式事務通常是指在一個分散式環境下執行的扁平事務,因此需要根據資料所在位置訪問網路中的不同節點,比如:通過建設銀行向招商銀行轉賬,建設銀行和招商銀行肯定用的不是同一個資料庫,同時二者的資料庫也不在一個網路節點上,那麼當用戶跨行轉賬,就是通過分散式事務來保證資料的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)

(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);

(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)

(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)

10.批處理

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

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

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;

執行上面的檔案,test 表在 MyZone 資料庫中:

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

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

此時的batchfile2.txt裡含有query的資訊:

select * from test limit 200;
insert into test select * from test;
insert into test select * from test;

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

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

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;
//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;

上面的查詢語句中,我們使用了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};

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

13.左 右 連線 全連線 內連線

可參考

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