Mysql進階學習
1.MYSQL執行SQL的流程
SQL的執行過程;
-
- 客戶端發送一條查詢給服務器;
-
- 服務器通過權限檢查之後,先會檢查查詢緩存,如果命中了緩存,則立即返回存儲在緩存中的結果。否則進入下一階段;
-
- 服務器端進行SQL解析、預處理,再由優化器根據該SQL所涉及到的數據表的統計信息進行計算,生成對應的執行計劃;
-
- MySQL根據優化器生成的執行計劃,調用存儲引擎的API來執行查詢;
-
- 將結果返回給客戶端。
SQL執行的最大瓶頸在於磁盤的IO,即數據的讀取;不同SQL的寫法,會造成不同的執行計劃的執行,而不同的執行計劃在IO的上面臨完全不一樣的數量級,從而造成性能的差距;
所以,我們說,優化SQL,其實就是讓查詢優化器根據程序猿的計劃選擇匹配的執行計劃,來減少查詢中產生的IO;
2.schema(表結構)對性能的影響
- 冗餘數據的處理;
- 適當的數據冗餘可以提高系統的整體查詢性能;
- 關係數據庫的三範式:
- 第一範式(1NF)是對關係模式的基本要求,不滿足第一範式(1NF)的數據庫就不是關係數據庫,是指數據庫表的每一列都是不可分割的基本數據項,同一列中不能有多個值;
- 第二範式(2NF)要求數據庫表中的每個實例或行必須可以被惟一地區分。
- 第三範式(3NF)要求一個數據庫表中不包含已在其它表中已包含的非主關鍵字信息。 (不允許有冗餘數據)
- 大表拆小表,有大數據的列單獨拆成小表;
在一個數據庫中,一般不會設計屬性過多的表;
在一個數據庫中,一般不會有超過500/1000萬數據的表(拆表,按照邏輯拆分,按照業務拆分);
有大數據的列單獨拆成小表(富文本編輯器,CKeditor);
- 根據需求的展示設置更合理的表結構;
- 把常用屬性分離成小表;
- 減少查詢常用屬性需要查詢的列;
- 便於常用屬性的集中緩存;
3.索引和索引的優化
- 索引的原理:把無序的數據變成有序的查詢;
索引:
索引的物理結構:
- 數據庫文件存儲的位置:my.ini配置文件中dataDir對應的數據目錄中;
- 每一個數據庫一個文件夾;
- MYISAM引擎:每一個表(table_name)–>
table_name.MYI:存放的是數據表對應的索引信息和索引內容;
table_name.FRM:存放的是數據表的結構信息;
table_name.MYD:存放的是數據表的內容;- InnoDB引擎:每一個表(table_name)–>
table_name.frm:存放的是數據表的結構信息;
數據文件和索引文件都是統一存放在ibdata文件中;- 索引文件都是額外存在的,對索引的查詢和維護都是需要消耗IO的;
索引的結構:
- 默認情況下,一旦創建了一個表,這個表設置了主鍵,那麼MYSQL會自動的爲這個主鍵創建一個unique的索引;
- 索引類型:
- Normal:普通的索引;允許一個索引值後面關聯多個行值;
- UNIQUE:唯一索引;允許一個索引值後面只能有一個行值;之前對列添加唯一約束其實就是爲這列添加了一個unique索引;當我們爲一個表添加一個主鍵的時候,其實就是爲這個表主鍵列(設置了非空約束),併爲主鍵列添加了一個唯一索引;
- Fulltext:全文檢索,mysql的全文檢索只能用myisam引擎,並且性能較低,不建議使用;
索引的方法(規定索引的存儲結構): (數據結構,算法基礎)
* b-tree:是一顆樹(二叉樹,平衡二叉樹,平衡樹(B-TREE))
使用平衡樹實現索引,是mysql中使用最多的索引類型;在innodb中,存在兩種索引類型,第一種是主鍵索引(primary key),在索引內容中直接保存數據的地址;第二種是其他索引,在索引內容中保存的是指向主鍵索引的引用;所以在使用innodb的時候,要儘量的使用主鍵索引,速度非常快;
b-tree中保存的數據都是按照一定順序保存的數據,是可以允許在範圍之內進行查詢;
select * from accountflow where account_id <100;
* hash:把索引的值做hash運算,並存放到hash表中,使用較少,一般是memory引擎使用;優點:因爲使用hash表存儲,按照常理,hash的性能比B-TREE效率高很多。
- hash索引的缺點:
- hash索引只能適用於精確的值比較,=,in,或者<>;無法使用範圍查詢;
- 無法使用索引排序;
- 組合hash索引無法使用部分索引;
- 如果大量索引hash值相同,性能較低;
4.索引的利弊
- 索引的好處:
- 提高表數據的檢索效率;
- 如果排序的列是索引列(如果查詢的列==排序的列[並且在這列上做了索引]),大大降低排序成本;
- 在分組操作中如果分組條件是索引列,也會提高效率;
- 索引的問題:
- 索引需要額外的維護成本;因爲索引文件是單獨存在的文件,對數據的增加,修改,刪除,都會產生額外的對索引文件的操作,這些操作需要消耗額外的IO,會降低增/改/刪的執行效率;
- 怎麼創建索引?
- 較頻繁的作爲查詢條件的字段應該創建索引;
- 唯一性太差的字段不適合單獨創建索引,即使頻繁作爲查詢條件;
- 作爲索引的列,如果不能有效的區分數據,那麼這個列就不適合作爲索引列;比如(性別,狀態不多的狀態列)
- 舉例:SELECT sum(amount) FROM accountflow WHERE accountType = 0;
- 假如把accountType作爲索引列,因爲accountType只有14種,所以,如果根據accountType來創建索引,最多隻能按照1/14的比例過濾掉數據;但是,如果可能出現,只按照該條件查詢,那我們就要考慮到其他的提升性能的方式了;
- 第一種方案:單獨創建一個系統摘要表;在這個表裏面有一個列叫做系統總充值金額;每次充值成功,增加這個列的值;以後要查詢系統總充值金額,只需要從這個系統摘要表中查詢;(缺陷:如果充值頻率過快,會導致表的鎖定問題;)
- 第二種方案:流水一旦發生了,是不會隨着時間改變的;針對這種信息,我們就可以使用增量查詢(結算+增量查詢);
* 創建一張日充值表;記錄每一天的充值總金額(beginDate,endDate,totalAmount),每天使用定時器對當前的充值記錄進行結算;日充值報表裏面記錄只能記錄截止昨天的數據;
* 創建一張月充值表;記錄每一個月的充值總金額(beginDate,endDate,totalAmount),每月最後一天使用定時器對當月的充值記錄進行結算(數據源從日充值報表來);
* 要查詢系統總充值,從月報表中彙總(當前月之前的總充值金額),再從日充值報表中查詢當天之前的日報表數據彙總;再從流水中查詢當前截止查詢時間的流水;使用另外一張當天流水錶記錄當天的流水;再把三個數據累加;
- 更新非常頻繁的字段不適合創建索引;原因,索引有維護成本;
- 不會出現在WHERE 子句中的字段不該創建索引;
- 索引不是越多越好;(只爲必要的列創建索引)
- 不管你有多少個索引,一次查詢至多采用一個索引;(索引和索引之間是獨立的);
- 因爲索引和索引之間是獨立的,所以說每一個索引都應該是單獨維護的;數據的增/改/刪,會導致所有的索引都要單獨維護;
5.索引的使用限制
BLOB 和TEXT 類型的列只能創建前綴索引
MySQL 目前不支持函數索引(在MYSQL中,索引只能是一個列的原始值,不能把列通過計算的值作爲索引);
- 實例:請查詢1981年入職的員工:
SELECT * FROM emp WHERE year(hire_date)=‘1981’;- 問題:查詢的列是在過濾之前經過了函數運算;所以,就算hire_date作爲索引,year(hire_date)也不會使用索引;
解決方案:- SELECT * FROM emp WHERE hire_date BETWEEN ‘1981-01-01’ AND ‘1981-12-31’;
- 在創建一列,這列的值是year(hire_date),然後把這列的值作爲索引;
使用不等於(!= 或者<>)的時候MySQL 無法使用索引
過濾字段使用了函數運算後(如abs(column)),MySQL 無法使用索引
Join 語句中Join 條件字段類型不一致的時候MySQL 無法使用索引
使用LIKE 操作的時候如果條件以通配符開始( ‘%abc…’)MySQL 無法使用索引
- 字符串是可以用來作爲索引的;
- 字符串創建的索引按照字母順序排序;
- 如果使用LIKE,實例:SELECT * FROM userinfo WHERE realName LIKE ‘吳%’;這種情況是可以使用索引的;
但是LIKE ‘_嘉’ 或者LIKE '%嘉’都是不能使用索引的;使用非等值查詢的時候MySQL 無法使用Hash 索引
6.單列索引和複合索引
- 因爲一個查詢一次至多隻能使用一個索引,所以,如果都使用單值索引(一個列一個索引),在數據量較大的情況下,不能很好的區分數據;
- 所以,MYSQL引入了多值索引(複合索引);
複合索引就是由多列的值組成的索引;並且(注意),多列的索引是有順序的!!!- 複合索引的原理:就是類似orderby(orderby後面可以跟多個排序條件order by hire_date,username desc);
- 就是在排序和分組(創建倒排表的時候),按照多個列進行排序和合並;
- SELECT * FROM accountflow WHERE actionTime < ‘xxxxx’ AND account_id = 5 可以使用actionTime+account_id的複合索引;
- SELECT * FROM accountflow WHERE actionTime < ‘xxxxx’ 可以使用actionTime+account_id的複合索引;
- SELECT * FROM accountflow WHERE account_id = 5 不可以使用actionTime+account_id的複合索引;
- SELECT * FROM accountflow WHERE account_id = 5 AND actionTime < ‘xxxxx’ 不可以使用actionTime+account_id的複合索引;
- 複合索引,在查詢的時候,遵守向左原則;只要在查詢的時候,是按照複合索引從左到右的順序依次查詢,不管查詢條件是否完全滿足所有的符合索引的列,都可以使用部分的符合索引;
- 在實際應用中,基本上都使用複合索引;
7.查看MYSQL的執行計劃和執行明細狀態(explain+profiling)
- Explain:可以讓我們查看MYSQL執行一條SQL所選擇的執行計劃;
- Profiling:可以用來準確定位一條SQL的性能瓶頸;
7.1 EXPLAIN:
- 使用方式:
explain SQL;
- 返回結果:
ID:執行查詢的序列號;
select_type:使用的查詢類型
- DEPENDENT SUBQUERY:子查詢中內層的第一個SELECT,依賴於外部查詢的結果集;
- DEPENDENT UNION:子查詢中的UNION,且爲UNION 中從第二個SELECT 開始的後面所有SELECT,同樣依賴於外部查詢的結果集;
- PRIMARY:子查詢中的最外層查詢,注意並不是主鍵查詢;
- SIMPLE:除子查詢或者UNION 之外的其他查詢;
- SUBQUERY:子查詢內層查詢的第一個SELECT,結果不依賴於外部查詢結果集;
- UNCACHEABLE SUBQUERY:結果集無法緩存的子查詢;
- UNION:UNION 語句中第二個SELECT 開始的後面所有SELECT,第一個SELECT 爲PRIMARY
- UNION RESULT:UNION 中的合併結果;
table:這次查詢訪問的數據表;
type:對錶所使用的訪問方式:
- all:全表掃描
- const:讀常量,且最多隻會有一條記錄匹配,由於是常量,所以實際上只需要讀一次;
- eq_ref:最多隻會有一條匹配結果,一般是通過主鍵或者唯一鍵索引來訪問;
- fulltext:全文檢索,針對full text索引列;
- index:全索引掃描;
- index_merge:查詢中同時使用兩個(或更多)索引,然後對索引結果進行merge 之後再讀取表數據;
- index_subquery:子查詢中的返回結果字段組合是一個索引(或索引組合),但不是一個主鍵或者唯一索引;
- rang:索引範圍掃描;
- ref:Join 語句中被驅動表索引引用查詢;
- ref_or_null:與ref 的唯一區別就是在使用索引引用查詢之外再增加一個空值的查詢;
- system:系統表,表中只有一行數據;
- unique_subquery:子查詢中的返回結果字段組合是主鍵或者唯一約束;
possible_keys:可選的索引;如果沒有使用索引,爲null;
key:最終選擇的索引;
key_len:被選擇的索引長度;
ref:過濾的方式,比如const(常量),column(join),func(某個函數);
rows:查詢優化器通過收集到的統計信息估算出的查詢條數;
Extra:查詢中每一步實現的額外細節信息
- Distinct:查找distinct 值,所以當mysql 找到了第一條匹配的結果後,將停止該值的查詢而轉爲後面其他值的查詢;
- Full scan on NULL key:子查詢中的一種優化方式,主要在遇到無法通過索引訪問null值的使用使用;
- Impossible WHERE noticed after reading const tables:MySQL Query Optimizer 通過收集到的統計信息判斷出不可能存在結果;
- No tables:Query 語句中使用FROM DUAL 或者不包含任何FROM 子句;
- Not exists:在某些左連接中MySQL Query Optimizer 所通過改變原有Query 的組成而使用的優化方法,可以部分減少數據訪問次數;
- Select tables optimized away:當我們使用某些聚合函數來訪問存在索引的某個字段的時候,MySQL Query Optimizer 會通過索引而直接一次定位到所需的數據行完成整個查詢。當然,前提是在Query 中不能有GROUP BY 操作。如使用MIN()或者MAX()的時候;
- Using filesort:當我們的Query 中包含ORDER BY 操作,而且無法利用索引完成排序操作的時候,MySQL Query Optimizer 不得不選擇相應的排序算法來實現。
- Using index:所需要的數據只需要在Index 即可全部獲得而不需要再到表中取數據;
- Using index for group-by:數據訪問和Using index 一樣,所需數據只需要讀取索引即可,而當Query 中使用了GROUP BY 或者DISTINCT 子句的時候,如果分組字段也在索引中,Extra 中的信息就會是Using index for group-by;
- Using temporary:當MySQL 在某些操作中必須使用臨時表的時候,在Extra 信息中就會出現Using temporary 。主要常見於GROUP BY 和ORDER BY 等操作中。
- Using where:如果我們不是讀取表的所有數據,或者不是僅僅通過索引就可以獲取所有需要的數據,則會出現Using where 信息;
- Using where with pushed condition:這是一個僅僅在NDBCluster 存儲引擎中才會出現的信息,而且還需要通過打開Condition Pushdown 優化功能纔可能會被使用。控制參數爲engine_condition_pushdown 。
7.2 profiling
- Query Profiler是MYSQL5.1之後提供的一個很方便的用於診斷Query執行的工具,能夠準確的獲取一條查詢執行過程中的CPU,IO等情況;
- 開啓profiling:set profiling=1;
- 執行QUERY,在profiling過程中所有的query都可以記錄下來;
- 查看記錄的query:show profiles;
- 選擇要查看的profile:show profile cpu, block io for query 6;
- status是執行SQL的詳細過程;
- Duration:執行的具體時間;
- CPU_user:用戶CPU時間;
- CPU_system:系統CPU時間;
- Block_ops_in:IO輸入次數;
- Block_ops_out:IO輸出次數;
profiling只對本次會話有效;
8.JOIN
- JOIN的原理:
- 在mysql中使用Nested Loop Join來實現join;
- A JOIN B:通過A表的結果集作爲循環基礎,一條一條的通過結果集中的數據作爲過濾條件到下一個表中查詢數據,然後合併結果;
- JOIN的優化原則:
- 儘可能減少Join 語句中的Nested Loop 的循環總次數,用小結果集驅動大結果集;
- 優先優化Nested Loop 的內層循環;
- 保證Join 語句中被驅動表上Join 條件字段已經被索引;
- 擴大join buffer的大小;
9. SQL優化原則
[原則一:選擇需要優化的SQL]
- 選擇需要優化的SQL:不是所有的SQL都需要優化,在優化的過程中,首選更需要優化的SQL;
怎麼選擇?優先選擇優化高併發低消耗的SQL;
- 1小時請求1W次,1次10個IO;
- 1小時請求10次,1次1W個IO;
考慮:- 從單位時間產生的IO總數來說,相同的;
- 針對一個SQL,如果我能把10個IO變成7個IO,一小時減少3W個IO;
針對第二個SQL,如果能把1W個IO變成7K個IO,一小時減少3W個IO;- 從優化難度上講,1W->7K難的多;
- 從整體性能上來說,第一個SQL的優化能夠極大的提升系統整體的性能;第二個SQL慢一點,無非也就是10個連接查詢慢一點;
- 定位性能瓶頸;
- SQL運行較慢有兩個影響原因,IO和CPU,明確性能瓶頸所在;
- 明確優化目標;
[原則二:從Explain和Profile入手]
- 任何SQL的優化,都從Explain語句開始;Explain語句能夠得到數據庫執行該SQL選擇的執行計劃;
- 首先明確需要的執行計劃,再使用Explain檢查;
- 使用profile明確SQL的問題和優化的結果;
[原則三:永遠用小結果集驅動大的結果集]
[原則四:在索引中完成排序]
[原則五:使用最小Columns]
- 減少網絡傳輸數據量;
- 特別是需要使用column排序的時候.爲什麼?MYSQL排序原理,是把所有的column數據全部取出,在排序緩存區排序,再返回結果;如果column數據量大,排序區容量不夠的時候,就會使用先column排序,再取數據,再返回的多次請求方式;
[原則六:使用最有效的過濾條件]
- 過多的WHERE條件不一定能夠提高訪問性能;
- 一定要讓where條件使用自己預期的執行計劃;
[原則七:避免複雜的JOIN和子查詢]
- 複雜的JOIN和子查詢,需要鎖定過多的資源,MYSQL在大量併發情況下處理鎖定性能下降較快;
- 不要過多依賴SQL的功能,把複雜的SQL拆分爲簡單的SQL;
- MySQL子查詢性能較低,應儘量避免使用;
10. innobuffer和事務
Innodb_buffer_pool_size:innodb的緩存,可以用於緩存索引,同時還會緩存實際的數據;
innodb_buffer_pool_size 參數用來設置Innodb 最主要的Buffer(Innodb_Buffer_Pool)的大小,對Innodb 整體性能影響也最大,可以按需要設置大一些;innodb中的事務處理:
a. 理解Innodb事務機制:
- 事務在buffer中對數據進行修改;
- 事務的變化記錄在事務日誌中;
- 在合適的時機同步事務日誌中的數據到數據庫中;
b. 所以什麼時候提交事務日誌文件,對系統性能影響較大,可以通過設置 innodb_flush_log_at_trx_commit來修改事務日誌同步時機:
- innodb_flush_log_at_trx_commit = 0,每1秒鐘同步一次事務日誌文件;
- innodb_flush_log_at_trx_commit = 1,默認設置,每一個事務完成之後,同步一次事務日誌文件;
- innodb_flush_log_at_trx_commit = 2,事務完成之後,寫到事務日誌文件中,等到日誌覆蓋再同步數據;
- 注意,1性能最差,2不能完全保證數據是寫到數據文件中,如果宕機,可能會有數據丟失現象,但性能最高;1,性能和安全性居中;
11. MYSQL的主從
什麼是MYSQL的主從,爲什麼要使用主從?
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-l9BHAsUQ-1589597779571)(https://image.ayding.top/markdown/image-20200516002317778.png)]
- 就算MYSQL拆成了多個,也必須分出主和從,所有的寫操作都必須要在主MYSQL 上完成;
- 所有的從MYSQL的數據都來自於(同步於)主MYSQL;
- 既然涉及到同步,那一定有延遲;有延遲,就一定可能在讀的時候產生髒數據;所以,能夠在從MYSQL上進行的讀操作,一定對實時性和髒數據有一定容忍度的數據;比如,登陸日誌,後臺報表,首頁統計信息來源;文章;資訊;SNS消息;
- 在一些金融項目做主從,絕大部分的讀操作,都必須在主MYSQL上執行;只有(登陸日誌,報表,滿標一審列表,滿標二審列表,用戶的流水信息,充值明細,投標明細查詢類的業務可以定位到從MYSQL);
- [一定注意]:在MYSQL主從時,如果一個業務(service中的一個方法)中,如果既有R操作,又有W操作,因爲W操作一定要在主MYSQL上,所以在一個事務中所有的數據來源都只能來自於一個MYSQL
MYSQL主從原理
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Cgll8tt5-1589597779572)(https://image.ayding.top/markdown/image-20200516003000218.png)]
- 要完成主從同步,就必須讓在Master上執行的所有的DML和DDL能夠正確的在Salve上再執行一遍;MYSQL選擇使用文件來記錄SQL;
- 要完成主從同步,第一個事情就是把在主服務器上的bin-log(二進制文件)打開,bin-log文件就可以記錄在MYSQL上執行的所有的DML+DDL+TCL;
- MYSQL使用被動註冊的方式來讓從MYSQL請求同步主MYSQL的binlog;原因:被動請求的方式,主的MYSQL不需要知道有哪些從的MYSQL,我額外添加/去掉從MYSQL服務器,對主MYSQL服務器的正常運行沒有任何影響;
- 第二步,從MYSQL後臺一個線程發送一個請求,到主服務器請求更新數據;最重要的數據(我這次請求,請求你bin-log的哪一行數據之後的數據)
- 第三步,主MYSQL後臺一個線程接收到從MYSQL發送的請求,然後讀取bin-log文件中指定的內容,並放在從MYSQL的請求響應中;
- 第四步,從MYSQL的請求帶回同步的數據,然後寫在從MYSQL中的relay-log(重做日誌)中;relay-log中記錄的就是從主MYSQL中請求回來的哪些SQL數據;
- 第五步,從MYSQL後臺一個線程專門用於從relay-log中讀取同步回來的SQL,並寫入到從MYSQL中,完成同步;
- MYSQL的主從同步是經過高度優化的,性能非常高;
配置主從:
添加一個新的MYSQL實例
a. 複製mysql安裝目錄;
b. 修改新mysql的相關配置(端口,安裝目錄,數據目錄)
c. 爲新的mysql創建數據目錄(從mysql的安裝目錄中拷貝data文件夾);
d. 爲新的mysql創建windows系統服務mysqld install MySQL2 --defaults-file=“E:\MySQL\mysql_base\ini\my.ini”
e.檢查創建的系統服務,並啓動測試;配置主從:
a. 因爲主數據庫之前的內容沒有放在binlog中,所以要同步這些數據,只能通過主數據庫備份來完成;
b. 配置主數據庫;
- server-id://給數據庫服務的唯一標識,一般爲大家設置服務器Ip的末尾號,在一個集羣中,這個id是不能重複的;
- log-bin=master-bin://開啓二進制文件;後面設置的這個master-bin就是二進制文件的名字前綴(名字);
- log-bin-index=master-bin.index//開啓二進制文件的索引;名字一般爲log-bin.index
啓動主數據庫,執行show master status命令;
只要能夠看到正常的查詢結果,說明主服務器已經配置完成;
結果中,注意兩個重點:
* File:二進制文件的文件名;
* sition:當前文件已經記錄到的位置;配置從服務器;
- server-id;
- relay-log=slave-relay-bin
- relay-log-index=slave-relay-bin.index
啓動從服務器;
回覆主數據庫的備份;
讓從數據庫指定Master庫:
- change master to master_host=‘127.0.0.1’, //Master 服務器Ip
- master_port=3306,//Master服務器的端口
- master_user=‘root’,//Master服務器的賬戶(其實應該是一個專門用於數據同步的賬戶)
- master_password=‘admin’,//Master服務器的同步賬戶密碼
- master_log_file=‘master-bin.000001’,//Master服務器產生的日誌
- master_log_pos=0;//指定請求同步Master的bin-log的哪一行數據之後的內容;
- 啓動從MYSQL;
12. 讀寫分離
- 需求:在後臺的登陸日誌中,讓登陸日誌的查詢從從數據庫中查詢,其他業務還是都先使用主數據庫;
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-GEhxobJS-1589597779575)(https://image.ayding.top/markdown/image-20200516004634355.png)]
一個service方法必須定位到一個唯一的數據庫上;
引入路由DataSource之後:
a. 在應用中,需要自己去確定(告訴路由DS)這次要訪問的真實的目標Datasource;
b. 讓路由DS知道有哪些真實的Datasource和他們對應的名字;
c. 讓路由DS根據我傳入的名字去返回真實的DS;完成讀寫分離:
a. 認識Spring中的AbstractRountingDataSource;
在Spring中提供了AbstractRountingDataSource來完成路由DS的功能;
targetDataSources:用於配置真實的datasource,這個屬性是一個Map,Map的key就是DS的名字,Map的value是真實的DS對象;
defaultTargetDataSource:如果路由DS沒有找到你當前請求的DS,直接使用默認的DS;
abstract Object determineCurrentLookupKey():這個方法是需要我們自己實現的,這個方法需要返回一個值,這個值就是DS的名字;這個方法就是讓應用(我們)提供給Spring怎麼找DS名字的邏輯;
b. 步驟:
- 創建一個繼承AbstractRountingDataSource的對象,並在Spring中配置;
- 修改原來的datasource的配置:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-s4proi83-1589597779577)(https://image.ayding.top/markdown/image-20200516005214166.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-e1ypot7W-1589597779579)(https://image.ayding.top/markdown/image-20200516005243619.png)]
- 配置路由:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-XN9vlYI5-1589597779580)(https://image.ayding.top/markdown/image-20200516005308983.png)]
- 注意,SqlSessionFactoryz中使用的datasource必須是路由datasource;
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-dI3jKBJO-1589597779585)(https://image.ayding.top/markdown/image-20200516005419285.png)]
測試:
- 正常登陸,查看master和slave是否同步;
- 修改從slave中的數據庫 ,檢查查詢是否修改;