YesOk ,你們好 ,我是小劉,許久不見,甚是想念 ,小劉今天來帶你們學習 分庫分表的基礎知識mysql
數據庫分區是一種物理數據庫的設計技術,它的目的是爲了在特定的 SQL
操做中減小數據讀寫的總量以縮減響應時間。面試
分區並非生成新的數據庫表,而是將表的數據均勻分攤到不一樣的硬盤,系統或不一樣服務器存儲介子中,實際上仍是一張表。另外,分區能夠作到將表的數據分攤到不一樣的地方,提升數據檢索的效率,下降數據庫頻繁 IO
壓力值,分區的優勢以下:算法
這種形式分區是對錶的行進行分區,經過這種的方式不一樣分組裏面的物理列分割的數據集得以組合,從而進行個體分體或集體分割。全部在表中定義的列在每一個數據集中都能找到,因此表的特性得以保持。sql
舉例:一個包含十年發票記錄的表能夠被分區爲10個不一樣的分區,每一個分區包含的是其中一年的記錄。mongodb
這種分區方式通常來講是經過對錶的垂直劃分來減小目標表的寬度,使某些特定的列被劃分到特定的分區,每一個分區都包含了其中的列所對應的行。數據庫
舉例:一個包含了大 text
和 blob
列的表,這些 text
和 blod
列又不常常被訪問,這時候就要把這些不常用的 text
和 blob
了劃分到另外一個分區,在保證它們數據關聯性的同時還能提升訪問速度。服務器
mysql5
開始支持分區功能微信
建立表:session
create table sales( id int auto increment, amount double not null, order_day datetime not null, primary key(id,order_day) ) engine=Innodb
設置分區:併發
partition by range(year(order_day))( partition p_2010 values less than (2000), partition p_2011 values less than (2011), partition p_2012 values less than (2012), partition p_2012 values less than maxvalue );
sql
通過優化分表後,單表的併發能力提升了,磁盤的 IO
性能也提供了,寫操做效率也提升了。
I/O
性能提升要業務系統配合遷移升級,工做量較大
經常使用分區分表的規則策略
Range
(範圍)Hash
(哈希)Hash
以後按照分表個數取模DB
,這個 DB
單獨保存 user_id
到 DB
的映射關係DB
的存儲空間不夠其主要目的是爲突破單節點數據庫服務器的 I/O
能力限制,解決數據庫擴展性問題。
垂直拆分
把系統中不存在關聯關係或者須要 join
的表能夠放在不一樣的數據庫不一樣的服務器中。 按照業務垂直拆分。好比:能夠按照業務分爲資金、會員、訂單三個數據庫。
須要解決的問題:跨數據庫的事務、 join
查詢等問題。
水平拆分
例如,大部分的站點。數據都是和用戶有關,那麼能夠根據用戶,將數據按照用戶水平拆分。
按照規則拆分,通常水平庫是在垂直分庫以後的。好比天天處理的訂單數量是海量的,能夠按照必定的規則水平劃分。
須要解決的問題:數據路由、組裝。
讀寫分離
對於時效性不高的數據,能夠經過讀寫分離緩解數據庫壓力。
須要解決的問題:在業務上區分哪些業務是容許必定時間延遲的,以及數據同步問題。
分區就是把一張表的數據分紅N個區塊,在邏輯上看最終只是一個表,但底層是由N個物理區塊組成的。分表就是把一張表按必定的規則分解成N個具備獨立存儲空間的實體表。系統讀寫時須要根據定義好的規則獲得對應的字表名,而後操做它。分庫一旦分表,一個數據庫中的表會愈來愈多
優先級:垂直分庫–>水平分庫–>讀寫分離
join
時跨庫,跨表的問題解決方案:
對於不一樣的方式之間沒有嚴格的界限,特色不一樣,側重點不一樣。須要根據實際狀況,結合每種方式的特色來進行處理。選用第三方的數據庫中間件( Atlas
, Mycat
, TDDL
, DRDS
),同時業務系統須要配合數據存儲的升級。
總結:優先考慮分區。當分區不能知足需求時,開始考慮分表,合理的分表對效率的提高會優於分區。
現狀
總體的數據存儲:基礎數據存儲,文本存儲
基礎數據存儲
MySQL
:只存儲非文本的基礎信息。包括:評論狀態,用戶,時間等基礎數據。以及圖片,標籤,點贊等附加信息。數據組織形式(不一樣的數據又可選擇不一樣的庫表拆分方案):
ID
進行拆庫並拆表文本存儲
文本存儲(評論的內容)使用了 mongodb
、 hbase
nosql
而非 mysql。
mysql
存儲壓力,釋放 msyql
,龐大的存儲也有了可靠的保障。nosql
的高性能讀寫大大提高了系統的吞吐量並下降了延遲。在分佈式存儲系統中,數據須要分散在多臺設備上,數據分片( Sharding
)就是用來肯定數據在多臺存儲設備上分佈的技術,數據分片要達到三個目的:
數據分片方法
Consistent Hashing
)是在1997年由 MIT
提出的一種分佈式哈希 (DHT
)實現算法,設計目標是爲了解決因特網的熱點(Hot Spot
)問題。一致性哈希的算法簡單而巧妙,很容易作到數據均分佈,其單調性也保證了擴縮容的數據遷移是比較少的。虛擬服務器
爲了讓系統有更好的擴展性,這裏提出存儲層 VServer
(虛擬服務器)的概念,一個 VServer
是一個邏輯上的存儲服務器,是分佈式存儲系統的一個存儲單元,一臺物理設備上能夠部署多個 VServer
,一個 VServer
支持一個寫進程和多個讀進程。
經過 VServer
的方式,會有下面一些好處:
VServer
方式把單機上的存儲資源(內存、硬盤)劃分爲多個存儲單元,這樣就支持多個寫進程同時工做,大大提高單機寫併發能力。VServer
的方式在部署上很是靈活,能夠根據單機的資源狀況來肯定 VServer
的數量,針對不一樣的機型配置不一樣的 VServer
數量,這樣不一樣的機型都能充分利用機器上的資源,即便在一個系統中使用多種機型,也能作到機器的負載比較均衡。Atomic
):事務中各項操做,要麼全作要麼全不作,任何一項操做失敗都會致使整個事務的失敗Consistent
):事務結束後系統的狀態是一致的Isolated
):併發操做的事務彼此看不到對方的中間狀態Durable
):事務完成後所作的改動都會被持久化數據庫事務併發致使的問題
A
讀到了事務 B
未提交的數據A
查詢獲得一行記錄 row1
,事務B提交修改後,事務 A
第二次查詢獲得 row1
,但列內容發生了改變,側重於次數A
第一次查詢獲得一行記錄 row1
,事務 B
提交修改後,事務 A
第二次查詢獲得兩行記錄 row1
和 row2
,側重於 insert
MySQL數據庫給咱們提供的4中隔離級別
Serializable
):事務A屢次從一張表中讀取到相同的行,禁止其餘事務對這張表進行CRUD操做Repeatable read
):事務A能夠讀取到相同的值,禁止其餘事務對字段進行更改Read committed
):事務A只能讀取已提交的數據Read uncomitted
): 事務A能夠讀取到未提交的數據髒讀可重複讀幻讀串行化√√√不可重複讀√√×讀已提交√××讀未提交×××
Oracle提供3種隔離級別
讀已提交,串行化,只讀模式:只讀事務只能看到事務執行前就已經提交的數據,且事務中不能執行 insert
、 update
及 delete
語句。
爲了儘量數據庫的併發度,每次鎖定的數據範圍越小越好,理論上每次只鎖定當前操做的數據的方案會獲得最大的併發度,可是管理鎖是很耗資源的事情(涉及獲取,檢查,釋放鎖等操做),所以數據庫系統須要在高併發響應和系統性能兩方面進行平衡,這樣就產生了"鎖粒度( Lock granularity
)"的機率。
一種提升共享資源併發性的方式是讓鎖定對象更有選擇性。儘可能只鎖定須要修改的部分數據,而不是全部的資源。更理想的方式是,只對會修改的數據片進行精確的鎖定。任什麼時候候,在給定的資源上,鎖定的數據量越少,則系統的併發度越高,只要相互之間不發生衝突便可。
特色:偏向 MyISAM
存儲引擎,開銷小,加鎖快;無死鎖;鎖定粒度大,發生鎖衝突的機率最高,併發度最低。
案例1【加讀鎖】:
[session1] lock table user read; 這裏只能執行查詢當前表,不能查詢其餘表,插入或更新當前表都會提示錯誤 unlock tables; [session2] 在session1鎖定表後,session2能查詢或更新未鎖定的表,能查詢鎖定表,插入或者更新鎖定表會一直等待鎖被釋放。
案例1【加寫鎖】:
[session1] lock tables user write; 這裏能夠對鎖定表作查詢、更新、插入操做 unlock tables; [session2] 在session1鎖定表後,查詢、更新、插入操做均須要等到鎖被釋放。
結論:
MyISAM
表的讀操做(加讀鎖),不會阻塞其餘進程對同一表的讀請求,但會堵塞同一表的寫請求。只要當讀鎖釋放後,纔會執行其餘進程的寫操做。MyISAM
表的寫操做(加寫鎖),會阻塞其餘進程的對同一表的讀和寫操做,只有當寫鎖釋放後,纔會執行其它進程的讀寫操做。查看哪些表被加鎖: show open tables;
分析表鎖定: show status like 'table%';
Table_locks_immediate
:產生表級鎖定的次數,表示能夠當即獲取鎖的查詢次數,每當即獲取鎖值加1 ;
Table_locks_waited
:出現表級鎖定爭用而發生等待的次數(不能當即獲取鎖的次數,每等待一次鎖值加1),此值高則說明存在着較嚴重的表級鎖爭用狀況;
Myisam的讀寫鎖調度是讀優先,這也是myisam不適合作寫爲主表的引擎。由於寫鎖後,其餘線程不能作任何操做,大量的更新會使查詢很可貴到鎖,從而形成永遠阻塞
特色:
InnoDB
存儲引擎,開銷大,加鎖慢;鎖定粒度最小,發生鎖衝突的機率最低,併發度也最高。InnoDB
和 MyISAM
的最大不一樣有兩點:一是支持事務;二是採用了行級鎖。案例【加行鎖】
[session1] set autocommit=0; 這裏能夠對鎖定表作更新操做 commit; [session2] 在session2鎖定表後不commit時,這裏對鎖定表進行update操做,會等待鎖釋放。
無索引行鎖升級爲表鎖
當某個索引列沒有正常使用,如賦錯誤的類型的值,會致使行鎖變表鎖。
間隙鎖危害
間隙鎖:當咱們用範圍條件而不是相等條件檢索數據,並請求共享或拍他鎖時, InnoDB
會給符合條件的已有數據記錄的索引項加鎖;對於鍵值在條件範圍內但不存在的記錄,叫作"間隙( GAP
)", InnoDB
也會對這個"間隙"進行加鎖,這種鎖機制就是所謂的間隙鎖( Next-Key
)。
危害:當鎖定一個範圍鍵值以後,即便某些不存在的鍵值也會被無辜的鎖定,而形成在鎖定的時候沒法插入鎖定鍵值範圍內的任何數據,在某些場景下這可能會對性能形成很大的危害。
【面試題】 如何鎖定一行
select * from user for update;
結論:
Innodb
存儲引擎因爲實現了行級鎖定,雖然在鎖定機制的實現方面所帶來的的性能損耗可能比表級鎖定會要更高一些,可是總體併發處理能力方面要遠遠優於 MyISAM
的表級鎖定。當系統併發量較高的時候, InnoDB
的總體性能和 MyISAM
相比就有比較明顯的優點了。
可是 Innodb
的行級鎖定一樣也有脆弱的一面,當咱們使用不當的時候,可能會讓 Innodb
的總體性能表現不只不能比 MyISAM
高,甚至可能會更差。
分析行鎖定:
經過檢查 InnoDB_row_lock
狀態變量來分析系統上的行鎖的爭奪狀況
命令: mysql> show status like 'innodb_row_lock%';
Innodb_row_lock_current_waits
:當前正在等待鎖定的數量;
Innodb_row_lock_time
:從系統啓動到如今鎖定總時間長度;
Innodb_row_lock_time_avg
:每次等待所花平均時間;
Innodb_row_lock_time_max
:從系統啓動到如今等待最常的一次所花的時間;
Innodb_row_lock_waits
:系統啓動後到如今總共等待的次數;
優化建議
開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度通常。
select p1.Email from person p1 where p1.Email in (select p2.Email from person p2 where p1.Id!=p2.Id); [優]SELECT email FROM `person` group by email HAVING count(email)>1; [拓展]刪除重複數據 [思路]根據重複數據進行分組,而後查出最小的id,刪除其餘以外的id行,這裏得建立一個臨時表, 在mysql中,不能在一條Sql語句中,即查詢這些數據,同時修改這些數據 DELETE from person where id not in( select temp.id from (SELECT min(id) id FROM person group by email)as temp); 注意:這裏在mysql5.7以上版本會報錯,由於不支持select那些group by和聚合函數以外的字段
建立: create index idx_a_b on table(col_a,col_b);
查看: show index from table;
where 1=1
用於拼接多條件語句時,這樣就不用管條件是否存在,拼 where
仍是拼 and
。
where1=0
不返回數據,僅返回結構,用於快熟建表。
微信搜一搜 : 全棧小劉 ,獲取文章 pdf 版本