1. 程式人生 > 程式設計 >資料庫知識整理

資料庫知識整理

1、資料庫隔離級別有哪些,各自的含義是什麼,MYSQL預設的隔離級別是是什麼。 Read uncommitted:讀未提交,顧名思義,就是一個事務可以讀取另一個未提交事務的資料。

Read committed:讀提交,顧名思義,就是一個事務要等另一個事務提交後才能讀取資料。

Repeatable read:重複讀,就是在開始讀取資料(事務開啟)時,不再允許修改操作。

Serializable 序列化:Serializable 是最高的事務隔離級別,在該級別下,事務序列化順序執行,可以避免髒讀、不可重複讀與幻讀。但是這種事務隔離級別效率低下,比較耗資料庫效能,一般不使用。

值得一提的是:大多數資料庫預設的事務隔離級別是Read committed,比如Sql Server,Oracle。Mysql的預設隔離級別是Repeatable read。

2、什麼是幻讀。

幻讀 : 是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的資料進行了修改,這種修改涉及到表中的全部資料行。 同時,第二個事務也修改這個表中的資料,這種修改是向表中插入一行新資料。那麼,以後就會發生操作第一個事務的使用者發現表中還有沒有修改的資料行,就好象 發生了幻覺一樣。

例如:程式設計師某一天去消費,花了2千元,然後他的妻子去檢視他今天的消費記錄(全表掃描FTS,妻子事務開啟),看到確實是花了2千元,就在這個時候,程式設計師花了1萬買了一部電腦,即新增INSERT了一條消費記錄,並提交。當妻子列印程式設計師的消費記錄清單時(妻子事務提交),發現花了1.2萬元,似乎出現了幻覺,這就是幻讀。

3、MYSQL有哪些儲存引擎,各自優缺點。 兩種儲存引擎的大致區別表現在:

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

2)MyISAM適合查詢以及插入為主的應用,InnoDB適合頻繁修改以及涉及到安全性較高的應用

3)InnoDB支援外來鍵,MyISAM不支援

4)從MySQL5.5.5以後,InnoDB是預設引擎

5)InnoDB不支援FULLTEXT型別的索引

6)InnoDB中不儲存表的行數,如select count() from table時,InnoDB需要掃描一遍整個表來計算有多少行,但是MyISAM只要簡單的讀出儲存好的行數即可。注意的是,當count(

)語句包含where條件時MyISAM也需要掃描整個表。

7)對於自增長的欄位,InnoDB中必須包含只有該欄位的索引,但是在MyISAM表中可以和其他欄位一起建立聯合索引。

8)清空整個表時,InnoDB是一行一行的刪除,效率非常慢。MyISAM則會重建表。

9)InnoDB支援行鎖(某些情況下還是鎖整表,如 update table set a=1 where user like '%lee%'

有人說MYISAM只能用於小型應用,其實這只是一種偏見。

如果資料量比較大,這是需要通過升級架構來解決,比如分表分庫,讀寫分離,而不是單純地依賴儲存引擎。

現在一般都是選用InnoDB了,主要是MyISAM的全表鎖,讀寫序列問題,併發效率鎖表,效率低,MyISAM對於讀寫密集型應用一般是不會去選用的。

總之:

1.MyISAM型別不支援事務處理等高階處理,而InnoDB型別支援。

2.MyISAM型別的表強調的是效能,其執行速度比InnoDB型別更快,但是不提供事務支援,而InnoDB提供事務支援已經外部鍵等高階資料庫功能。

4、高併發下,如何做到安全的修改同一行資料。

1)、使用悲觀鎖。即是當前只有一個執行緒執行操作,排斥外部請求的修改。

2)、FIFO(First Input First Output,先進先出)快取佇列思路。即是直接將請求放入佇列中,就不會導致某些請求永遠獲取不到鎖。有點強行將多執行緒變成單執行緒的感覺

3)、使用樂觀鎖(推薦)。相對於“悲觀鎖”採用更為寬鬆的加鎖機制,大都是採用帶版本號(Version)更新

更詳細請閱讀: blog.csdn.net/riemann_/ar…

5、樂觀鎖和悲觀鎖是什麼,INNODB的標準行級鎖有哪2種,解釋其含義。

樂觀鎖(Optimistic Concurrency Control,縮寫”OCC”):是一種併發控制的方法。樂觀的認為多使用者併發的事務在處理時不會彼此互相影響,各事務能夠在使用鎖的情況下處理各自的資料。

悲觀鎖(Pessimistic Concurrency Control,縮寫”PCC”):與樂觀鎖相對應的就是悲觀鎖。悲觀鎖就是在操作資料時,認為此操作會出現資料衝突,所以在進行每次操作時都要通過獲取鎖才能進行對相同資料的操作,這點跟 java 中的 synchronized 很相似,所以悲觀鎖需要耗費較多的時間。 它們就是共享鎖與排它鎖。共享鎖和排它鎖是悲觀鎖的不同的實現,它倆都屬於悲觀鎖的範疇。

6、SQL優化的一般步驟是什麼,怎麼看執行計劃,如何理解其中各個欄位的含義。 【1】、通過 show status 命令瞭解各種 sql 的執行頻率。mysql 客戶端連線成功後,通過show [session|global] status 命令可以提供服務狀態資訊,也可以使用 mysqladmin extend-status 命令獲取這些訊息。

通常比較關心的是以下幾個統計引數: 1)、Com_select:執行 select 操作的次數,一次查詢只累加1。 2)、Com_insert:執行 insert 操作的次數,對於批量插入的 insert 操作,只累加一次。 3)、Com_update:執行 update 操作的次數。 4)、Com_delete:執行 delete 操作的次數。

上面這些引數對於所有儲存引擎的表操作都會進行累計。下面這幾個引數只是針對 innodb 的,累加的演演算法也略有不同: 1)、Innodb_rows_read : select 查詢返回的行數。 2)、Innodb_rows_inserted : 執行 insert 操作插入的行數。 3)、Innodb_rows_updated : 執行 update 操作更新的行數。 4)、Innodb_rows_deleted : 執行 delete 操作刪除的行數。

通過以上幾個引數,可以很容易地瞭解當前資料庫的應用是以插入更新為主還是以查詢操作為主,以及各種型別的 sql 大致的執行比例是多少。對於更新操作的計數,是對執行次數的計數,不論提交還是回滾都會進行累加。

對於事務型的應用,通過 Com_commit 和 Com_rollback 可以瞭解事務提交和回滾的情況,對於回滾操作非常頻繁的資料庫,可能意味著應用編寫存在問題。

此外,以下幾個引數便於使用者瞭解資料庫的基本情況: 1)、Connections : 試圖連線 mysql 伺服器的次數 2)、Uptime : 伺服器工作時間 3)、Slow_queries:慢查詢次數

【2】、查詢執行效率較低的 sql 語句:

通過慢查詢日誌定位那些執行效率較低的 sql 語句,用 --log-slow-queries[=file_name] 選項啟動時,mysqld 寫一個包含所有執行時間超過 long_query_time 秒的 sql 語句的日誌檔案。

慢查詢日誌在查詢結束以後才記錄,所以在應用反映執行效率出現問題的時候慢查詢日誌並不能定位問題,可以使用 show processlist 命令檢視當前 mysql 在進行的執行緒,包括執行緒的狀態、是否鎖表等,可以實時的檢視 sql 的執行情況,同時對一些鎖表操作進行優化。

【3】、通過 explain 分析低效 SQL 的執行計劃: 查詢到效率低的 SQL 語句後,可以通過 explain 或者 desc 命令獲取 MySQL 如何執行 select 語句的資訊,包括在 select 語句執行過程中表如何連線和連線的順序。

以下是 explain 語句返回引數:

1)、 id:select 查詢的序列號,包含一組數字,表示查詢中執行 select 子句或操作表的順序。三種情況: ①、id相同:執行順序由上而下 ②、id不同:如果是子查詢,id 序號會遞增,id 越大優先順序越高,越先被執行 ③、id既有相同的也有不同的,兩者同時存在--->id 如果相同,可以認為是一組,由上往下執行;在所有組裡id越大,優先順序越高,越先執行。 2)、select_type:型別主要用於區別普通查詢、聯合查詢、子查詢等的複雜程度。

SIMPLE:簡單的 select 查詢,查詢中不包含子查詢或者UNION。

PRIMARY:查詢中若包含任何複雜的自查詢,最外層查詢為 PRIMARY。

SUBQUERY:在 SELECT 或 WHERE 中包含子查詢。

DERIVED:在 FROM 列表中包含的子查詢被標記為

DERIVED(衍生)MySQL會遞迴執行這些子查詢,把結果放進臨時表。

UNION:若第二個SELECT出現在UNION之後,則被標記為UNION,若UNION包含在FROM子句的子查詢,則外層SELECT將被標記為DERIVED。

UNION RESULT:從UNION表中獲取結果的SELECT。

3)、table:顯示這行資料是關於那張表的。

4)、type:主要型別如下:

從最好到最差:system > const > eq_ref > ref > range > index > ALL,一般達到 rang 級別,最好達到 ref 級別。

5)、possible_keys :顯示可能應用到這張表中的索引,查詢欄位上若存在索引則列出來,但不一定被查詢實際使用。

6)、keys:實際使用的索引。如果未null,則沒有使用索引。若查詢中出現了覆蓋索引(覆蓋索引:查詢的欄位和建立的索引的欄位和個數完全一樣時),則該索引只出現 key。

7)、key_len:表示索引中使用的位元組數,可通過該列查找出使用索引的長度。在不損壞精準性的情況下,長度越短越好。key_len顯示的值為索引欄位的最大可能長度,並非實際長度,即 key_len 是根據表定義實際計算出來的,不是通過表內檢出來的。

8)、ref:顯示索引的那一列被使用,如果可能的話,是一個常數。那些列或常量被用於查詢索引上的值。

9)、rows:根據表統計資訊及索引選用情況,大致估算出找到所需的記錄的行數。

10)、Extra:包含不適合在其他列中顯示,但十分重要的資訊。

7、mysql怎麼解決死鎖。

產生死鎖的四個必要條件:

①、互斥條件:一個資源每次只能被一個程式使用。

②、請求與保持條件:一個程式因請求資源而阻塞時,對已獲得的資源保持不放。

③、不剝奪條件:程式已獲得的資源,在末使用完之前,不能強行剝奪。

④、迴圈等待條件:若干程式之間形成一種頭尾相接的迴圈等待資源關係。

這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發生死鎖。

這裡提供兩個解決資料庫死鎖的方法:

①、重啟資料庫。②、殺掉搶資源的程式

8、Mysql的索引原理,索引的型別有哪些,如何建立合理的索引,索引如何優化。

MySql索引的原理:

1)、通過不斷地縮小想要獲取資料的範圍來篩選出最終想要的結果,同時把隨機的事件變成順序的事件,也就是說,有了這種索引機制,我們可以總用同一種查詢方式來鎖定資料。

2)、索引是通過複雜的演演算法,提高資料查詢效能的手段。從磁碟 io 到記憶體 io 的轉變。

MySql索引的型別:

1)、普通索引 index:加速查詢

2)、唯一索引: ①、主鍵索引:primary key:加速查詢+主鍵唯一約束且不為空。 ②、唯一索引:unique:加速查詢+主鍵唯一約束。

3)、聯合索引:

①、primary key(id,name):聯合主鍵索引。 ②、unique(id,name):聯合唯一索引。 ③、unique(id,name):聯合普通索引。

4)、全文索引 fulltext:用於搜尋很長一篇文章的時候,效果最好。

5)、空間索引 spatial:瞭解就好,幾乎不用。

9、聚集索引和非聚集索引的區別。

“聚簇”:就是索引和記錄緊密在一起。

“非聚簇索引”:索引檔案和資料檔案分開存放,索引檔案的葉子頁只儲存了主鍵值,要定位記錄還要去查詢相應的資料塊。

10、select for update 是什麼含義,會鎖表還是鎖行或是其他。

select for update 語句是我們經常使用手工加鎖語句。藉助 for update 子句,我們可以在應用程式的層面手工實現資料加鎖保護操作。屬於併發行鎖。

11、為什麼要用Btree實現,它是怎麼分裂的,什麼時候分裂,為什麼是平衡的。

為什麼使用B+樹?言簡意賅,就是因為:

1).檔案很大,不可能全部儲存在記憶體中,故要儲存到磁碟上

2).索引的結構組織要儘量減少查詢過程中磁碟I/O的存取次數(為什麼使用B-/+Tree,還跟磁碟存取原理有關。)

3).區域性性原理與磁碟預讀,預讀的長度一般為頁(page)的整倍數,(在許多作業系統中,頁得大小通常為4k)

4).資料庫系統巧妙利用了磁碟預讀原理,將一個節點的大小設為等於一個頁,這樣每個節點只需要一次I/O就可以完全載入,(由於節點中有兩個陣列,所以地址連續)。而紅黑樹這種結構,h明顯要深的多。由於邏輯上很近的節點(父子)物理上可能很遠,無法利用區域性性。

Key 超過1024才分裂,因為隨著資料的增多,一個結點的 key 滿了,為了保持 B 樹的特性,就會產生分裂,就向紅黑樹和 AVL樹為了保持樹的性質需要進行旋轉一樣!

12、資料庫的ACID是什麼。

A(atomic):原子性,要麼都提交,要麼都失敗,不能一部分成功,一部分失敗。

C(consistent):一致性,事務開始及結束後,資料的一致性約束沒有被破壞

I(isolation):隔離性,併發事務間相互不影響,互不幹擾。   D(durabilit):永續性,已經提交的事務對資料庫所做的更新必須永久儲存。即便發生崩潰,也不能被回滾或資料丟失。

13、某個表有近千萬資料,CRUD比較慢,如何優化。

資料千萬級別之多,佔用的儲存空間也比較大,可想而知它不會儲存在一塊連續的物理空間上,而是鏈式儲存在多個碎片的物理空間上。可能對於長字串的比較,就用更多的時間查詢與比較,這就導致用更多的時間。

1)、作為關係型資料庫,是什麼原因出現了這種大表?是否可以做表拆分,減少單表字段數量,優化表結構。

2)、在保證主鍵有效的情況下,檢查主鍵索引的欄位順序,使得查詢語句中條件的欄位順序和主鍵索引的欄位順序保持一致。

3)、在程式邏輯中採用手動事務控制,不要每插入一條資料就自動提交,而是定義一個計數器,進行批量手動提交,能夠有效提高執行速度。

更多分析可閱讀文章: blog.csdn.net/riemann_/ar…

14、Mysql怎麼優化全表掃描(table scan)的。

避免在 where 子句中對欄位進行 is null 判斷。

應儘量避免在 where 子句中使用 != 或 <> 操作符,否則將會導致引擎放棄使用索引而進行全表掃描。

避免在 where 子句中使用 or 來連線條件。

in 和not in 也要慎用。

Like 查詢(非左開頭)。

不要使用 NUM=@num 引數這種。

不要where 子句中對欄位進行表示式操作 num/2=XX。

不要在where子句中對欄位進行函式操作。

15、如何寫sql能夠有效的使用到複合索引。

由於複合索引=組合索引,類似多個木板拼接在一起,如果中間斷了就無法用了,所以要能用到複合索引,首先開頭(第一列)要用上,比如index(a,b) 這種,我們可以select table tname where a=XX 用到第一列索引 如果想用第二列 可以 and b=XX 或者and b like ‘TTT%’。

16、mysql中in 和exists 區別。

mysql 中的 in 語句是把外表和內表作 hash 連線,而 exists 語句是對外表作 loop 迴圈,每次 loop 迴圈再對內表進行查詢。一直大家都認為 exists 比 in 語句的效率要高,這種說法其實是不準確的。這個是要區分環境的。

㊤、如果查詢的兩個表大小相當,那麼用 in 和 exists 差別不大。

㊥、如果兩個表中一個較小,一個是大表,則子查詢表大的用 exists,子查詢表小的用 in。

㊦、not in 和 not exists 如果查詢語句使用了not in 那麼內外表都進行全表掃描,沒有用到索引;而 not extsts 的子查詢依然能用到表上的索引。所以無論那個表大,用 not exists 都比 not in 要快。

EXISTS 只返回 TRUE 或 FALSE,不會返回 UNKNOWN IN 當遇到包含NULL的情況,那麼就會返回 UNKNOWN

17、資料庫自增主鍵可能的問題。

【1】、使用自增主鍵對資料庫做分庫分表,可能出現一些諸如主鍵重複等的問題。 【2】、資料庫匯入的時候,可能會因為主鍵出現一些問題。

可參考文章:yq.aliyun.com/articles/38…

18、你做過的專案裡遇到分庫分表了嗎,怎麼做的,有用到中介軟體麼,比如sharding jdbc等,它們的原理知道麼。

參考文章: www.cnblogs.com/butterfly10…

19、MYSQL的主從延遲怎麼解決。

實際上主從同步延遲根本沒有什麼一招制敵的辦法,因為所有的 SQL 必須都要在從伺服器裡面執行一遍,但是主伺服器如果不斷的有更新操作源源不斷的寫入, 那麼一旦有延遲產生,那麼延遲加重的可能性就會越來越大。 當然我們可以做一些緩解的措施。

a)、最簡單的減少 slave 同步延時的方案就是在架構上做優化,儘量讓主庫的 DDL 快速執行。還有就是主庫是寫,對資料安全性較高,比如 sync_binlog=1,innodb_flush_log_at_trx_commit = 1 之類的設定,而 slave 則不需要這麼高的資料安全,完全可以將 sync_binlog 設定為 0 或者關閉 binlog,innodb_flushlog 也可以設定為 0 來提高 sql 的執行效率。另外就是使用比主庫更好的硬體裝置作為 slave。

b)、把一臺從伺服器當作備份使用, 而不提供查詢, 這樣他的負載就下來了, 執行 relay log 裡面的 SQL 效率自然就高了。

c)、增加從伺服器,這個目的還是分散讀的壓力, 從而降低伺服器負載。

更多優秀文章:

www.cnblogs.com/wenxiaofei/…

blog.csdn.net/zhengzhaoya…

studygolang.com/articles/14…