mysql 相關
1、數據庫優化查詢方法
外鍵、索引、聯合查詢、選擇特定字段等等
2、簡述mysql和redis區別
redis: 內存型非關系數據庫,數據保存在內存中,速度快mysql:關系型數據庫,數據保存在磁盤中,檢索的話,會有一定的Io操作,訪問速度相對慢
3、列出常見MYSQL數據存儲引擎
InnoDB:支持事務處理,支持外鍵,支持崩潰修復能力和并發控制。如果需要對事務的完整性要求比較高(比如銀行),要求實現并發控制(比如售票),那選擇InnoDB有很大的優勢。如果需要頻繁的更新、刪除操作的數據庫,也可以選擇InnoDB,因為支持事務的提交(commit)和回滾(rollback)。MyISAM:插入數據快,空間和內存使用比較低。如果表主要是用于插入新記錄和讀出記錄,那么選擇MyISAM能實現處理高效率。如果應用的完整性、并發性要求比 較低,也可以使用。MEMORY:所有的數據都在內存中,數據的處理速度快,但是安全性不高。如果需要很快的讀寫速度,對數據的安全性要求較低,可以選擇MEMOEY。它對表的大小有要求,不能建立太大的表。所以,這類數據庫只使用在相對較小的數據庫表。
4、日常工作中你是怎么優化SQL的?
加索引--避免返回不必要的數據--適當分批量進行--優化sql結構--分庫分表--讀寫分離
5、說說分庫與分表的設計
水平分庫:以字段為依據,按照一定策略(hash、range等),將一個庫中的數據拆分到多個庫中水平分表:以字段為依據,按照一定策略(hash、range等),將一個表中的數據拆分到多個表中。垂直分庫:以表為依據,按照業務歸屬不同,將不同的表拆分到不同的庫中。垂直分表:以字段為依據,按照字段的活躍性,將表中字段拆到不同的表(主表和擴展表)中。
6、事務的隔離級別有哪些?MySQL的默認隔離級別是什么?
讀未提交(Read Uncommitted)讀已提交(Read Committed)可重復讀(Repeatable Read)串行化(Serializable)Mysql默認的事務隔離級別是可重復讀(Repeatable Read),其他數據庫一般默認為讀已提交。(我們可以把mysql的默認隔離級別修改為讀已提交,這句話面試官不問不要說,不要給自己挖坑)
7、什么是幻讀,臟讀,不可重復讀呢?
事務A、B交替執行,事務A被事務B干擾到了,因為事務A讀取到事務B未提交的數據,這就是臟讀在一個事務范圍內,兩個相同的查詢,讀取同一條記錄,卻返回了不同的數據,這就是不可重復讀。事務A查詢一個范圍的結果集,另一個并發事務B往這個范圍中插入/刪除了數據,并靜悄悄地提交,然后事務A再次查詢相同的范圍,兩次讀取得到的結果集不一樣了,這就是幻讀。
8、說一下數據庫的三大范式
第一范式:數據表中的每一列(每個字段)都不可以再拆分第二范式:在第一范式的基礎上,分主鍵列完全依賴于主鍵,而不能是依賴于主鍵的一部分第三范式:在滿足第二范式的基礎上,表中的非主鍵只依賴于主鍵,而不依賴于其他非主鍵
9、索引有哪幾種類型?
主鍵索引: 數據列不允許重復,不允許為NULL,一個表只能有一個主鍵。唯一索引: 數據列不允許重復,允許為NULL值,一個表允許多個列創建唯一索引。普通索引: 基本的索引類型,沒有唯一性的限制,允許為NULL值。全文索引:是目前搜索引擎使用的一種關鍵技術,對文本的內容進行分詞、搜索覆蓋索引:查詢列要被所建的索引覆蓋,不必讀取數據行組合索引:多列值組成一個索引,用于組合搜索,效率大于索引合并
10、創建索引有什么原則呢?
最左前綴匹配原則頻繁作為查詢條件的字段才去創建索引頻繁更新的字段不適合創建索引索引列不能參與計算,不能有函數操作優先考慮擴展索引,而不是新建索引,避免不必要的索引在order by或者group by子句中,創建索引需要注意順序區分度低的數據列不適合做索引列(如性別)定義有外鍵的數據列一定要建立索引。對于定義為text、image數據類型的列不要建立索引。刪除不再使用或者很少使用的索引
11、什么是數據庫事務?
數據庫事務(簡稱:事務),是數據庫管理系統執行過程中的一個邏輯單位,由一個有限的數據庫操作序列構成,這些操作要么全部執行,要么全部不執行,是一個不可分割的工作單位。
12、mysql 事務的特性,ACID
原子性、一致性、隔離性、持久性
13、B樹和B+樹的區別?
1、B-樹是一類樹,包括B-樹、B+樹、B*樹等,是一棵自平衡的搜索樹,它類似普通的平衡二叉樹,不同的一點是B-樹允許每個節點有更多的子節點。B-樹是專門為外部存儲器設計的,如磁盤,它對于讀取和寫入大塊數據有良好的性能,所以一般被用在文件系統及數據庫中。2、B+樹是B-樹的變體,也是一種多路搜索樹, 它與 B- 樹的不同之處在于:所有關鍵字存儲在葉子節點出現,內部節點(非葉子節點并不存儲真正的 data)為所有葉子結點增加了一個鏈指針因為內節點并不存儲 data,所以一般B+樹的葉節點和內節點大小不同,而B-樹的每個節點大小一般是相同的,為一頁
14、mysql 行鎖
MySQL的行鎖又分為共享鎖(S鎖)和排他鎖(X鎖)。一般普通的select語句,InnoDB不加任何鎖,我們稱之為快照讀select * from test;通過加S鎖和X鎖的select語句或者插入/更新/刪除操作,我們稱之為當前讀select * from test lock in share mode;select * from test for update;insert into test values(…);update test set …;delete from test …;以上的當前讀,讀取的都是記錄的最新版本。對讀取記錄都會加鎖,除了第一條語句lock in share mode是對記錄加S鎖(共享鎖)外,其他的操作都是加X鎖(排他鎖)。
15、什么是死鎖?怎么解決?
死鎖是指兩個或多個事務在同一資源上相互占用,并請求鎖定對方的資源,
從而導致惡性循環的現象
常見的解決死鎖的方法如果不同程序會并發存取多個表, 盡量約定以相同的順序訪問表,可以大大降低死鎖機會。
在同一個事務中,盡可能做到一次鎖定所需要的所有資源,減少死鎖產生概率;
對于非常容易產生死鎖的業務部分,可以嘗試使用升級鎖定顆粒度,
通過表級鎖定來減少死鎖產生的概率;
16、什么是臟讀?幻讀?不可重復讀?
臟讀(Drity Read):某個事務已更新一份數據,另一個事務在此時讀取了同一份數據,由于某些原因,前一個RollBack了操作,則后一個事務所讀取的數據就會是不正確的。不可重復讀(Non-repeatable read):在一個事務的兩次查詢之中數據不一致,
這可能是兩次查詢過程中間插入了一個事務更新的原有的數據。幻讀(Phantom Read):在一個事務的兩次查詢中數據筆數不一致,
例如有一個事務查詢了幾列(Row)數據, 而另一個事務卻在此時插入了新的幾列數據,
先前的事務在接下來的查詢中, 就會發現有幾列數據是它先前所沒有的。
17、索引有哪些使用場景
1)、應該創建索引的場景
主鍵應該創建主鍵索引。
頻繁作為查詢條件的字段應該創建索引。
查詢中需要與其他表進行關聯的字段應該創建索引。
需要排序的字段應該創建索引。
需要統計或分組的字段應該創建索引。
優先考慮創建復合索引。2)、不應創建索引的場景
數據記錄較少的表。
經常需要增刪改操作的字段。
數據記錄重復較多且分布平均的字段(如性別、狀態等)。
redis 相關
1、redis 是單線程還是多線程?
大家所熟知的 Redis 確實是單線程模型,指的是執行 Redis 命令的核心模塊是單線程的,
而不是整個 Redis 實例就一個線程,Redis 其他模塊還有各自模塊的線程的
2、Redis 不僅僅是單線程
一般來說 Redis 的瓶頸并不在 CPU,而在內存和網絡。如果要使用 CPU 多核,
可以搭建多個 Redis 實例來解決。
其實,Redis 4.0 開始就有多線程的概念了,比如 Redis 通過多線程方式在后臺刪除對象、
以及通過 Redis 模塊實現的阻塞命令等。
3、Redis系列 | 緩存穿透、擊穿、雪崩、預熱、更新、降級
緩存穿透
當查詢Redis中沒有的數據時,該查詢會下沉到數據庫層,同時數據庫層也沒有該數據,
當這種情況大量出現或被惡意攻擊時,接口的訪問全部透過Redis訪問數據庫,
而數據庫中也沒有這些數據,我們稱這種現象為"緩存穿透"。解決方案:
在接口訪問層對用戶做校驗,如接口傳參、登陸狀態、n秒內訪問接口的次數;
利用布隆過濾器,將數據庫層有的數據key存儲在位數組中,
以判斷訪問的key在底層數據庫中是否存在;
緩存擊穿
緩存擊穿和緩存穿透從名詞上可能很難區分開來,它們的區別是:
穿透表示底層數據庫沒有數據且緩存內也沒有數據,擊穿表示底層數據庫有數據而緩存內
沒有數據。當熱點數據key從緩存內失效時,大量訪問同時請求這個數據,
就會將查詢下沉到數據庫層,此時數據庫層的負載壓力會驟增,
我們稱這種現象為"緩存擊穿"。解決方案:
延長熱點key的過期時間或者設置永不過期,如排行榜,首頁等一定會有高并發的接口;
利用互斥鎖保證同一時刻只有一個客戶端可以查詢底層數據庫的這個數據,
一旦查到數據就緩存至Redis內,避免其他大量請求同時穿過Redis訪問底層數據庫;
緩存雪崩
緩存雪崩是緩存擊穿的"大面積"版,緩存擊穿是數據庫緩存到Redis內的熱點數據失效
導致大量并發查詢穿過redis直接擊打到底層數據庫,而緩存雪崩是指Redis中
大量的key幾乎同時過期,然后大量并發查詢穿過redis擊打到底層數據庫上,
此時數據庫層的負載壓力會驟增,我們稱這種現象為"緩存雪崩"。解決方案:
在可接受的時間范圍內隨機設置key的過期時間,分散key的過期時間,
以防止大量的key在同一時刻過期;
對于一定要在固定時間讓key失效的場景(例如每日12點準時更新所有最新排名),
可以在固定的失效時間時在接口服務端設置隨機延時,將請求的時間打散,
讓一部分查詢先將數據緩存起來;
延長熱點key的過期時間或者設置永不過期,這一點和緩存擊穿中的方案一樣;
緩存預熱
緩存預熱如字面意思,當系統上線時,緩存內還沒有數據,如果直接提供給用戶使用,
每個請求都會穿過緩存去訪問底層數據庫,如果并發大的話,很有可能在上線當天就會宕機,
因此我們需要在上線前先將數據庫內的熱點數據緩存至Redis內再提供出去使用,
這種操作就成為"緩存預熱"。
緩存預熱的實現方式有很多,比較通用的方式是寫個批任務,
在啟動項目時或定時去觸發將底層數據庫內的熱點數據加載到緩存內。
緩存更新
緩存服務(Redis)和數據服務(底層數據庫)是相互獨立且異構的系統,
在更新緩存或更新數據的時候無法做到原子性的同時更新兩邊的數據,
因此在并發讀寫或第二步操作異常時會遇到各種數據不一致的問題。
緩存更新的設計模式有四種:
Cache aside:查詢:先查緩存,緩存沒有就查數據庫,然后加載至緩存內;
更新:先更新數據庫,然后讓緩存失效;或者先失效緩存然后更新數據庫; Read through:在查詢操作中更新緩存,即當緩存失效時,Cache Aside 模式是由
調用方負責把數據加載入緩存,而 Read Through 則用緩存服務自己來加載;Write through:在更新數據時發生。當有數據更新的時候,如果沒有命中緩存,
直接更新數據庫,然后返回。如果命中了緩存,則更新緩存,然后由緩存自己更新數據庫; Write behind caching:俗稱write back,在更新數據的時候,只更新緩存,
不更新數據庫,緩存會異步地定時批量更新數據庫;
緩存降級
緩存降級是指當訪問量劇增、服務出現問題(如響應時間慢或不響應)或
非核心服務影響到核心流程的性能時,即使是有損部分其他服務,
仍然需要保證主服務可用。可以將其他次要服務的數據進行緩存降級,
從而提升主服務的穩定性。
Redis 能夠處理速度快的原因主要有以下幾個方面:
1、內存數據庫:Redis是一種內存數據庫,數據存儲在內存中,因此讀寫速度非常快。2、單線程:Redis是單線程的,避免了多線程帶來的上下文切換和鎖競爭的開銷,因此可以更高效地利用CPU資源。3、非阻塞式IO:Redis使用了非阻塞式IO,當執行一個IO操作時,它不會被阻塞,而是會立即返回,這樣就可以執行其他操作,提高了Redis的響應速度。4、基于事件驅動:Redis采用了基于事件驅動的模型,通過監聽socket事件,當事件發生時,執行相應的操作,避免了輪詢的開銷,提高了Redis的性能。5、輕量級:Redis的代碼量相對較小,且沒有復雜的依賴關系,因此它的啟動速度非常快,這也是它處理速度快的重要原因之一。綜上所述,Redis之所以能夠處理速度快,是因為它采用了多種優化策略和技術,從而實現了高效的數據存儲和快速的讀寫操作。