2020字節跳動數據庫面試題及答案(1)


第二部分NoSQL部分已發布:2020字節跳動數據庫面試題及答案(二)—— NoSQL部分

題目列表

  • 數據庫三范式
  • 分別說一下范式和反范式的優缺點
  • Mysql 數據庫索引。B+ 樹和 B 樹的區別
  • 為什么 B+ 樹比 B 樹更適合應用於數據庫索引,除了數據庫索引,還有什么地方用到了(操作系統的文件索引)
  • 聚簇索引和非聚簇索引
  • 前綴索引和覆蓋索引
  • 介紹一下數據庫的事務
  • Mysql 有哪些隔離級別
  • Mysql 什么情況會造成臟讀、不可重復度、幻讀?如何解決
  • Mysql 在可重復讀的隔離級別下會不會有幻讀的情況,為什么?
  • Mysql 事務是如何實現的
  • Binlog 和 Redo log 的區別是什么,分別是什么用?
  • 談一談 MVCC 多版本並發控制
  • Innodb 和 MyISAM 的區別是什么
  • Innodb 的默認加鎖方式是什么,是怎么實現的
  • 如何高效處理大庫 DDL
  • Mysql 索引重建
  • 對於多列索引,哪些情況下能用到索引,哪些情況用不到索引
  • 為什么使用數據庫索引可以提高效率,在什么情況下會用不到數據庫索引?
  • 共享鎖和排他鎖的使用場景
  • 關系型數據庫和非關系數據庫的優缺點
  • Mysql 什么情況會造成慢查,如何查看慢查詢
  • 如何處理慢查詢,你一般是怎么處理慢查詢的
  • Mysql 中 varchar 和 char 的區別
  • 數據庫外鍵的優缺點
  • 有沒有使用過數據庫的視圖
  • Mysql 中插入數據使用自增 id 好還是使用 uuid,為什么?
  • Mysql 有哪些數據類型,使用的時候有沒有什么注意點
  • Mysql 集群有哪幾種方式,分別適用於什么場景
  • Mysql 主從模式如何保證主從強一致性
  • Mysql 集群如何保證主從可用性
  • Mysql 讀寫分離有哪些解決辦法

數據庫三范式

  1. 第一范式: 確保每列的原子性,每列都是不可分割的最小數據單元
  2. 第二范式: 在第一范式的基礎上,要求每列都和主鍵相關
  3. 第三范式: 在第二范式的基礎上,要求其他列和主鍵是直接相關,而不是間接相關

分別說一下范式和反范式的優缺點

1.范式化

優點:

  • 減少數據冗余
  • 表中重復數據較少,更新操作比較快
  • 范式化的表通常比反范式化的表小

缺點:

  • 在查詢的時候通常需要很多的關聯,降低性能
  • 增加了索引優化的難度

2.反范式化

優點:

  • 可以減少表的關聯
  • 更好的進行索引優化

缺點:

  • 數據重復冗余
  • 對數據表的修改需要更多的成本

Mysql 數據庫索引。B+ 樹和 B 樹的區別

MySQL數據庫索引和存儲引擎有關,MyISAM和InnoDB只支持BTREE索引。MEMORY和HEAP支持HASH和BTREE索引

B+樹和B樹的區別

  • B+樹非葉子節點只存儲關鍵字和指向子節點的指針,而B樹還存儲了數據,在同樣大小的情況下,B+樹可以存儲更多的關鍵字
  • B+樹葉子節點存儲了所有關鍵字和數據,並且多個節點用鏈表連接。可以快速支撐范圍查找
  • B+樹非葉子節點不存儲數據,所以查詢時間復雜度固定為O(logN),B樹查詢時間復雜度不固定,最好是O(1)

參考文章:B+樹和B樹的區別

為什么 B+ 樹比 B 樹更適合應用於數據庫索引,除了數據庫索引,還有什么地方用到了(操作系統的文件索引)

因為B樹葉子節點和非葉子結點都存儲了數據,這樣就導致了非葉子結點能保存的關鍵字和指針變少,如果要保存大量數據,只能增加樹的高度,導致IO操作變多,查詢性能降低

除數據庫索引,還有操作系統的文件索引用到了B樹。參考文章:操作系統 文件索引結構

聚簇索引和非聚簇索引

  • 聚簇索引,又叫主鍵索引,每個表只有一個主鍵索引,葉子節點保存主鍵的值和數據
  • 非聚簇索引,又叫輔助索引,葉子節點保存索引字段的值和主鍵的值

前綴索引和覆蓋索引

1.前綴索引

對於列的值較長,比如BLOB、TEXT、VARCHAR,就必須建立前綴索引,即將值的前一部分作為索引。這樣既可以節約空間,又可以提高查詢效率。但無法使用前綴索引做 ORDER BY 和 GROUP BY,也無法使用前綴索引做覆蓋掃描。

2.覆蓋索引

select的數據列從索引中就能獲得,不必再從數據表中讀取。如果一個索引包含了(或覆蓋了)滿足查詢語句中字段與條件的數據就叫 做覆蓋索引。

當發起一個被索引覆蓋的查詢(也叫作索引覆蓋查詢)時,在EXPLAINExtra列可以看到“Using index”的信息

參考文章:什么叫做覆蓋索引?

介紹一下數據庫的事務

事務是一個操作序列,這些操作要么全部執行,要么都不執行。

事務具有四大特性:A(原子性)、C(一致性)、I(隔離性)、D(持久性)

Mysql 有哪些隔離級別

       
       
       
       
       

Mysql 什么情況會造成臟讀、不可重復讀、幻讀?如何解決

  • 臟讀:有兩個事務A和B,A讀取已經被B修改但未提交的字段,此時B回滾,那么A讀取的字段就是臨時且無效的。可以提高隔離級別,改成讀已提交
  • 不可重復讀: 有兩個事務A和B,A讀取了一個字段值,然后B更新並且提交事務,A再重新讀取這個字段,就和之前不相等了。可以提高隔離級別,改成可重復讀
  • 幻讀: 有兩個事務A和B,A讀取某個范圍內的記錄時,B又在該范圍內插入了新的記錄並提交,當事務A再次讀取該范圍的記錄時,會產生幻行。可以升級隔離級別到串行化,或者使用 MVCC + next-key鎖機制實現

Mysql 在可重復讀的隔離級別下會不會有幻讀的情況,為什么?

不會。InnoDB存儲引擎默認隔離級別為RR,通過MVCC + next-key鎖機制解決了幻讀的問題。

PS:其實嚴格來說,是存在幻讀的。。。可以嘗試一下這個操作,A開啟事務,執行查詢,此時B開啟事務新增一條數據並提交,此時A再查詢,發現沒有幻讀,但是如果A執行一個update操作,再查詢,會發現出現了幻讀。我認為應該是A在執行update操作的時候,新建了一條創建版本號為A事務版本號的記錄,然后標記B事務創建的記錄為待刪除的,查詢的版本號依據是刪除版本號為空或大於當前版本號,並且創建版本號小於等於當前事務版本號,那么這里剛剛A更新的這條數據,顯然也符合查詢的條件,所以也會被查出來。

MVCC版本號原理參考文章:Mysql中MVCC的使用及原理詳解

詳細測試參考文章:MySQL可重復讀級別會不會造成幻讀

Mysql 事務是如何實現的

  • 原子性:通過undo log實現的。每條數據變更都伴隨一條undo log日志的生成,當系統發生錯誤或執行回滾根據undo log做逆向操作
  • 持久性:通過redo log實現的。redo log記錄了數據的修改日志。數據持久化到磁盤,先是儲存到緩沖池里,然后緩沖池中的數據定期同步到磁盤中,如果系統宕機,可能會丟失數據,系統重啟后會讀取redo log恢復數據
  • 隔離性:mysql數據庫通過MVCC + next-key機制實現了隔離性
  • 一致性:以上3大特性,保障了事務的一致性

Binlog 和 Redo log 的區別是什么,分別是什么用?

  • binlog是二進制文件,記錄了對數據庫執行更改的所有操作,不包括 select、show,因為這兩個操作沒有對數據本身做修改。但是若操作了數據,但是數據沒有發生變化,也會記錄到binlog。常用來數據恢復,數據備份。
  • redo log又叫做重做日志文件,記錄了事務的修改,不管事務是否提交都記錄下來。在實例和介質失敗時,InnoDB存儲引擎會使用redo log恢復到之前的狀態,保證數據的完整性

談一談 MVCC 多版本並發控制

MVCC是通過在每行記錄后面保存兩個隱藏的列來實現的。這兩個列,一個保存了行的創建時間,一個保存行的過期時間(或刪除時間)。當然存儲的並不是實際的時間值,而是系統版本號(system version number)。每開始一個新的事務,系統版本號都會自動遞增。事務開始時刻的系統版本號會作為事務的版本號,用來和查詢到的每行記錄的版本號進行比較。

SELECT

InnoDB會根據以下兩個條件檢查每行記錄:

  1. InnoDB只查找版本早於當前事務版本的數據行(也就是,行的系統版本號小於或等於事務的系統版本號),這樣可以確保事務讀取的行,要么是在事務開始前已經存在的,要么是事務自身插入或者修改過的。
  2. 行的刪除版本要么未定義,要么大於當前事務版本號。這可以確保事務讀取到的行,在事務開始之前未被刪除。

只有符合上述兩個條件的記錄,才能返回作為查詢結果

INSERT

InnoDB為新插入的每一行保存當前系統版本號作為行版本號。

DELETE

InnoDB為刪除的每一行保存當前系統版本號作為行刪除標識。

UPDATE

InnoDB為插入一行新記錄,保存當前系統版本號作為行版本號,同時保存當前系統版本號到原來的行作為行刪除標識。

Innodb 和 MyISAM 的區別是什么

  1. Innodb 支持事務。MyISAM 不支持
  2. Innodb 支持外鍵。MyISAM 不支持
  3. Innodb 主鍵索引的葉子節點是數據文件,輔助索引的葉子節點是主鍵的值。MyISAM 的主鍵索引和輔助索引,葉子節點都是數據文件的指針
  4. Innodb 不保存表的行數,執行 select count(*) from tb需要全表掃描。MyISAM 用一個變量保存了整個表的行數,執行上述語句只需要讀取該變量,速度很快
  5. Innodb 所有的表在磁盤上保存在一個文件中。MyISAM 存儲成三個文件。
  6. Innodb 需要更多的內存和存儲。MyISAM 可被壓縮,存儲空間較小。
  7. Innodb 移植方案拷貝文件、備份 binlog,或者用 mysqldump,移植較困難。MyISAM 數據以文件形式存儲,在備份和回復時可以單獨針對表進行操作
  8. Innodb 支持行鎖、表鎖。MyISAM 支持表鎖
  9. Innodb 在5.7版本之前不支持全文索引。MyISAM 支持全文索引

Innodb 的默認加鎖方式是什么,是怎么實現的

Innodb默認加鎖方式是行級鎖

通過給索引上的索引項加鎖來實現的

如何高效處理大庫 DDL

DDL是值數據定義語句,即建表,建視圖這種,所以這里的問題,我認為可能是考察建表的時候注意事項。

比如數據字段的定義,遵循從小原則。表的創建,降低耦合。

這道題不是很明白,歡迎留言討論。

Mysql 索引重建

  1. mysqldump導出然后重新導入,drop index + recreate index
  2. alter table xxx ENGINE = InnoDB
  3. repaire table xxx,這種對於InnoDB的無效
  4. OPTIMIZE TABLE xxx

對於多列索引,哪些情況下能用到索引,哪些情況用不到索引

  1. like%開頭
  2. or查詢,必須左右字段都是索引,否則索引失效
  3. 聯合索引,遵從最左匹配原則,如果不是使用第一列索引,索引失效
  4. 數據出現隱形轉換,如varchar字段沒加單引號,自動轉為int類型,會使索引失效
  5. 索引字段使用not<>!=,索引失效
  6. 索引字段使用函數,索引無效

為什么使用數據庫索引可以提高效率,在什么情況下會用不到數據庫索引?

默認執行SQL語句是進行全表掃描,遇到匹配條件的就加入搜索結果合集。如果有索引,就會先去索引表中一次定位到特定值的行數,減少遍歷匹配的行數。索引把無序的數據變成了相對有序的數據結構。

什么情況用不到數據庫索引 見上題回答

共享鎖和排他鎖的使用場景

更新、新增、刪除默認加排它鎖,查詢默認不加鎖

共享鎖,使用語法select * from tb lock in share mode,自身可以讀,其他事務也可以讀(也可以繼續加共享鎖),但是其他事務無法修改

排它鎖,適用語法select * from tb for update,自身可以進行增刪改查,其他事務無法進行任何操作

關系型數據庫和非關系數據庫的優缺點

關系型數據庫

優點:

  1. 二維表格,容易理解
  2. 操作方便
  3. 易於維護
  4. 支持SQL

缺點:

  1. 讀寫性能較差
  2. 固定的表結構,不夠靈活
  3. 應對高並發場景,磁盤I/O存在瓶頸
  4. 海量數據的讀寫性能差

非關系型數據庫

優點:

  1. 不需要SQL解析,讀寫性能高
  2. 可以使用硬盤或者內存作為載體,速度快
  3. 基於鍵值對,數據沒有耦合性,方便擴展
  4. 部署簡單

缺點:

  1. 不支持SQL,增加了學習成本
  2. 沒有事務

Mysql 什么情況會造成慢查,如何查看慢查詢

響應時間超過閾值會產生慢查詢日志。一般有以下情況會造成查詢慢

  1. 沒有設置索引,或查詢沒有用到索引
  2. I/O吞吐量過小
  3. 內存不足
  4. 網絡速度慢
  5. 查詢的數據量過大
  6. 鎖或者死鎖
  7. 返回了不必要的行或列
  8. 查詢語句存在問題,需要優化

慢查詢日志默認是關閉的,如果非必要,不要開啟,會影響性能。

使用SHOW VARIABLES LIKE 'slow_query%';

slow_query_log,慢查詢開啟關閉狀態

slow_query_log_file,慢查詢日志存儲位置,用文本編輯器打開存儲位置的文件,查詢慢查詢

如何處理慢查詢,你一般是怎么處理慢查詢的

  1. 把數據、日志、索引放到不同的I/O設備上,增加讀取速度
  2. 縱向、橫向分割表,減少表的尺寸
  3. 升級硬件
  4. 根據查詢條件,建立索引,索引優化
  5. 提高網速
  6. 擴大服務器內存
  7. 分庫分表

Mysql 中 varchar 和 char 的區別

varchar會根據存儲的內容改變長度,char是定長,如果長度不夠,則使用空格補齊

數據庫外鍵的優缺點

優點:

  1. 能最大限度的保證數據的一致性和完整性
  2. 增加ER圖的可讀性

缺點:

  1. 影響數據操作的效率
  2. 增加開發難度,導致表過多

有沒有使用過數據庫的視圖

使用create view view_name as select * from tb創建視圖

使用select * from view_name正常查詢視圖

Mysql 中插入數據使用自增 id 好還是使用 uuid,為什么?

  1. 單實例或單節點組,不擔心網絡爬蟲獲取數據量,推薦使用自增id,性能更好
  2. 分布式場景。20個節點下的小規模分布式場景,推薦uuid。20~200個節點的中規模分布式場景,推薦自增id+步長的策略。200以上節點,推薦推特雪花算法的全局自增ID

Mysql 有哪些數據類型,使用的時候有沒有什么注意點

  • 整數類型:BITBOOLTINY INTSMALL INTMEDIUM INTINTBIG INT
  • 浮點數類型:FLOATDOUBLEDECIMAL
  • 字符串類型:CHARVARCHARTINY TEXTTEXTMEDIUM TEXTLONGTEXTTINY BLOBMEDIUM BLOBLONG BLOB
  • 日期類型:DateDateTimeTIMESTAMPTIMEYEAR

使用的時候建議遵循從小原則。

  • 使用charvahrchar的時候,注意char會去掉字符串末尾的空格
  • 使用textblob的時候,注意定期清理碎片空間,使用OPTIMIZE TABLE命令
  • 浮點數會造成精度丟失,盡量使用定點數DECIMAL

Mysql 集群有哪幾種方式,分別適用於什么場景

組建MySQL集群的方式:

  1. LVS + Keepalived + MySQL
  2. DRBD + Heartbeat + MySQL
  3. MySQL + Proxy
  4. MySQL Cluster
  5. MySQL + MHA
  6. MySQL + MMM

場景:

  1. 如果是雙主復制,不需要數據拆分,可以使用MHA或Keepalived或Heartbeat
  2. 如果是雙主復制,需要數據拆分,采用Cobar
  3. 如果是雙主復制+Slave,還做了數據拆分,需要讀寫分離,采用Amoeba

Mysql 主從模式如何保證主從強一致性

主從復制原理:master寫數據留下寫入日志,slave根據master留下的日志模仿數據執行過程寫入

所以有兩個步驟可能導致主從復制不一致:

  1. master日志寫入不成功
  2. slave根據日志模仿不成功

解決辦法;

  1. master上修改配置

    • innodb_flush_log_at_trx_commit = 1
      sync_binlog = 1

    上述兩個選項的作用是:保證每次事務提交后,都能實時刷新到磁盤中,尤其是確保每次事務對應的binlog都能及時刷新到磁盤中

  2. slave上修改配置

    • master_info_repository = "TABLE"
      relay_log_info_repository = "TABLE"
      relay_log_recovery = 1
      

       

    上述前兩個選項的作用是:確保在slave上和復制相關的元數據表也采用InnoDB引擎,受到InnoDB事務安全的保護,而后一個選項的作用是開啟relay log自動修復機制,發生crash時,會自動判斷哪些relay log需要重新從master上抓取回來再次應用,以此避免部分數據丟失的可能性。

Mysql 集群如何保證主從可用性

使用HA檢測工具。HA工具部署在第三台服務器上,同時連接主從,檢測主從是否存活。如果主庫宕機則及時將從庫升級為主庫,將原來的主庫降級為從庫

Mysql 讀寫分離有哪些解決辦法

  1. 配置多數據源
  2. 使用中間件代理


免責聲明!

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



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