本文目錄一覽:
- 1、一文總結高並發大數據量下MySQL開發規範「軍規」
- 2、mysql資料庫
- 3、淺談mysql資料庫分庫分表那些事-億級數據存儲方案
- 4、mysql資料庫事件調用有錯誤日誌記錄嗎
- 5、一文詳解-MySQL 事務和鎖
一文總結高並發大數據量下MySQL開發規範「軍規」
在互聯網公司中,MySQL是使用最多的資料庫,那麼在並發量大、數據量大的互聯網業務中,如果高效的使用MySQL才能保證服務的穩定呢?根據本人多年運維管理經驗的總結,梳理了一些核心的開發規範,希望能給大家帶來一些幫助。
一、基礎規範
二、庫表設計
問題:使用VARCHAR(5) 和VARCHAR(200) 存儲』hello』的磁碟空間開銷是一樣的,使用更短的列表有什麼優勢嗎?
更大的定義列會消耗更多的內存,因為MySQL通常會分配固定大小的內存塊來保存內部值,尤其是使用內存臨時表進行排序或操作時會特別糟糕
三、索引設計
基本規則:索引不是越多越好,能不添加的索引盡量不要添加,過多的索引會嚴重降低數據插入和更新的效率,並帶來更多的讀寫衝突和死鎖!
示例:假設在表tab中id建立了索引
四、SQL優化
示例:
欄位: code varchar(50) NOT NULL COMENT 『編碼』 #code上建立了索引
SELECT id,name,addr from tab_name where code=10001; 不會使用索引
SELECT id,name,addr from tab_name where code=’10001′; 會使用索引
Select * from table limit 10000,10;
LIMIT原理:
Limit 10000,10 偏移量越大則越慢
Select * from table WHERE id=23423 limit 11; #10+1 (每頁10條)
Select * from table WHERE id=23434 limit 11;
Select * from table WHERE id = ( select id from table limit 10000,1 ) limit 10;
Select * from table INNER JOIN (SELECT id from table limit 10000,10) USING(id)
最後說明:
上述規範是多年MySQL資料庫使用的經驗總結,希望能給大家帶來一些啟發和幫助!
mysql資料庫
MySQL資料庫一般指MySQL,MySQL是一個關係型資料庫管理系統,由瑞典MySQL AB 公司開發。
mysql是目前網站以及APP應用上用得較多的一個開源的關係型資料庫系統,可以對數據進行保存,分段化的數據保存,也可以對其數據進行檢索,查詢等功能的資料庫。
默認的mysql資料庫中存有一個庫這個就是mysql的系統資料庫,可以對其保存系統的數據包括mysql資料庫的信息,資料庫root賬號,普通賬號,以及資料庫的名稱,還有資料庫的一些表還有一些數字型的數據類型結構都會有所保存。
mysql資料庫的優點
(1)MySQL資料庫是用C和C++語言編寫的,並且使用了多種編輯器進行測試,以保證源碼的可移植性。
(2)支持多個操作系統例如:Windows、Linux、Mac OS等等。
(3)支持多線程,可以充分的利用CPU資源。
(4)為多種編程語言提供API,包括C語言、Java、PHP、Python語言等。
(5)MySQL優化了SQL演算法,有效的提高了查詢速度。
(6)MySQL內提供了用於管理,檢查以及優化資料庫操作的管理工具。
(7)它能夠作為一個單獨的應用程序應用在客戶端伺服器網路環境中,也可以作為一個庫嵌入到其他的軟體中並提供多種語言支持。
淺談mysql資料庫分庫分表那些事-億級數據存儲方案
mysql分庫分表一般有如下場景
其中1,2相對較容易實現,本文重點講講水平拆表和水平拆庫,以及基於mybatis插件方式實現水平拆分方案落地。
在 《聊一聊擴展欄位設計》 一文中有講解到基於KV水平存儲擴展欄位方案,這就是非常典型的可以水平分表的場景。主表和kv表是一對N關係,隨著主表數據量增長,KV表最大N倍線性增長。
這裡我們以分KV表水平拆分為場景
對於kv擴展欄位查詢,只會根據id + key 或者 id 為條件的方式查詢,所以這裡我們可以按照id 分片即可
分512張表(實際場景具體分多少表還得根據欄位增加的頻次而定)
分表後表名為kv_000 ~ kv_511
id % 512 = 1 …. 分到 kv_001,
id % 512 = 2 …. 分到 kv_002
依次類推!
水平分表相對比較容易,後面會講到基於mybatis插件實現方案
場景:以下我們基於博客文章表分庫場景來分析
目標:
表結構如下(節選部分欄位):
按照user_id sharding
假如分1024個庫,按照user_id % 1024 hash
user_id % 1024 = 1 分到db_001庫
user_id % 1024 = 2 分到db_002庫
依次類推
目前是2個節點,假如後期達到瓶頸,我們可以增加至4個節點
最多可以增加只1024個節點,性能線性增長
對於水平分表/分庫後,非shardingKey查詢首先得考慮到
基於mybatis分庫分表,一般常用的一種是基於spring AOP方式, 另外一種基於mybatis插件。其實兩種方式思路差不多。
為了比較直觀解決這個問題,我分別在Executor 和StatementHandler階段2個攔截器
實現動態數據源獲取介面
測試結果如下
由此可知,我們需要在Executor階段 切換數據源
對於分庫:
原始sql:
目標sql:
其中定義了三個註解
@useMaster 是否強制讀主
@shardingBy 分片標識
@DB 定義邏輯表名 庫名以及分片策略
1)編寫entity
Insert
select
以上順利實現mysql分庫,同樣的道理實現同時分庫分表也很容易實現。
此插件具體實現方案已開源:
目錄如下:
mysql分庫分表,首先得找到瓶頸在哪裡(IO or CPU),是分庫還是分表,分多少?不能為了分庫分表而拆分。
原則上是盡量先垂直拆分 後 水平拆分。
以上基於mybatis插件分庫分表是一種實現思路,還有很多不完善的地方,
例如:
mysql資料庫事件調用有錯誤日誌記錄嗎
一.錯誤日誌
錯誤日誌在Mysql資料庫中很重要,它記錄著mysqld啟動和停止,以及伺服器在運行過程中發生的任何錯誤的相關信息。
1.配置信息
–log-error=[file-name]用來指定錯誤日誌存放的位置。
如果沒有指定[file-name],默認hostname.err做為文件名,默認存放在DATADIR目錄中。
也可以將log-error配置到my.cnf文件中,這樣就省去了每次在啟動mysqld時都手工指定–log-error.例如:
[mysql@test2]$ vi /etc/my.cnf
# The MySQL server
[mysqld]
….
一文詳解-MySQL 事務和鎖
當多個用戶訪問同一份數據時,一個用戶在更改數據的過程中,可能有其他用戶同時發起更改請求,為保證資料庫記錄的更新從一個一致性狀態變為另外一個一致性狀態,使用事務處理是非常必要的,事務具有以下四個特性:
MySQL 提供了多種事務型存儲引擎,如 InnoDB 和 BDB 等,而 MyISAM 不支持事務。為了支持事務,InnoDB 存儲引擎引入了與事務處理相關的 REDO 日誌和 UNDO 日誌,同時事務依賴於 MySQL 提供的鎖機制
事務執行時需要將執行的事務日誌寫入日誌文件,對應的文件為 REDO 日誌。當每條 SQL 進行數據更新操作時,首先將 REDO 日誌寫進日誌緩衝區。當客戶端執行 COMMIT 命令提交時,日誌緩衝區的內容將被刷新到磁碟,日誌緩衝區的刷新方式或者時間間隔可以通過參數 innodb_flush_log_at_trx_commit 控制
REDO 日誌對應磁碟上的 ib_logifleN 文件,該文件默認為 5MB,建議設置為 512MB,以便容納較大的事務。MySQL 崩潰恢復時會重新執行 REDO 日誌的記錄,恢復最新數據,保證已提交事務的持久性
與 REDO 日誌相反,UNDO 日誌主要用於事務異常時的數據回滾,具體內容就是記錄數據被修改前的信息到 UNDO 緩衝區,然後在合適的時間將內容刷新到磁碟
假如由於系統錯誤或者 rollback 操作而導致事務回滾,可以根據 undo 日誌回滾到沒修改前的狀態,保證未提交事務的原子性
與 REDO 日誌不同的是,磁碟上不存在單獨的 UNDO 日誌文件,所有的 UNDO 日誌均存在表空間對應的 .ibd 數據文件中,即使 MySQL 服務啟動了獨立表空間
在 MySQL 中,可以使用 BEGIN 開始事務,使用 COMMIT 結束事務,中間可以使用 ROLLBACK 回滾事務。MySQL 通過 SET AUTOCOMMIT、START TRANSACTION、COMMIT 和 ROLLBACK 等語句支持本地事務
MySQL 定義了四種隔離級別,指定事務中哪些數據改變其他事務可見、哪些數據該表其他事務不可見。低級別的隔離級別可以支持更高的並發處理,同時佔用的系統資源更少
InnoDB 系統級事務隔離級別可以使用以下語句設置:
查看系統級事務隔離級別:
InnoDB 會話級事務隔離級別可以使用以下語句設置:
查看會話級事務隔離級別:
在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。讀取未提交的數據稱為臟讀(Dirty Read),即是:首先開啟 A 和 B 兩個事務,在 B 事務更新但未提交之前,A 事務讀取到了更新後的數據,但由於 B 事務回滾,導致 A 事務出現了臟讀現象
所有事務只能看見已經提交事務所做的改變,此級別可以解決臟讀,但也會導致不可重複讀(Nonrepeatable Read):首先開啟 A 和 B 兩個事務,A事務讀取了 B 事務的數據,在 B 事務更新並提交後,A 事務又讀取到了更新後的數據,此時就出現了同一 A 事務中的查詢出現了不同的查詢結果
MySQL 默認的事務隔離級別,能確保同一事務的多個實例在並發讀取數據時看到同樣的數據行,理論上會導致一個問題,幻讀(Phontom Read)。例如,第一個事務對一個表中的數據做了修改,這種修改會涉及表中的全部數據行,同時第二個事務也修改這個表中的數據,這次的修改是向表中插入一行新數據,此時就會發生操作第一個事務的用戶發現表中還有沒有修改的數據行
InnoDB 通過多版本並發控制機制(MVCC)解決了該問題:InnoDB 通過為每個數據行增加兩個隱含值的方式來實現,這兩個隱含值記錄了行的創建時間、過期時間以及每一行存儲時間發生時的系統版本號,每個查詢根據事務的版本號來查詢結果
通過強制事務排序,使其不可能相互衝突,從而解決幻讀問題。簡而言之,就是在每個讀的數據行上加上共享鎖實現,這個級別會導致大量的超時現象和鎖競爭,一般不推薦使用
為了解決資料庫並發控制問題,如走到同一時刻客戶端對同一張表做更新或者查詢操作,需要對並發操作進行控制,因此產生了鎖
共享鎖的粒度是行或者元組(多個行),一個事務獲取了共享鎖以後,可以對鎖定範圍內的數據執行讀操作
排他鎖的粒度與共享鎖相同,一個事務獲取排他鎖以後,可以對鎖定範圍內的數據執行寫操作
有兩個事務 A 和 B,如果事務 A 獲取了一個元組的共享鎖,事務 B 還可以立即獲取這個元組的共享鎖,但不能獲取這個元組的排他鎖,必須等到事務 A 釋放共享鎖之後。如果事務 A 獲取了一個元組的排他鎖,事務 B 不能立即獲取這個元組的共享鎖,也不能立即獲取這個元組的排他鎖,必須等到 A 釋放排他鎖之後
意向鎖是一種表鎖,鎖定的粒度是整張表,分為意向共享鎖和意向排他鎖。意向共享鎖表示一個事務有意對數據上共享鎖或者排他鎖。有意表示事務想執行操作但還沒真正執行
鎖的粒度主要分為表鎖和行鎖
表鎖的開銷最小,同時允許的並發量也是最小。MyISAM 存儲引擎使用該鎖機制。當要寫入數據時,整個表記錄被鎖,此時其他讀/寫動作一律等待。一些特定的動作,如 ALTER TABLE 執行時使用的也是表鎖
行鎖可以支持最大的並發,InnoDB 存儲引擎使用該鎖機制。如果要支持並發讀/寫,建議採用 InnoDB 存儲引擎
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/288941.html