java【mysql】面試題


一、為什么互聯網公司一般選擇mysql而不是Oracle?

  免費、流行、夠用。

二、數據庫的三范式是什么?什么是反模式?

  數據庫范式是為解決關系數據庫中數據冗余、更新異常、插入異常、刪除異常問題而引入的。簡單的理解,數據庫范式可以避免數據冗余,減少數據庫的空間,並且減輕維護數據完整性的麻煩。

  第一范式:

  強調的是數據庫中每個表中的屬性,具有原子性,不再進行分解。

  比如:如果涉及到設計一張活動表,這個表中,包含了屬性(活動id,活動名稱,活動地址等屬性)其中,活動名稱符合原子性,但是活動地址還可以進行分割成活動國家,活動省,活動地區,活動市等等。活動地址這個屬性就不滿足第一范式。

  第二范式:

  強調的是數據庫中的數據必須有唯一主鍵,並且這個表中的非主鍵字段,都必須完全依賴主鍵。不能存在部分依賴。

  比如說:版本表(有四個字段:版本編碼,版本名稱,產品編碼,產品名稱),其中主鍵是(版本編碼、產品編碼),那么這個場景中,數據庫設計並不符合第二范式,因為產品名稱依賴於產品編碼。存在部分依賴,所以,為了使其滿足第二范式,可以改造成兩個表()產品表和編碼表。

  第三范式:

  強調屬性冗余性的約束,即非主鍵列必須直接依賴於主鍵。

  比如:訂單表:(訂單編碼、顧客編碼、顧客名稱),其中主鍵是(訂單編碼、顧客編碼、顧客名稱),其中主鍵是(訂單編號),這個場景中,顧客編碼、顧客名稱都完全依賴於主鍵,因此符合第二范式,但是顧客名稱依賴於顧客比那嗎,從而間接依賴於主鍵,所以不滿足第三范式,可以拆分成兩個表:訂單表(訂單編碼、顧客編碼)和顧客表(顧客編碼、顧客名稱),拆分后的數據庫設計,就可以完全滿足第三范式的要求了。

注意事項:第二范式的側重點是非主鍵列是否完全依賴於主鍵,還是依賴於主鍵的一部分。第三范式的側重點是非主鍵列是直接依賴於主鍵,還是直接依賴於非主鍵列。

  反模式:

  雖然范式可以避免數據冗余,減少數據庫的空間,減輕維護數據的完整性的麻煩。

  然而,通過數據庫范式化設計,將導致數據庫業務涉及的表變多,並且可能需要將涉及的業務表進行多表連接查詢,這樣將導致性能變差,且不利於分庫分表。因此,處於性能有限的考量,可能在數據庫的結構中需要使用反模式的設計,即空間獲取時間,采取數據冗余的方式避免表之間的關聯查詢。至於數據一致性問題,因為難以滿足數據強一致性,一般情況下,使存儲數據盡可能達到用戶一致,保證系統經過一段較短的時間的自我恢復和修正,數據最終達到一致。

  需要謹慎使用反模式設計數據庫。一般情況下,盡可能使用范式化的數據庫設計。因為范式化的數據設計能讓產品更加靈活,並且能在數據庫層保持數據完整性。

  有的時候,提升性能最好的方法是在同一張表中保持冗余數據,如果能容許少量的臟數據,創建一張完全獨立的匯總表或者緩存表是非常好的方法。舉個例子,設計一張“下載次數表“來緩存下載次數信息,可使在海量數據的情況下,提高查詢總數信息的速度。

  另外一個比較典型的場景,處於拓展性考慮,可能會使用BLOB和TEXT類型的列存儲JSON結構的數據,這樣的好處在於可以在任何時候,將新的屬性添加到這個字段中。而不需要更改表的結構,但是,這個設計的缺點也比較明顯,就是需要獲取整個字段內容進行解碼來獲取指定的屬性,並且無法使用所以、排序、聚和等操作。因此,需要考慮更加復雜的使用場景,更加建議使用MongoDB這樣的文檔型數據庫。

三、MySql的數據類型有那些?

  數值、日期/時間和字符串類型。

MySql中varchar與char的區別?varchar(50)中的50代表什么含義?

  1.Varchar與char的區別,char是一種固定長度的類型,varchar則是一種可變長度的類型。

  2.varchar(50)中50的涵義最多可以存放50個字符,varchar(50)和varchar(200)存儲hello所占的空間一樣,但是后者在排序時會消耗更多的內存。因為order By clo采用的fixed_length計算col長度(memory引擎也是一樣。)

所以,實際場景下,選擇合適的varchar長度還是必要的。

int(11)中的11代表了什么含義?

int(11)中的11,不影響字段存儲范圍,只是影響展示效果。

金額(金錢)相關的數據,選擇什么數據類型?

  • 方式一、使用int或者bigint類型,如果需要存儲到分的維度,需要*100進行放大。
  • 方式二、使用decimal類型,避免精度丟失。如果使用java語言時,需要使用bigDecimal進行對應

四、一張表,里面有ID自增主鍵,當insert17條數據之后,刪除了第15,16,17條數據,再把MySql重啟,再insert一條,這條記錄的id是多少?

  • 一般情況下,我們創建的表的類型是innoDB,如果新增一條記錄(不重啟Mysql情況下)這時的ID是18,但是如果重新啟動的話,這條記錄就是15,因為InnooDB表只把自增主鍵的最大值記錄到內存中,所以重啟數據庫或者對表OPTIMIZE操作,都會使最大ID丟失。
  • 但是如果我們使用的表的類型是MYISAM,那么這條記錄的ID就是18,因為MYISAM表會把自增主鍵的最大ID記錄到數據文件里面,重啟MYISAM后,自增主鍵的最大ID也不會丟失。

五、表中有大字段X(例如:text類型),且字段X不會經常更新,以讀為主,請問您是選擇拆成子表,還是繼續放在一起?寫出您的理由。

  • 拆帶來的問題:連接消耗+存儲拆分空間。
如果能容忍拆分帶來的空間問題,拆的話,最好和經常要查詢的表的主鍵再物理結構上放置在一起(分區)順序IO,減少連接消耗,最后這是一個文本列再加上一個全文索引來盡量抵消連接消耗。
  • 不拆可能帶來的問題:查詢性能
如果能容忍不拆分帶來的查詢性能損失的話,上面的方案再某個極致條件下可能會出現問題,那么不拆就是最好的選擇。

實際場景下,例如說商品表數據量比較大的情況下,會將商品描述單獨存儲到一個表中。即使用拆的方案。

六、MYSQL常用的存儲引擎有哪些?

  • InnoDB
  • MyISAM
  • MRG_MYISAM
  • MEMORY
  • CSV
  • ARCHIVE
  • BLACKHOLE
  • PERFORMEANCE_SCHEMA
  • FEDERATED
  • 。。。

如何選擇合適的存儲引擎?

  提供幾個選擇的標准,然后按照標准來進行選擇合適的存儲引擎,也可以根據常用引擎對比,來選擇你使用的存儲引擎,使用哪種引擎需要根據需求靈活選擇,一個數據庫中多個表可以使用不同的引擎滿足各種性能與實際需求。使用合適的存儲引擎,將會提高整個數據庫的性能。

  • 1.是否需要支持事務。
  • 2.對索引和緩存的支持。
  • 3.是否需要使用熱備
  • 4.崩潰恢復,能否接受崩潰
  • 5.存儲的限制。
  • 6.是否需要外鍵支持。

  目前,MySQL默認的存儲引擎是InnoDB,並且也是最主流的選擇。主要原因是:

  • 1.支持事務
  • 2.支持行級鎖和表級鎖,能支持更多的並發量。
  • 3.查詢不加鎖,完全不影響性能。
  • 4.支持崩潰后恢復。

在Mysql5.1以及之前的版本,默認的存儲引擎是MYISAM,但是目前已經不再更新,且它有幾個比較關鍵的缺點:

  • 不支持事務
  • 使用表級鎖,如果數據量大,一個插入操作鎖定表后,其他請求都將阻塞。

 

 

 

Innodb的四大特性?

  • 插入緩存,
  • 二次寫
  • 自適應哈希索引
  • 預讀

六、為什么select count(*) from table 在InnoDB比MyISAM慢?

對於 SELECT COUNT(*) FROM table 語句,在沒有 WHERE 條件的情況下,InnoDB 比 MyISAM 可能會慢很多,尤其在大表的情況下。因為,InnoDB 是去實時統計結果,會全表掃描;而 MyISAM 內部維持了一個計數器,預存了結果,所以直接返回即可。
 
各種不同 MySQL 版本的 Innodb 的改進?
MySQL5.6 下 Innodb 引擎的主要改進:
  • 1. online DDL
  • 2. memcached NoSQL 接口
  • 3. transportable tablespace( alter table discard/import tablespace) 
  • 4. MySQL 正常關閉時,可以 dump 出 buffffer pool 的( space, page_no),重啟時 reload,加快預熱速度
  • 5. 索引和表的統計信息持久化到 mysql.innodb_table_stats 和 mysql.innodb_index_stats,可提供穩定的執行計划
  • 6. Compressed row format 支持壓縮表
MySQL5.7 下 Innodb 引擎的主要改進:
  • 1、修改 varchar 字段長度有時可以使用
  • 2、Buffffer pool 支持在線改變大小
  • 3、Buffffer pool 支持導出部分比例
  • 4、支持新建 innodb tablespace,並可以在其中創建多張表
  • 5、磁盤臨時表采用 innodb 存儲,並且存儲在 innodb temp tablespace 里面,以前是 MyISAM 存儲
  • 6、透明表空間壓縮功能

七、什么是索引?

  MySQL中存儲引擎使用類似的方式進行查詢,先去索引中查詢對應的值,然后根據匹配的索引找到對應的數據行。

索引有什么好處?

  • 1.提高數據的檢索速度,降低數據庫IO成本:使用索引的意義就是通過縮小表中需要查詢的記錄的數目從而加快搜索的速度。
  • 2.降低數據排序的成本,降低CPU消耗:索引之所以查的快,是因為先將數據排好序,若該字段正好需要排序,則正好降低了排序的成本。

索引有什么壞處?

  • 1.占用存儲空間:索引實際上也是一張表,記錄了主鍵和索引字段,一般以索引文件的形式存儲在磁盤上。
  • 2.降低更新表的速度:表的數據發生了變化,對應的索引也需要一起變更,從而減低的更新速度,否則索引指向的物理數據可能不對,這也是索引失效的原因之一。

索引的使用場景?

  • 對非常小的表,大部分情況下全表掃描效率更高。
  • 對中大型表,索引非常有效。
  • 特大型的表,建立和使用索引的代價隨着增長,可以使用分區技術來解決。

索引的類型?

索引,都是實現在存儲引擎層的。主要有六種類型:

  • 1、普通索引:最基本的索引,沒有任何約束
  • 2、唯一索引:與普通索引類似,但具有唯一性約束。
  • 3、主鍵索引:特殊的唯一索引,不允許有空值。
  • 4、復合索引:將多個列組合在一起創建索引,可以覆蓋多個列
  • 5、外鍵索引:只有InnoDB類型的表才可以使用外鍵索引,保證數據的一致性,完整性和實現級聯操作。
  • 6、全文索引:MySQL自帶的全文索引只能用於InnoDB、MyISAM,並且只能對引文進行全文檢索,一般使用全文索引引擎。

Mysql索引的“創建”原則?

  • 1、最適合的索引的列是出現在where子句中的列,或者連接子句中的列。而不是出現在Select關鍵字后的列。
  • 2、索引列的基數越大,索引效果越好。
  • 3、根據情況創建復合索引,復合索引可以提高查詢效率。
  • 4、避免創建過多的索引,索引會額外占用磁盤空間,降低寫操作效率。
  • 5、主鍵盡可能選擇較短的數據類型,可以有效減少索引的磁盤占用提高查詢效率。
  • 6、對字符串進行索引,應該定制一個前綴長度,可以節省大量的索引空間。

MySQL索引的“使用”注意事項?

  • 1.應盡量避免在where子句中使用!=或者<>操作符,否則將引擎放棄使用索引而進行全表掃描。優化器將無法通過索引來確定將要命中的行數,因此需要搜索該表的所有行。
  • 2.應盡量避免在where子句中使用or連接,否則將導致引擎放棄使用索引而進行全表掃描,如: SELECT id FROM t WHERE num = 10 OR num = 20 。
  • 3.應盡量避免在where子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。
  • 4.應盡量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。
  • 5.不要在where子句中的==左邊進行函數、算數運算或者其他表達式運算,否則系統將可能無法正確使用索引。
  • 6.復合索引怎訊前綴原則。
  • 7.如果mysql評估使用索引比全表掃描更慢,會放棄使用索引。如果此時想要索引,可以在語句中添加強制索引。
  • 8.列類型是字符串類型,查詢時一定要給值加引號,否則索引將失效。
  • 9.like查詢,%不能在前,因為無法使用索引,如果需要模糊匹配,可以使用全文索引。

以下三條SQL如何創建索引,只建一條怎么建?

WHERE a = 1 AND b = 1 
WHERE b = 1
WHERE b = 1 ORDER BY time DESC
  • 以順序 b , a, time 建立復合索引, CREATE INDEX table1_b_a_time ON index_test01(b, a, time) 。
  • 對於第一條 SQL ,因為最新 MySQL 版本會優化 WHERE 子句后面的列順序,以匹配復合索引順序。

想知道一個查詢用到了那個索引,如何查看?

  EXPLAIN顯示了MYSQL如何使用索引來處理SELECT語句以及連接表,可以幫助選擇更好的索引和寫出更優化的查詢語句。

  使用方法,在SELECT語句前加上EXPLAIN就可以了。

MYSQL索引的原理?

-----

  MySQl有那些索引?

  B-Tree索引

  Hash索引

什么是B-Tree索引?

  B-Tree是為磁盤等外存儲設備設計的一種平衡查找樹,因此在講B-Tree之前先了解一卡磁盤的相關知識。

  • 系統從磁盤讀取數據到內存時以磁盤塊(block)為基本單位的,位於同一個磁盤塊中的數據會被一次性讀取出來,而不是需要什么取什么。
  • InnoDB存儲引擎中有頁(Page)的概念,頁是其磁盤管理的最小單位。Innodb存儲引擎中默認每個頁的大小為16kb,可通過參數innodb_page_size將頁的大小設置為4K、8K、16K,在Mysql中可通過如下命令查看頁的大小:
Mysql> show variables list 'innodb_page_size'
  • 而系統一個磁盤塊的存儲空間往往沒有那么大,因此innodb每次申請磁盤空間時都會是若干個地址連續磁盤塊來達到頁的大小16kb。Innodb在把磁盤數據讀入到磁盤時會以頁為基本單位,在查詢數據時如果一個頁中的每條數據都能有助於定位數據記錄的位置,這將會減少磁盤IO次數,提高查詢效率。

  B-Tree結構的數據可以讓系統高效的找到數據所在的磁盤塊,為了描述B-Tree,首先定一條記錄為一個二元組【key,data】,key為記錄的鍵值,對應表中的主鍵值,data為一行記錄中除主鍵外的數據。對於不同的記錄,key值互不相同。

  一棵m階的B-Tree有如下特性:

  • 1.每個節點最多有m個孩子。
    • 除了根節點和葉子節點外,其他每個節點至少有ceil(m/2)個孩子。
    • 若根節點不是葉子節點,則至少有2個孩子。
  • 2.所有葉子節點都在同一層,且不包含其他關鍵字信息。
  • 3.每個非葉子節點包含n個關鍵字信息(p0,p1,p2,pn)

B-Tree中的每個節點根據實際情況可以包含大量的關鍵字信息和分支,如下圖所示為一個3階的B-Tree:

 

 

  • 每個節點占用一個盤塊的磁盤空間,一個節點上有兩個升序排序的key和三個指向子樹根節點的point,point存儲的是子節點所在拍磁盤塊的地址,兩個key划分成的三個范圍域,對應三個point指向的子樹的數據的范圍域。
  • 以根節點為例。key為17和35,P1指針指向的子樹的范圍小雨17,P2指針指向的子樹的數據范圍為【17-35】,P3指針指向的子樹的數據范圍大於35.

模擬查找key為29的過程:

  • 1.根據根節點找到磁盤塊1,讀入內存,【磁盤的I/O次數為1】
  • 2.比較key29在區間(17,35),找到磁盤塊1的指針P2
  • 3.根據P2指針找到磁盤塊3,讀入內存。【磁盤I/O操作第二次】
  • 4.比較key29在區間(26,30),找到磁盤塊3的指針P2
  • 5.根據P2指針找到磁盤塊8,讀入內存,【磁盤I/O次數第三次】
  • 6.在磁盤塊8中的key列表中找到key29。

分析上面過程,發現需要3次磁盤i/o操作,和3次內存查找操作。由於內存中的key是一個有序表結構,可以二分法查找提高效率。而3次磁盤i/o操作是影響整個B-Tree查找效率的決定因素。B-Tree相對於AVLTree縮減了節點個數,使每次磁盤I/O取到內存的數據都發揮了做用,從而提高了查詢效率。

什么是B+Tree索引?

   B+Tree是在B-Tree基礎上的一種優化,使其更適合實現外存儲索引結構,InnoDB存儲引擎就是用B+Tree實現其索引結構。

  從上一節的B-Tree結構圖中可以看到,每個節點中不僅包含數據的key值,還有data值,而每一個頁的存儲空間都是有限的。如果data數據較大時將會導致每個節點(即每一個頁)能存儲的key的數量很小,當存儲的數據量和大時,同樣會導致B—Tree的深度較大,增大查詢時的磁盤I/O次數,進而影響查詢效率。在B+Tree中,所有數據記錄節點都是按照鍵值大小順序存放在同一層的頁子節點上,而非頁子節點上只存儲key值信息,這樣可以大大加大每個節點存儲的key值數量,降低B+Tree的高度。

B+Tree相對於B-Tree有幾點不同:

  • 非葉子節點只存儲鍵值信息
  • 所有葉子節點之間都有一個鏈指針
  • 數據記錄都存放在葉子節點中。

  將上一節中的B-Tree優化,由於B+Tree的非葉子節點只存儲鍵值信息,假設每一個磁盤塊都能存儲4個鍵值及指針信息,則變成B+Tree后其結構如下圖所示:

 

 

 

  • 通常在B+Tree上有兩個頭指針,一個指向根節點,另一個指向關鍵字最小的葉子節點,而且所有葉子節點(即數據節點)之間是一種鏈式環結構。因此可以對B+Tree進行兩種查找運算:一種是對於主鍵的范圍查找和分頁查找,另一種就是從根節點開始,進行隨機查找。

可能上面例子中只有22條數據記錄,看不出B+Tree的優點,下面做一個推算:

  • Innodb存儲引擎中頁的大小為16kb,一般表的主鍵類型為Int(占用4個字節)或者BIGINT(占用8個字節),指針類型也一般為4個字節或者8個字節,也就是說每一個頁(B+Tree中的一個節點)中國大概存儲16kb/(8B+8B)=1k個鍵值(因為時估值,為方便計算,這里的k取值為1000個)也就是說一個深度為3的B+Tree索引可以維護1000*1000*1000=10億條記錄。
  • 實際情況中每一個節點可能不能填充滿,因此在數據庫中,B+Tree的高度一般都在2-4層,MySql的Innodb存儲引擎子設計時是將根節點常駐內存的,也就是說查找一個鍵值的行記錄時,最多需要1-3次磁盤I/操作。

B-Tree有哪些索引類型?

  在B+Tree中,根據葉子節點的內容,索引類型分為主鍵索引和非主鍵索引。

  • 主鍵索引的葉子節點存的數據是整行數據(即具體數據)。在InnoDB里,非主鍵索引也被稱為聚集索引。
  • 非主鍵索引的葉子節點存的數據是整行數據的主鍵,鍵值是索引。在InnoDB里,非主鍵索引也被稱為輔助索引。

  輔助索引與聚集索引的區別在於輔助索引的葉子節點並不包含行記錄的全部數據,而是存儲相應行數據的聚集索引鍵,即主鍵。當通過輔助索引來查詢數據時,需要進行兩步:

  • 首先,InnoDB存儲引擎會遍歷輔助索引找到主鍵。
  • 然后,再通過主鍵在聚集索引中找到完整的行記錄數據。

另外,InnoDB通過主鍵聚簇數據,如果沒有定義主鍵,會選擇唯一的非空索引代替,如果沒有這樣的索引,會隱式定義一個主鍵作為聚簇索引。

輔助索引如果是相同的索引怎么進行存儲?因為最終存儲到B+Tree非子節點中時,他們對應的主鍵ID是不同的。所以妥妥的。

 

 

聚簇索引的注意點有哪些?

聚簇索引表最大限度提高了I/O密集型應用的性能,但它也有一下幾個限制:

  • 1.插入速度嚴重依賴插入順序,按照主鍵的順序插入是最快的方式,否則將會出現頁裂,嚴重影響性能。因此,對於InnoDB表,我們一般都會定義一個自增的ID列為主鍵。
  • 2.更新主鍵的代價很高,因為將會導致被更新的行移動。因此,對於InnoDB表,我們一般定義主鍵為不可更新。
  • 3.二級索引訪問需要兩次索引查找,第一次找到主鍵值,第二次根據主鍵值找到行數據。
  • 4.主鍵ID建議使用整型,因為,每個主鍵索引的B+Tree節點的鍵值可以存儲更多主鍵ID,每個非主鍵索引的B+Tree節點的數據可以存儲更多主鍵ID。

什么是索引的最左匹配特性?

  當B+Tree的數據項是復合的數據結構,比如索引(name,age,sex)的時候,B+Tree是按照從左到右的順序來建立搜索樹的。

  • 比如當(張三,20,F)這樣的數據來檢索的時候,B+Tree會優先比較name來確定下一步的搜索方向,如果name相同再依次比較age和sex,最后得倒檢索的數據。
  • 但當(20,F)這樣的沒有name的數據來的時候,B+Tree就不知道下一步該查那個節點,因為建立搜索樹的時候name就是第一個比較因子,必須要先根據name來搜索才能知道下一步去哪里查詢。
  • 比如當(張三,F)這樣的數據來檢索時,B+Tree可以用name來指定搜索方向,但下一個字段age的缺失,所以只能把名字等於張三的數據都找到,然后再匹配性別是F的數據了。
  • 這個是非常重要的性質,即索引的最左匹配特性。

MyISAM索引實現?

  MyISAM索引的實現,和InnoDB索引的實現是一樣使用B+Tree,差別在於MyISAM索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址。

1)主鍵索引:

  MYISAM引擎使用B+Tree作為索引結構,葉節點的data域存放的數據記錄的地址。下圖MyISAM主鍵索引的原理圖:

 

 

 

  • 這里設表一共有三列,假設我們以Col1為主鍵,上圖是一個MYISAM表的主鍵索引(Primary Key)示意。可以看出MYISAM的索引文件僅僅保存數據記錄的地址。

2)輔助索引:

  在MyISAM中,主索引和輔助索引在結構上沒有任何區別,只是主索引要求key是唯一的,而輔助索引的key可以重復。如果我們在Col2上建立一個輔助索引,則此索引的結構如下圖所示:

 

 

 

  • 同樣是一顆B+Tree,data域保存數據記錄的地址,因此,MyISAM中檢索的算法為首先按照B+Tree搜索算法搜索索引,如果指定的key存在,則取出其data域的值為地址,讀取相應的數據記錄。

MyISAM的索引方式也叫做非聚集的,只索引這么稱呼是為了InnoDB的聚集索引區分。

MyISAM索引與InnoDB索引的區別?

  • InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引。
  • InnoDB的主鍵索引的葉子節點存儲着行數據,因此主鍵索引非常高效。
  • InnoDB的主鍵索引的葉子節點存儲着行數據地址,需要再尋找一個才能得到數據。
  • InnoDB非主鍵索引的葉子節點存儲的是主鍵和其他帶索引的列數據,因此查詢時做到覆蓋索引會非常高效。

請說說Mysql的四種事務隔離級別?

  事務就是對一系列的數據庫操作(比如插入多條數據)進行統一的提交或者回滾操作,如果插入成功,那么一起成功,如果中間有一條出現異常,那么回滾之前的所有操作。

  這樣可以防止出現臟數據,防止數據庫數據出現問題。

事務的特性指的是?

指的時ACID,如下圖所示:

 

 

  • 1.原子性:Atomicity,一個事務(transaction)中的所有操作,或者全部完成,或者全部步完成,不會結束再中間某個環節。事務在執行過程中發生錯誤,會被回復(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣,即,事務不可分割,不可約簡。
  • 一致性Consistency:在事務開始之前和事務結束之后,數據庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設約束、觸發器、級聯回滾等。
  • 隔離性Isolation:數據庫允許多個兵法事務同時對數據進行讀寫和修改能力,隔離性可以防止多個事務並發之行時由於交叉之行而導致數據的不一致。事務隔離分為不同級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重復讀(repeatable read)和串行化(Sericlizable)
  • 持久性Durablity:事務處理結束后,對數據的修改就是永久的,即便系統故障也不會丟失。

事務的並發問題?

實際場景下,事務並不是串行的,所以會帶來如下三個問題:

  • 臟讀:事務A讀取了事務B更新的數據,然后B回滾操作,那么A讀取到的數據就是臟數據。
  • 不可重復讀:事務A多次讀取同一數據,事務B在事務A多次讀取的過程中,對數據做了更新並提交,導致事務A多次讀取同一數據時,結果不一致。
  • 幻讀:系統管理員A將數據庫中所有學生的成績從具體分數改為ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束后發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫做幻讀。

不可重復讀的和幻讀很容易混淆,不可重復讀側重於修改,幻讀側重於新增和刪除。解決不可重復讀的問題只需要鎖住滿足條件的行,解決幻讀需要鎖表。

Mysql事務隔離級別會產生的並發問題?

事務定義了四種事務隔離級別,不同數據庫在實現時,產生的並發問題時不同的。

  不同的隔離級別有不同的現象,並有不同的鎖定/並發機制,隔離級別越高,數據庫的並發性能就越差。

  • READ UNCOMMITTED(未提交讀):事務中的修改,即使沒有提交,對其他事務也都是可見的。(會導致臟讀)
  • READ COMMITTED(提交讀):事務從開始直到提交之前,所做的任何修改對其他事務都是不可見的。(會導致不可重復讀)。
  • REPEATABLE READ(可重復讀):一個事務按相同的查詢條件讀取以前檢索過的數據,其他事務插入了滿足其查詢條件的新數據,產生換行(會導致幻讀)
  • SERIALIZABLE(可串行化):強制事務串行化之行。
MySQL InnoDB 采用 MVCC 來支持高並發,實現結果如下表所示:

  • MySQL默認的事務隔離級別為可重復讀(repeatable-read)
  • 有些資料說可重復讀解決了幻讀,實際是存在的,可以通過 SELECT xxx FROM t WHERE id = ? FOR UPDATE 的方式,獲得到悲觀鎖,禁止其它事務操作對應的數據,從而解決幻讀問題。

請說說MySQL的鎖機制?

表鎖時日常開發中的常見問題,當多個查詢同一時刻進行數據修改時,就會產生並發控制的問題。MySQL的共享鎖和排他鎖,就是讀鎖和寫鎖。

  • 共享鎖:不堵塞,多個用戶可以同時讀一個資源,互不干擾。
  • 排他鎖:一個寫鎖會阻塞其他的讀鎖和寫鎖,這樣可以只允許一個用戶進行寫入,防止其他用戶讀取正在寫入的資源。

鎖的粒度?

  • 表鎖:系統開銷最小,會鎖定整個表,MyISAM使用表鎖。
  • 行鎖:最大程度的支持並發處理,但是也帶來了最大的鎖開銷,InnoDB使用行鎖。

什么是悲觀鎖?什么是樂觀鎖?

1)悲觀鎖

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

在悲觀鎖的情況下,為了保證事務的隔離性,就需要一致性鎖定讀,讀取數據時給加鎖,其他事務無法修改這些數據。修改刪除數據時也要加鎖,其他事務無法讀取這些數據。

2)樂觀鎖

  相對於悲觀鎖而言,樂觀鎖機制才去了更加寬松的加鎖機制。悲觀鎖大多數情況下依靠數據庫的鎖機制實現,以保證操作最大程度上的獨占性,但隨之而來的就是數據庫性能的大量開銷,特別是對長事務而言,這樣的開銷往往無法承受。

  而樂觀鎖在一定程度上解決了這個問題,樂觀鎖,大多是基於數據版本(Version)記錄機制實現的,

何謂數據版本?

即為數據庫表的版本解決方案中,一般是通過為數據庫表增加一個“version”字段來實現。讀取出數據時,將此版本號一同讀出,之后更新時,對此版本號加一,此時,將提交數據的版本數據與數據庫表對應記錄的當前版本信息進行比對,如果提交的數據版本號大於數據庫表當前版本號,則予以更新,否則認為是過期數據。

什么是死鎖?

  多數情況下,可以認為如果一個資源被鎖定,它總會在以后某個時間被釋放。而死鎖發生在多個進程訪問同一數據庫時,其中每個進程都無法繼續下去,簡單的說,進程A等待進程B釋放了它的資源,B又等待A釋放它的資源,這就形成了互相等待,形成了死鎖。

雖然進程在運行時,可能發生死鎖,但是死鎖的發生也必須具備一定的條件,死鎖的發生必須具備以下四個必要條件:

  • 互斥條件:指進程對所分配到的資源進行排他性使用,即在一段時間內資源只由一個進程占用,如果此時還有其他進程請求資源,則請求者只能等待,直至占有資源的進程用完釋放。
  • 請求和保持條件:指進程已經保持了至少一個資源,但又提出了新的資源請求,而該資源已被其他進程占有,此時請求進程阻塞,但又對自己已獲得的其他資源保持不放。
  • 不剝奪條件:指進程已獲得的資源,在未使用完之前,不能被剝奪,只能在使用完時由自己釋放。
  • 環路等待條件:指在發生死鎖時,必然存在一個進程-資源的環形臉,即進程集合(p0,p1,p2,p3....pn)中p0正在等待一個p1占用的資源,p1正在等待p2占用的資源,...pn正在等待已被p0占用的資源。

下列方法有助於最大限度地降低死鎖:

  • 設置獲取鎖的超時時間。(通過超時時間,至少保證最差最差的情況下,有個口子可以退出去)
  • 按同一順序訪問對象
  • 避免事務中的用戶交互
  • 保持事務間斷並在同一批處理中。
  • 使用低隔離級別
  • 使用綁定連接

Mysql中InnoDB引擎的行鎖時通過加在什么上完成(或實現的)?為什么時這樣子的?

InnoDB時基於索引來完成行鎖的,例如Select * from table_with_index where id =1 for update.

for update可以根據條件來完成行鎖鎖定,並且id是有索引鍵的列,如果id不是索引鍵那么Innodb將完成表鎖,並發將無從談起。

關於熟悉MySQL的鎖機制?

  • gap鎖
  • next-key鎖

Innodb的行鎖的怎么實現的?

InnoDB的鎖策略為next-key鎖,即record lock+gap lock,時通過在index上加lock實現的。

  • 如果index 為unique index,則降級為record lock行鎖
  • 如果時普通index,則為next-key lock
  • 如果沒有index,則直接鎖住全表,即表鎖。

MyISAM的表鎖時怎么實現的?

MyISAM直接使用表鎖。

MySQL查詢之行順序?

SELECT
DISTINCT
FROM
JOIN
ON
WHERE
GROUP BY
HAVING
ORDER BY
LIMIT

什么是MVCC?

多版本並發控制(MVCC),是一種用來解決讀-寫沖突的無鎖並發控制,也就是為事務分配單向增長的時間戳,為每一個修改保存一個版本,版本與事務時間戳相關聯,讀操作只讀事務開始前的數據庫的快照。這樣在讀操作不用阻塞寫操作,寫操作不用阻塞讀操作的同時,避免了臟讀和不可重復讀。

MySQL數據庫CPU飆升到500%的話,怎么處理?

  當CPU飆升到500%的話,先用操作系統命令top命令觀察是不是mysqlId占用導致的,如果不是,找出占用高的進程,並進行相關的處理。

如果此時是IO壓力比較大的話,可以使用iostat命令,定位是那個進程占用了磁盤io

如果是mysqld造成的,使用show processlist命令,看着里面跑的Session情況,是不是又消耗資源的SQL在運行,找出消耗高的SQL,看着之行計划是否准確,index是否缺失,或者是數據量太大造成的,一般來說,肯定要kill掉線程,同時觀察cpu使用率是否下降,等進行相應的調整,(比方說加索引,改sql,改內存參數等)之后,再重新跑這些sql。

也可以查看MySQL慢查詢日志,看是否有慢SQL

  也有可能是每個SQL消息資源並不多,但是突然間有大量的Session連接進來並導致CPU飆升,這種情況就需要根應用一起來分析為何連接數會激增,再做出相應的調整,比如說限制連接數

在Mysql服務器運行緩慢的情況下輸入什么命令能緩解服務器壓力?

1)檢查系統的狀態

  通常操作系統的一些工具檢查系統的狀態,比如CPU,內存,磁盤的利用率,根據經驗或者系統正常時的狀態相比懟,有時系統表面上看起來空閑,這也可能不是一個正常狀態,因為CPU可能正等待IO的完成,除此之外,還應該注意哪些占用系統資源(CPU、內存)的進程。

  • 使用sar來檢查操作系統是否存在IO問題
  • 使用cmstat監控內存cpu資源。
  • 磁盤io問題,處理方式:做raid10提高性能。
  • 網絡問題,telnet 一下mysql對外開放的端口,如果不通的話,看着防火牆是否正確設置了。另外,看着MySQL是不是開啟了skip-networking的選項,如果開啟請關閉。

2)檢查Mysql參數

  • max_connect_errors
  • connect_timeout
  • skip-name-resolve
     
  • slave-net-timeout=seconds
     
  • master-connect-retry

3)檢查MySQL相關狀態值

  • 關注連接數
  • 關注下系統鎖情況
  • 關注慢查詢(slow query)日志

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM