查詢緩存:
如何判斷是否命中:
通過查詢語句的哈希值判斷:哈希值考慮的因素包括
查詢本身、要查詢的數據庫、客戶端使用協議版本,...
查詢語句任何字符上的不同,都會導致緩存不能命中;
哪此查詢可能不會被緩存?
查詢中包含UDF、存儲函數、用戶自定義變量、臨時表、mysql庫中系統表、或者包含列級權限的表、有着不確定值的函數(Now());
查詢緩存相關的服務器變量:
query_cache_min_res_unit: 查詢緩存中內存塊的最小分配單位;
較小值會減少浪費,但會導致更頻繁的內存分配操作;
較大值會帶來浪費,會導致碎片過多;
query_cache_limit:能夠緩存的最大查詢結果;
對於有着較大結果的查詢語句,建議在SELECT中使用SQL_NO_CACHE
query_cache_size:查詢緩存總共可用的內存空間;單位是字節,必須是1024的整數倍;
query_cache_type:ON, OFF, DEMAND
query_cache_wlock_invalidate:如果某表被其它的連接鎖定,是否仍然可以從查詢緩存中返回結果;默認值爲OFF,表示可以在表被其它連接淘寶的場景中繼續從緩存返回數據;ON則表示不允許;
查詢相關的狀態變量
SHOWGLOBAL STATUS LIKE 'Qcache%';
+-------------------------+----------+
|Variable_name | Value |
+-------------------------+----------+
|Qcache_free_blocks | 1 |
|Qcache_free_memory | 16759688 |
|Qcache_hits | 0 |
|Qcache_inserts | 0 |
|Qcache_lowmem_prunes | 0 |
|Qcache_not_cached | 0 |
|Qcache_queries_in_cache | 0 |
|Qcache_total_blocks | 1 |
+-------------------------+----------+
緩存命中率的評估:Qcache_hits/(Qcache_hits+Com_select)
查詢mysql運行時全局變量
例:查詢與緩存有關的去全局變量
showglobal variables like '%query%'
select@@query_cache_type;
關閉緩存
set query_cache_type=off;
MySQL日誌:
是否啓用二進制日誌
sql_log_bin=on
二進制日誌保存位置
log-bin=二進制日誌保存位置
show binary logs;
查看二進制日誌
showbinlog events in 'mysql-bin.000001'\G
二進制日誌文件的位置:
二進制日誌保存格式
binlog_format=mixed混合|statement基於語句|row基於行
是否啓用二進制日誌
sql_log_bin=on
設置單個二進制日誌文件大小上限
max_binlog_size=1073741824 [最下4k最大1G]
設置二進制日誌緩存文件大小
max_binlog_cache_size=18446744073709547520[這個值不能大於max_binlog_stmt_cache_size]
max_binlog_stmt_cache_size=18446744073709547520
設置多久同步一次二進制日誌文件,0表示不同步,任何正值都表示記錄多少個語句後同步一次
sync_binlog=0
二進制日誌的格式
[root@1GPC~]# mysqlbinlog mysql-bin.000001
MySQL的備份和恢復
注意的要點
1.可容忍丟失多少數據
2.需要恢復什麼
3.持鎖時長
4.備份過程時長
5.備份時cpu的負載
6.恢復過程時長
備份類型:
完全備份,部分備份:僅備份其中的一張表或多張表
完全備份,增量備份:僅備份從上次完全備份或增量備份之後變化的數據部分
熱備份、溫備份、冷備份
熱備份:在線備份,讀寫不受影響
溫備份:在線備份,讀可進行,寫不允許
冷備份:離線備份,數據庫服務器離線,備份期間不能爲業務提供讀寫服務
MyISAM:溫備份
InnoDB:熱備份
物理備份和邏輯備份
物理備份:直接複製數據文件進行的備份。
優點:基於文件進行備份的,可以直接複製。恢復數據快。
缺點:和存儲引擎有關,MyISAM導出的數據不能導入到InnoDB中。不能跨OS。
邏輯備份:從數據庫中"導出"數據另存而進行的備份。
優點:可以通過修改sql語句進行二次加工,與存儲引擎無關,可以導入到任何存儲引擎中;
缺點:無法保證數據導出和在導入或一致性,因爲浮點數會取近似值。索引需重建
設計備份方案:
備份數據、二進制日誌、InnoDB事務日誌等日誌數據、代碼(存儲過程和存儲函數、觸發器、時間調度器等)、服務器配置文件
完全備份+增量備份
建議完全備份1週一次,1天一次增量備份
使用mysqldump做完全備份,通過備份二進制日誌實現增量備份
lvm2快照:幾乎熱備,用cp,tar做完全備份,通過備份二進制日誌實現增量備份
xtrabackup:物理備份
對InnoDB:熱備份,支持完全備份和增量備份
其他存儲引擎:溫備份
備份工具:
mysqldump:邏輯備份工具,支持完全備份和部分備份,不支持增量備份,若要支持需備份二進制日誌,對其他存儲引擎溫備份,InnoDB熱備份
C/S架構,mysqldump是Client,mysqld是SERver
-A:備份所有數據庫例:mysqldump -A -uroot -hlocalhost -x -p > /tmp/all.sql
要用 -x 鎖定所要備份表或用 -l 鎖定備份的表[會導致數據不一致,最好不要使用]
--single-transaction:表示啓動一個單一事務實現備份,可以實現鎖定備份的表
-B:指定備份哪個數據庫例:mysqldump -uroot -hlocalhost -x -B test -p > /tmp/test.sql
使用-B和不使用-B直接備份數據庫是有區別的,-B會自動添加create database 數據庫這條語句,不使用則需恢復時自檢創建數據庫
備份表:mysqldump -uroot -hlocalhost mysql user -p > /tmp/mysql.test
-C:壓縮傳輸,但會大量佔用Server的CPU
-E:備份指定數據庫的事件調度器
-R:備份存儲過程和存儲函數
--triggers:備份觸發器
--master-data[=#]
0 表示不記錄
1 記錄CHANGE MASTERTO語句,此語句未被註釋
2 記錄CHANGE MASTERTO語句,此語句被註釋
例:mysqldump --master-data=2 --lock-all-tables -A > /tmp/all.1.sql
-F:鎖定表後執行flushlogs命令
案例:每週日完全備份,每週一到週五增量備份
二進制日誌文件與數據文件不應放在同一磁盤上
例 hellodb單個數據庫:在crontable中設計週期任務
完全備份:mysqldump -B tpweb --flush-logs --lock-all-tables --master-data=2 -uroot -hlocalhost -p > /tmp/tpweb-`date +%F`.sql
在這個sql文件中會看見
第22行表示備份後的所有的更改將會保存在mysql-bin.000003二進制文件中
增量備份:基於二進制日誌文件進行備份
mysqladmin-uroot -p flush-logs
這時將會產生一個新的二進制日誌文件mysql-bin.000004,mysql-bin.000003二進制文則會保存自上次備份後到現在的所有更改,只需把這個文件備份到安全的位置即可
mysqlbinlog /data/mysql-bin.000003 > /tmp/mysql-bin.000003
恢復備份:
mysql> SET SESSION sql_log_bin=0;關閉還原時產生的二進制日誌
mysql> SOURCE /tmp/tpweb-2015-06-16.sql
…
mysql> SET SESSION sql_log_bin=1;恢復完成後開啓二進制日誌
不然就只能去編輯配置文件去關閉二進制日誌,用命令行還原
1.恢復完全備份
mysql -uroot -hlocalhost -p < /tmp/tpweb-2015-06-16.sql
2.恢復增量備份
mysql -uroot -hlocalhost -p < /tmp/mysql-bin.000003
當數據未備份卻進行了誤操作,可通過二進制日誌進行恢復
例:誤刪除了數據庫
1.備份二進制日誌文件到安全的位置上
mysqlbinlog /data/mysql-bin.000003 > /tmp/mysql-bin.000003
2.用vimmysql-bin.000003
找到最近一次的誤操作並刪除,並用mysql -uroot -hlocalhost -p < /tmp/mysql-bin.000003恢復
或
1.先用mysqlbinlog/data/mysql-bin.000003看下誤操作的position 即at 後面的數字
mysqlbinlog --stop-position 7295 /data/mysql-bin.000003 > /tmp/mysql-bin.000003
2.mysql -uroot -hlocalhost-p < /tmp/mysql-bin.000003
cp,tar等文件系統工具:物理備份工具,冷備份,一般用於MyISAM備份,支持完全備份和部分備份
lvm2快照:幾乎熱備份,藉助cp,tar等文件系統工具實現物理備份,需備份事務日誌
ibbackup:對於InnoDB支持熱備份,需向IBM繳費
xtrbackup:對InnoDB熱備份,支持完全和增量備份
對MyISAM溫備份,只支持完全備份
官網下載percona-xtrabackup-2.2.3-4982.el6.x86_64.rpm
yum install yum install perl-DBD-MySQL
yuminstall percona-xtrabackup-2.2.3-4982.el6.x86_64.rpm
MySQL複製
複製功用
數據分佈、負載均衡、備份、高可用和故障切換、MySQL升級測試,
要想實現複製,需在主節點開啓二進制日誌
主從複製:
從服務器:
I/O線程:從master請求二進制日誌信息,並保存至slave中繼日誌
SQL線程:從[relay log]中繼日誌中讀取日誌信息,在本地完成重放
默認工作在異步[async]模式
存在的問題:
1.主從數據不一致
2.從服務器數據落後主服務器
雙主模型:
讀:負載均衡
寫:都要寫入,無法均衡
複製時應注意的問題
1.主節點運行很久後要加入從節點
在主節點上做一個完全備份,並記錄二進制日誌文件及position位置
在從節點恢復此完全備份,並在啓動複製是從記錄的二進制日誌文件position位置開始
2.如何限制從服務器只讀
在從服務器啓動read_only:但僅對非具有SUPER權限的用戶有效
阻止所有用戶:MariaDB> flush tables with read lock
3.如何保證主從複製時事務安全
在master節點上啓用參數:
sync_binlog=on
若用到的爲InnoDB存儲引擎:
啓用Innodb_flush_logs_at_trx_commit 表示一旦提交了事務立即同步到磁盤上
Innodb_support_xa=on
在slave節點上:
skip_slave_start=on 表示跳過slave自動啓動
主節點在不考慮磁盤IO的情況下:
snyc_master_info=1
從節點在不考慮磁盤IO的情況下:
snyc_master_info=1
snyc_relay_log=1
sync_relay_log_info=1
3.爲了避免從服務器數據落後主服務器,可以使用半同步複製
主節點:
安裝插件,文件在/usr/local/mysql/lib/plugin下
MariaDB> install plugin rpl_semi_sync_master soname'semisync_master.so'
show global variables like '%semi%'可以查看安裝後semisync的狀態
編輯配置文件:
rpl_semi_sync_master_enabled =on 開啓半同步
rpl_semi_sync_master_timeout=2000 超時時間設爲2000毫秒
從節點:
安裝插件
MariaDB> install plugin rpl_semi_sync_slave soname'semisync_slave.so'
show global variables like '%semi%'可以查看安裝後semisync的狀態
編輯配置文件:
rpl_semi_sync_slave_enabled =on 開啓半同步
重啓slave線程
stop slave io_thread;
start slave io_thread;
使用show global status like '%semi%' 查看狀態是否啓動
4.複製過濾器,不復制所有數據庫,只複製指定的數據庫
(1)主服務器僅向二進制日誌中記錄有特定數據庫相關的寫操作
問題:即時點還原將無法實現
binlog_do_db = 數據庫白名單
binlog_ignore_db = 數據庫黑名單
(2)從服務器的SQL_THREAD僅在中繼日誌中讀取特定數據相關的語句並應用在本地
問題:會造成網絡帶寬和磁盤IO的浪費
Replicate_Do_DB: 數據庫白名單
Replicate_Ignore_DB: 數據庫黑名單
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table: 用通配符匹配
Replicate_Wild_Ignore_Table:
例:
先stop slave;
set global Replicate_Do_DB=tpweb;
在start slave;
5.基於SSL的複製
前提:支持SSL
用show global variables like '%ssl%';查看ssl狀態,在編譯時指定開啓ssl
MariaDB[(none)]> show global variables like '%ssl%';
+---------------+----------+
|Variable_name | Value |
+---------------+----------+
| have_openssl |ENABLED |
| have_ssl | ENABLED |
| ssl_ca | ca證書路徑 |
| ssl_capath | 一堆ca證書路徑 |
| ssl_cert | ca給自己發的證書 |
| ssl_cipher | 加密算法 |
| ssl_key | 私鑰 |
+---------------+----------+
(1) 主服務器配置證書和私鑰,並創建一個要求必須使用SSL連接的複製賬號(使用REQUIRE SSL)
(2)SLAVE端連接MASTER時,使用MASTER_SSL相關的選項來配置證書等信息
6.跟複製有關的文件
在從節點上的master.info用來保存主從連接時的相關信息,如賬號,密碼…
relay-log.info:保存了當前slave節點上已經複製的當前二進制日誌和本地中繼日誌的對應關係,即position位置
7.複製的監控和維護
(1)清理日誌:使用PURGE
(2)監控複製:
show master status
show binlog events
show binary logs
show slave status
(3)如何判斷slave是否落後於master
用show slave status中的Seconds_Behind_Master: NULL來觀察
(4)如何確定主從節點數據是否一致
①在創建表時啓用checksum,之後可以通過show table status查看主從節點同一張表的checksum是否一致
②使用percona-tools中的pt-table-checksum
(5)數據不一致時的修復方法:
重新複製master節點的數據,重新同步
配置MySQL主從:
例:172.16.37.20做主節點,172.16.37.21做從節點
master:
1.啓用二進制日誌
2.設置一個在當前集羣中唯一的server-id
3.創建一個有複製權限[REPLICATIONSLAVE,REPLICATION CLIENT]的賬號
在mysql命令行中執行
MariaDB [(none)]> grant replicationclient,replication slave on *.* to 'testuser'@'172.16.%.%' identified by'123456';
slave:
1.啓動中繼日誌,註釋二進制日誌
2.設置一個在當前集羣中唯一的server-id
3.不允許client寫入操作
4.利用有複製權限的用戶賬號連接至主服務器,並啓動複製線程
MariaDB [(none)]> change master tomaster_host='172.16.37.20',master_user='testuser',master_password='123456',master_log_file='master-bin.000001',master_log_pos=419,master_connect_retry=5,master_heartbeat_period=2;
master_connect_retry=5:表示每5s重連一次
master_heartbeat_period=2:表示每2s探測一次master的健康狀態
在master中查出master_log_pos的值;
5.用show slavestatus查看slave狀態,並用startslave;啓動線程
MariaDB[(none)]> show slave status\G
***************************1. row ***************************
Slave_IO_State:
Master_Host: 172.16.37.21
Master_User: testuser
Master_Port: 3306
Connect_Retry: 5
Master_Log_File:master-bin.000001
Read_Master_Log_Pos: 419
Relay_Log_File:mysql-relay.000001
Relay_Log_Pos: 4
Relay_Master_Log_File:master-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 419
Relay_Log_Space: 245
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert:No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 0
測試:在master創建數據庫,在slave上查看是否複製成功
雙主模型:
互爲主從:
1.數據可能不一致;
2.id有auto_increment定義一個節點使用基數id,另一節點使用偶數id,但會產生id不連貫
用show global variables like '%increment%';查看偏移量
auto_increment_offset 表示從幾開始
auto_increment_increment表示一次增加幾
定義一個節點使用基數id
set @@auto_increment_offset=1;
set @@auto_increment_increment=2;
定義一個節點使用偶數id
set @@auto_increment_offset=2;
set @@auto_increment_increment=2;
配置:
1.各自使用不同的server-id
172.16.37.20:
172.16.37.21:
2.都啓用二進制日誌和中繼日誌
172.16.37.20:
172.16.37.21:
3.解決自增字段問題
172.16.37.20:
172.16.37.21:
4.都授權有複製權限的賬號
172.16.37.20/21都執行授權
MariaDB [(none)]> grant replicationclient,replication slave on *.* to 'testuser'@'172.16.%.%' identified by'123456';
5.各自把對方指定爲主服務器
172.16.37.20
先showmaster status;查看
再指定master爲對方
MariaDB [(none)]> change master to master_host='172.16.37.21',master_user='testuser',master_password='123456',master_log_file='mysq2l-bin.000001',master_log_pos=424,master_connect_retry=5,master_heartbeat_period=2;
再show slave status\G 查看slave狀態,並用startslave;啓動線程
172.16.37.21
先showmaster status;查看
再指定master爲對方
MariaDB [(none)]> change master to master_host='172.16.37.20',master_user='testuser',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=424,master_connect_retry=5,master_heartbeat_period=2;
再show slave status\G 查看slave狀態,並用startslave;啓動線程
測試:在兩個節點上創建數據庫,並在對方的Client上查看
讀寫分離:
爲了實現讀寫分離,寫操作都發往master,讀都發往slave
讀寫分離器:
mysql-proxy 測試版-->奇虎360的二次開發版 (atlas)
amoeba 淘寶研發的
dbrelay 商業產品
mysql-proxy:
先配置主從服務器
master : 172.16.37.20
1.啓用二進制日誌
2.設置一個在當前集羣中唯一的server-id
3.創建一個有複製權限[REPLICATIONSLAVE,REPLICATION CLIENT]的賬號
在mysql命令行中執行
MariaDB [(none)]> grant replicationclient,replication slave on *.* to 'testuser'@'172.16.%.%' identified by'123456';
slave : 172.16.37.21
1.啓動中繼日誌,註釋二進制日誌
2.設置一個在當前集羣中唯一的server-id
3.不允許client寫入操作
4.利用有複製權限的用戶賬號連接至主服務器,並啓動複製線程
MariaDB [(none)]> change master tomaster_host='172.16.37.20',master_user='testuser',master_password='123456',master_log_file='master-bin.000001',master_log_pos=419,master_connect_retry=5,master_heartbeat_period=2;
master_connect_retry=5:表示每5s重連一次
master_heartbeat_period=2:表示每2s探測一次master的健康狀態
在master中查出master_log_pos的值;
5.用show slavestatus查看slave狀態,並用startslave;啓動線程
再設置登錄用戶grant all on *.* to 'lx'@'%' identified by'123456';
配置mysql-proxy代理服務器,172.16.37.9
epel源:yum -yinstall mysql-proxy
使用官方二進制格式文件中的rw-splitting.lua腳本進行讀寫分離
配置文件:/etc/mysql-proxy.cnf
[mysql-proxy]
daemon= true
pid-file= /var/run/mysql-proxy.pid
log-file = /var/log/mysql-proxy.log # 可以選擇關閉日誌,因爲記錄的非常詳細,佔用磁盤空間
log-level = debug
max-open-files= 1024
plugins= admin,proxy
user= mysql-proxy
#
#ProxyConfiguration
proxy-address = 0.0.0.0:3306 #代理服務監聽的地址和端口
proxy-backend-addresses =172.16.100.7:3306 #支持讀寫操作的後端mysql
proxy-read-only-backend-addresses =172.16.100.8:3306 # 只讀後端
#proxy-lua-script=
proxy-lua-script =/usr/lib64/mysql-proxy/lua/rw-splitting.lua #讀寫分離腳本,可以註釋使用默認
#proxy-skip-profiling= true
#
#Admin Configuration
admin-address = 0.0.0.0:4041 # 默認管理程序監聽端口
admin-lua-script= /usr/lib64/mysql-proxy/lua/admin.lua
admin-username = admin # 管理用戶
admin-password = admin # 管理密碼
啓動服務:/etc/init.d/mysql-proxy start
測試:mysql -h172.16.37.9 -ulx -p123456 -e 'create database proxy-test';然後去主從服務器上查看是否創建了此database
複製的問題和解決方案:
(1) 數據損壞或丟失
從服務器崩潰回去找:master.info
最好在從節點上啓動
snyc_master_info=1
snyc_binlog=1
但會增加IO壓力
(2) 建議不要混合使用存儲引擎,可以考慮都使用InnoDB
(3) 注意要使用唯一的serverid
(4) 複製延遲
重啓從服務器的slave線程,要確保當前從服務器沒有正在進行的請求和長連接
數據庫切分:sharding
垂直切分:按表進行切分
水平切分:按表中的行進行的切分
切分條件:讀集中,寫離散
MySQL數據庫的向外擴展方式:複製、拆分、sharding
拆分方式:
按功能拆分:也即按應用拆分;
數據分片:
選擇切分鍵
把數據存儲在哪裏?
從哪兒讀數據?
數據庫切分框架:
cobar
gizzard
HibernatShards
HiveDB