MySQL服務端採用線程池維護客戶端鏈接mysql
分析查詢語句,生成解析樹,並將解析結果放入緩存中sql
優化包括選擇合適的索引,數據的讀取方式,分析語句執行的開銷以及統計信息,優化器能夠和存儲引擎直接交互,儘管看起來彷佛沒必要要。數據庫
執行查詢語句,返回結果緩存
緩存SQL解析器解析後的結果bash
粒度服務器
死鎖的簡單例子:兩個transaction同時開始執行,它們分別開始執行第一條update的語句時,便鎖住了對方的資源,你拿着個人資源不放,我拿着你的資源不放,最後二人都僵持着,當事人事不關己高高掛起,旁觀者疾呼:死鎖!微信
# transaction 1 START TRANSACTION; UPDATE USER SET NAME='Bob' WHERE ID=1; # sleep for some time; UPDATE USER SET NAME='Jack' WHERE ID=2; COMMIT;
# transaction 2 START TRANSACTION; UPDATE USER SET NAME='Bob' WHERE ID=2; # sleep for some time UPDATE USER SET NAME='Jack' WHERE ID=1; COMMIT;
隱式鎖定就是系統自動加鎖而不是人爲的添加鎖,顯示鎖定就是人爲的添加鎖,好比lock tables或者unlock tables。架構
事務的特色由存儲引擎決定,是MySQL與其它數據庫的不一樣。
不支持事務的存儲引擎有:併發
MySQL中的表按是否支持事務,分爲:事務型表和非事務型表。
非事務型表沒有commit或者rollback的概念。dom
SET AUTOCOMMIT=OFF;
或者
SET AUTOCOMMIT=0;
能設置當前鏈接是不是自動提交的。不過對非事務型表沒有做用。
ACID屬性
隔離級別
查詢和設置隔離級別:
# 查詢系統默認隔離級別,當前會話隔離級別 select @@global.tx_isolation,@@tx_isolation; # 設置系統隔離級別: SET global transaction isolation level read committed; # 設置會話隔離級別: SET SESSION transaction isolation LEVEL read committed;
複製意味着一份數據能夠有多個副本,一個數據庫中的數據,能夠複製至另外一個數據庫。
複製在咱們的生活中無處不在,同一份數據,有可能在你我的的電腦上有一份,U盤上有一份,雲端的網盤上也可能會有一份。甚至在我的電腦裏,一樣一份數據也會有多個副本。
這裏,咱們之因此會將數據複製出多份,目的是顯而易見的:備份。
當你抱着本身的電腦準備接上投影儀,準備向老闆展現你苦戰數個通宵後的PPT時,硬盤忽然壞了,或者文件誤刪,莫名其妙的找不到了,不要緊,你的U盤還有一份。什麼!U盤忘了帶了?不要緊,你的網盤裏還有一個。
複製與備份的是兩件不一樣的事情,能夠經過複製來實現備份的目的。可是,複製的卻不僅是能提供備份而已。
在MySQL中,複製能夠解決幾個問題:
若是大家公司的數據中心位於全國各地,經過複製,能夠實現異地備份,但異地的數據同步會有較大的時間延遲。
同時,若是主數據庫的數據都同步複製至從庫,那麼當須要更新數據時,只須要更新主庫便可,新更新的數據將會經過主庫同步至從庫,在這個基礎上,即可以實現讀寫分離,即DML語句在主庫上執行,而查詢類SQL語句則在從庫上執行,因爲主從的同步有時延,所以這裏的數據一致性模型並不知足強一致性,是最終一致性模型。
由於有了主從副本,因此當主庫不可用(宕機,崩潰等緣由),從庫能夠臨危受命,升級爲主庫,保證數據庫服務的高可用性。
分爲3個步驟
主庫在每次事務準備提交前,按照事務的提交順序,將更新事件記錄到binary log中,並通知存儲引擎提交事務。而後,從庫會主動啓動一個線程與主庫創建鏈接,與此對應,主庫會啓動一個二進制轉儲(binlog dump)線程與之合做,將binary log發送給從庫,從庫接收併產生relay log,而後由從庫的一個SQL線程負責將relay log還原爲數據。
須要注意的是,從庫在relay時,是單線程執行,換言之,串行執行的。
經過在my.cnf中添加一個配置項log-bin,來起用master的二進制日誌記錄功能,若是沒有配置log-bin,那麼master的二進制記錄功能並不會起用,log-bin在這裏有兩個做用
另外,須要在my.cnf中添加一個server-id配置項,用來指定master的惟一ID,範圍能夠是1到2^32-1。
[mysqld] # Replication Configurations(by beanlam) server-id=1 log-bin=bin-log
配置完成後須要重啓mysql server。
一樣,slave也須要配置一個惟一的server-id,不容許跟master的server-id衝突,若是有多個slave,各個slave與master的server-id都應該是不一樣的。
slave也能夠配置log-bin,配置了之後slave也能夠和master同樣,記錄binary log。slave記錄binary log有其用武之地的,好比數據備份和崩潰恢復,若當前的replication環境拓撲結構比較複雜,slave須要做爲其它mysql server的master時,那麼這個slave也必須啓用binary log的功能。
[mysqld] # Replication Configurations(by beanlam) server-id=2
slave獲取master的binary log時,經過用戶名和密碼與master創建鏈接,能夠建立一個專用於複製的帳號,並只賦予這個帳號與複製有關的權限。
mysql> CREATE USER 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass'; mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%.mydomain.com';
除了REPLICATION SLAVE權限,還能夠給用戶受權REPLICATION CLIENT權限,這樣用戶就能夠用來監控和管理複製。
slave必須事先了解從master的二進制文件的哪一個位置開始複製,所以須要先記錄master當前二進制日誌的座標,座標由文件名和偏移量決定。
得到master的二進制日誌座標,須要先保證沒有寫操做在進行。在master上執行如下語句:
mysql> FLUSH TABLES WITH READ LOCK;
這個語句能爲表得到讀鎖,阻止其它寫入操做。須要注意,執行這個語句的會話若是關閉,那麼這個鎖將會被釋放,若是會話沒有關閉,那麼鎖會一直持有。
在另外一個會話裏,用如下語句來查看master的二進制日誌座標
mysql> show master status; +----------------+----------+-------------------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +----------------+----------+-------------------------+------------------+-------------------+ | bin-log.000005 | 1264 | beanlam_db1,beanlam_db2 | | | +----------------+----------+-------------------------+------------------+-------------------+ 1 row in set (0.00 sec)
File和Position即代表了slave應該從何處開始進行復制。
若是master以前沒有啓用過二進制日誌的功能,那麼show master status
查詢結果將爲空。這時對於slave來講,File是一個空字符串,Position是4,之因此是4,與二進制日誌的文件格式有關。
根據以上步驟,獲得了master二進制文件的座標後,只須要告訴slave,slave即可以埋頭進入複製的狀態中。
這裏根據master是否有舊數據須要同步,分爲兩種狀況:
若是master是一個新的數據庫服務器,其上沒有任何舊的數據須要複製,那麼就可使用change master to
命令爲slave配置master的信息。
CHANGE MASTER TO MASTER_HOST='master_host_name', MASTER_USER='replication_user_name', MASTER_PASSWORD='replication_password', MASTER_LOG_FILE='recorded_log_file_name', MASTER_LOG_POS=recorded_log_position;
配置完後,能夠經過start slave
命令正式開始進行復制。
能夠經過mysqldump工具對當前master的數據庫數據作一個快照,生成一個dump文件,在slave開始複製以前,把這個文件的數據導入slave中。
基本的使用方法:
mysqldump --all-databases --master-data > dbdump.db
-all-databases
代表爲全部數據庫做快照,也能夠用--databases
來制定須要作快照的數據庫。--ignore-table
能夠跳過數據庫中的全部表--master-data
會自動地在dump文件里加上change master to
語句,啓動slave複製,若是不加這個選項,則須要先開啓一個新的會話,對全部的表加讀。
當存儲引擎是InnoDB時,推薦使用mysqldump。
另一種方法是直接拷貝數據文件到slave。
基於語句的複製也稱爲(邏輯複製),slave把master上形成數據更改的SQL語句在本身的庫上也執行一次。
master的binlog只記錄SQL語句,使得日誌文件體積更小。
master除了傳輸SQL語句給slave,還須要傳輸一些元數據,好比當前時間戳。
還有一些語句沒法被正確複製,好比包含用戶自定義函數的語句,這些函數可能有不肯定的行爲。如下函數可能致使非正常的複製:
LOAD_FILE(), UUID(), UUID_SHORT(), USER(), FOUND_ROWS(), SYSDATE(), GET_LOCK(), IS_FREE_LOCK(), IS_USED_LOCK, MASTER_POS_WAIT, RAND(), RELEASE_LOCK(), SLEEP(), VERSION()
此外,INSERT......SELECT
語句須要獲取更多的行級鎖,比起基於行的複製來講。UPDATE
語句可能致使全表掃描(where字句中沒有包含索引字段)
若是使用的是InnoDB引擎,帶有auto_increment
的insert
語句會堵塞其它非衝突的insert
語句。
slave上的更新是串行的,所以須要更多的鎖。另外,並非全部的存儲引擎都支持基於語句的複製。
MySQL5.1開始支持基於行的複製
更少的鎖
對於某些語句,例如插入或者刪除語句,基於行的複製方式會將整行的數據都寫進binary log,致使binary log體積很大,也致使須要持有鎖的時間變長。
若是包含用戶自定義函數,這些函數輸出值很是大的文本,那麼採起行的複製,會把這麼大的文本也寫進日誌裏。
在slave端看不到執行了哪些SQL語句
當使用MyISAM引擎時,insert
語句須要得到重量級的鎖,這意味着插入操做只能是串行的。
若是slave配置了log_slave_updates選項,slave也會像master同樣記錄binary log,從而能夠做爲一個master存在。
被動服務器時只讀的(日誌裏記錄的事件都帶有一個server id,發現server id與本身的相同,則忽略這個事件)
很是脆弱,其中一個節點失效會致使由這個節點發起的事件在其它節點之間鏈式死循環,由於只有它本身能過濾掉與本身server id相同的事件。
改進:
主要用在當多個備庫執行復制請求時,致使主庫負載太高時,能夠引進分發庫來減小主庫的負載。
故障處理過程更加複雜
mysql5.6 ref
mysql5.7 ref
《高性能MySQL》 3rd Edition