優秀DBA的素質前端
1、人品,不作某些事情
2、嚴謹,運行命令前深思熟慮,三思然後行,即便是依據select
3、細心,嚴格按照步驟一步一步執行,減小出錯
4、心態,遇到災難,首先要穩住,不慌張,不要受到旁人的影響
5、熟悉操做系統,Linux系統的工具和命令
6、熟悉業務(開發),編程語言
7、熟悉行業
8、喜歡數據庫
node
• 什麼是數據?mysql
數據是指對客觀事件進行記錄並能夠鑑別的符號,是對客觀事物的性質、狀態以及相互關係等進行記載的物理符號或這些物理符號的組合。它是可識別的、抽象的符號。
• 什麼是數據庫管理系統?linux
將大量的數據規範的管理在一塊兒的軟件ios
• 數據庫管理系統種類c++
關係型和非關係型git
• 關係型數據庫的特色 – 二維表 – 典型產品 Oracle傳統企業, MySQL是互聯網企業 – 數據存取是經過SQL – 最大特色,數據安全性方面強(ACID) • NoSQL:非關係型數據庫(Not only SQL) – 不是否認關係型數據庫,作關係型數據庫的的補充。 – 想作老大,先學會作老二。 RDBMS與NoSQL對比 • web1.0時代 企業提供內容,用戶瀏覽,因此關係型數據庫夠用,併發並不高,因此不須要NoSQL。 • web2.0時代 核心是企業提供平臺,用戶參與提供內容。這時關係型數據庫沒法知足需求了。 • 2003 NoSQL出現 memcached誕生,關注的點是性能,而安全性關注比較低。隨着安全性需求不斷提高,因此有了redis。 • redis特色 – 依然高性能該併發, – 數據持久化的功能 – 支持多數據類型,主從複製和集羣 – 管理再也不使用SQL了 • NoSQL特性總覽 – 不是否認關係型數據庫,而是做爲補充,如今也有部分替代的趨勢。 – 關注高性能,高併發,靈活性,忽略和上述無關的功能。 – 如今也在提高安全性和使用功能。 – 典型產品: Redis(持久化緩存,兩個半天)、 MongoDB(最接近關係型數據的NoSQL)、 Memcached。 – 管理不適用SQL管理,而是用一些特殊的 API 或 數據接口。 • NoSQL的分類、特色、典型產品 – 鍵值(KV)存儲: Memcached、 Redis – 列存儲(column-oriented): HBASE(新浪, 360)、 Cassandra(200臺服務器集羣) – 文檔數據庫(document-oriented): MongoDB(最接近關係型數據庫的NoSQL) – 圖形存儲(Graph): Neo4j
常見數據庫企業及其產品
• Oracle數據庫版本介紹
– 7--8i--9i--10g—11g--12c--18c(?)
• Oracle的市場應用
– 市場份額第一,趨勢遞減
– 市場空間,傳統企業
– 傳統企業也在互聯網化
• MySQL數據庫版本介紹
– 5.0--5.1--5.5--5.6--5.7--8.0
5.0和5.1已經不能用了,5.6和5.7是如今的主流,8.0暫時尚未穩定的版本
• MySQL的市場應用
– 中、大型互聯網公司
– 市場空間:互聯網領域第一
– 趨勢明顯
– 同源產品: MariaDB、 perconaDB
其餘公司產品介紹
• 微軟: SQL Server
– 微軟和sysbase合做開發的產品,後來本身開發,windows平臺
– 3,4線小公司,傳統行業在用
• IBM : DB2
– 市場佔有量小
– 目前只有:國有銀行(人行、中國銀行、工商銀行等)、中國移動應用。
• PostgreSQL
• MongoDB
• Redis
後三者普遍應用在大型互聯網公司。
MySQL發展史
• 1979年,報表工具Unireg出現。
• 1985 年,以瑞典David Axmark 爲首,成立了一家公司(AB前身), IASM引擎出現。
• 1990年,提供SQL支持。
• 1999-2000年, MySQL AB公司成立,並公佈源碼,開源化。
• 2000年4月BDB引擎出現,支持事務。
• 2008年1月16號 MySQL被Sun公司收購。
• 2009年04月20日Oracle收購Sun公司, MySQL 轉入Oracle 門下。
https://db-engines.com/en/ranking 點擊查看各類數據度廣度排名程序員
1、MySQL5.6.36安裝前準備 (1)克隆一個模板機器(使用centos6),克隆完作快照 (2)IP 10.0.0.52 主機名db02 (3)iptables selinux 關閉 (4)下載好5.6.36
官網下載 ftp://ftp.jaist.ac.jp/pub/mysql/Downloads/MySQL-5.6/ 下載完成最比如對一下md5 (5)安裝依賴包 yum install -y ncurses-devel libaio-devel (6)安裝cmake yum install cmake –y (7)建立用戶 useradd -s /sbin/nologin -M mysql id mysql 2、MySQL下載安裝 (0)建立軟件下載目錄: mkdir -p /server/tools cd /server/tools/ (1)下載並上傳到/server/tools
將下載的MySQL上傳到服務器文件 社區版MySQL Community Server 5.6 5.6.3x 5.6.34 5.6.36 5.6.38 發佈超過6-12餘額的版本 5.7 5.7.17之後 (2)解壓: cd /server/tools tar xf mysql-5.6.36.tar.gz (3)安裝:注意修改本身下載的版本號,我這裏是5.6.36,版本號輸入錯誤會致使安裝失敗 cd mysql-5.6.36 cmake . -DCMAKE_INSTALL_PREFIX=/application/mysql-5.6.36 \ -DMYSQL_DATADIR=/application/mysql-5.6.36/data \ -DMYSQL_UNIX_ADDR=/application/mysql-5.6.36/tmp/mysql.sock \ -DDEFAULT_CHARSET=utf8 \ -DDEFAULT_COLLATION=utf8_general_ci \ -DWITH_EXTRA_CHARSETS=all \ -DWITH_INNOBASE_STORAGE_ENGINE=1 \ -DWITH_FEDERATED_STORAGE_ENGINE=1 \ -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \ -DWITHOUT_EXAMPLE_STORAGE_ENGINE=1 \ -DWITH_ZLIB=bundled \ -DWITH_SSL=bundled \ -DENABLED_LOCAL_INFILE=1 \ -DWITH_EMBEDDED_SERVER=1 \ -DENABLE_DOWNLOADS=1 \ -DWITH_DEBUG=0
執行到這裏也許會抱一個錯誤,致使安裝失敗
CMake Error: your CXX compiler: "CMAKE_CXX_COMPILER-NOTFOUND" was not found. Pleaet CMAKE_CXX_COMPILER to a valid compiler path or name.
這是由於系統缺乏C++編譯器
yum install gcc-c++ -y
make && make install
太慢了... 3、配置並啓動 (1)製做軟鏈接: ln -s /application/mysql-5.6.36/ /application/mysql (2)拷貝配置文件到/etc:覆蓋原文件 cp support-files/my*.cnf /etc/my.cnf (3)初始化數據庫:建立元數據,系統數據庫 /application/mysql/scripts/mysql_install_db --basedir=/application/mysql/ --datadir=/application/mysql/data --user=mysql (4)建立關鍵目錄並設置權限: mkdir -p /application/mysql/tmp chown -R mysql.mysql /application/mysql/ (5)複製啓動腳本到/etc/init.d/mysqld cp support-files/mysql.server /etc/init.d/mysqld (6)啓動數據庫
chkconfig mysqld on /etc/init.d/mysqld start netstat -lntup|grep 330 (7)配置環境變量 echo 'PATH=/application/mysql/bin/:$PATH' >>/etc/profile tail -1 /etc/profile source /etc/profile echo $PATH mysql select user,host,password from mysql.user;
排錯:
1、輸出
2、錯誤日誌
tail -100 /application/mysql/data/db02.err
設置密碼:
mysqladmin -u root password 'pizza123'
mysql -uroot -pizza123
清理用戶及無用數據庫(基本優化)
select user,host from mysql.user;
drop user ''@'db02';
drop user ''@'localhost';
drop user 'root'@'db02';
drop user 'root'@'::1';
select user,host from mysql.user;
drop database test;
show databases;
做業github
1、請列舉你瞭解到的數據庫典型產品 2、請說明企業中選擇數據庫版本的規則 3、請簡述MySQL數據庫支持的安裝方式 4、編譯安裝本身的一套MySQL數據庫 5、簡述mysql_install_db命令的經常使用參數 6、簡述5.7版本安裝過程當中與5.6的區別(本身擴展學習)
• 經過網絡鏈接串web
mysql -uroot -poldboy123 -h 10.0.0.200
• 經過套接字文件
mysql -uroot -poldboy123 -S /tmp/mysql.sock
• 思考: mysql - uroot - poldboy123 使用的是什麼方式登陸的?
• MySQL在啓動過程
– 啓動後臺守護進程,並生成工做線程
– 預分配內存結構供MySQL處理數據使用
• 實例是什麼?
MySQL的後臺進程+線程+預分配的內存結構。
show processlist;能夠查看連接到MySQL的信息
在SQL層中,語句交給解析器,轉換成執行計劃,交給查詢執行
當有多種執行計劃時,交給優化器,確認執行計劃,交給查詢執行
獲得的結果(獲取數據的方式,即位置)交給存儲引擎層,
1、接收到鏈接層送過過來的「SQL」 2、由專門的模塊,會判斷SQL語法、語義(SQL語句的類型:DDL、DCL、DML) 3、將不一樣類型的語句,送到專門的處理接口(解析器) 4、解析器,將SQL解析成執行計劃 5、優化器,會選擇「它」最優的執行計劃交給執行器 6、執行器,執行 執行計劃,得出如何去「磁盤」獲取數據的方法 7、專門線程將獲取數據的方法,送給下層(存儲引擎層)繼續處理。 8、驗證受權,當前用戶對 庫或表對象有沒有操做的權限。 9、查詢高速緩存query_cache。 10、記錄修改操做日誌binlog。
真正接觸數據,和數據打交道的,接受SQL層執行計劃的結果,去指定的位置取指定的數據,或者將數據存儲在哪一個位置
存儲引擎是充當不一樣表類型的處理程序的服務器組件。
• 存儲引擎用於:
– 存儲數據
– 檢索數據
– 經過索引查找數據
• 雙層處理
– 上層包括SQL解析器和優化器
– 下層包含一組存儲引擎
• SQL 層不依賴於存儲引擎:
– 引擎不影響SQL處理
– 有一些例外,
依賴於存儲引擎的功能
• 存儲介質
• 事務功能
• 鎖定
• 備份和恢復
• 優化
• 特殊功能:
– 全文搜索
– 引用完整性
– 空間數據處理
首先,在磁盤中存儲的數據確定不是這個表的形式,在命令運行以後,通過一系列的操做,表格才展示在咱們眼前
一、鏈接層
通訊協議---驗證---受權---提供連接線程---接收SQL語句,並交給SQL層
二、SQL層
見上面的流程,驗證語法、語義(查詢or插入)---query_cache---解析---優化---
三、存儲引擎層
去指定位置取指定的數據---返回給SQL層---處理---鏈接層交給用戶展示
列、數據行、表、庫 就是這些抽象出來的結構
在物理層,是怎麼存儲到磁盤的呢?見下圖,MySQL對磁盤的使用
注:咱們只研究到文件系統層
程序文件隨數據目錄一塊兒存儲在服務器安裝目錄下。執行各類客戶機程序、管理程序 和實用程序時將建立程序可執行文件和日誌文件。
首要使用磁盤空間的是數據目錄。
• 服務器日誌文件和狀態文件: 包含有關服務器處理的語句的信息。日誌可用於進行故障排除、監視、複製和恢復。
• InnoDB 日誌文件: (適用於全部數據庫)駐留在數據目錄級別。
• InnoDB 系統表空間:
包含數據字典、撤消日誌和緩衝區。
每一個數據庫在數據目錄下均具備單一目錄(不管在數據庫中建立何種類型的表)。
數據庫目錄存儲如下內容:
- 數據文件: 特定於存儲引擎的數據文件。這些文件也可能包含元數據或索引信息,具體取決於所使用的存儲引擎。
- 格式文件 (.frm): 包含每一個表和/或視圖結構的說明,位於相應的數據庫目錄中。
- 觸發器: 與某個表關聯並在該表發生特定事件時激活的命名數據庫對象。
數據目錄的位置取決於配置、操做系統、安裝包和分發。
典型位置是 /var/lib/mysql。 MySQL在磁盤上存儲系統數據庫 (mysql)。
mysql 包含諸如用戶、特權、插件、 幫助列表、事件、時區實現和存儲例程之類的信息。
頁(默認是16k):是mysql數據庫存儲的最小單元
區:連續的多個頁組成,是一系列練習的數據行
段:一個表(分區表)就是一個段,包含了多個區
mysql命令 -u 用戶名 -p 密碼 例子: mysql -uroot -pizza123 -h ip 例子: mysql -uroot -pizza123 -h 10.0.0.52 -P 3308 例子: mysql -uroot -pizza123 -h 10.0.0.52 -P 3308 -S /tmp/mysql.sock 套接字目錄 例子: mysql -uroot -pizza123 -S /application/mysql/tmp/mysql.sock -e "show variables like 'server_id';" 免交互式執行SQL命令,直接得到結果 例子: mysql -uroot -pizza123 -e "show variables like 'server_id';" mysqladmin mysqladmin -uroot -p password pizza123
用戶權限由用戶名+主機範圍構成
對比一下Linux用戶和MySQL用戶
user:表示使用哪一個用戶登錄
host:表示從哪些地址訪問這個數據庫
• 用戶的做用:
– 1、用戶登陸
– 2、用於管理數據庫及數據
• 權限: 針對不一樣用戶設置不一樣對象管理能力
– 對數據庫的讀、寫等操做
– (insert update、select等)
• 角色:
– 數據庫定義好的一組權限的定義
– (all privileges、replication slave等)
• 權限範圍:
– 全庫級別: *.*
– 單庫級別:oldboy.*
– 單表級別:oldboy.t1
超級管理(管理)用戶:root ,當前若是要進行受權操做只能用root進行
也不用再去建立了,固然也能夠根據不一樣的地址,主機域去設置不一樣的密碼和操做
mysqladmin -uroot -p password pizza123 這條命令,執行的是root@localhost,即只在本地生效的權限範圍
普通用戶(開發)的權限包括:select update delete insert drop ...用的比較多的
用戶操做命令
• 查看當前用戶:
select user,host from mysql.user;
• 建立用戶
CREATE USER '用戶'@'主機' IDENTIFIED BY '密碼';
create user 'pizza'@'localhost' identified by 'pizza123';
#只有鏈接權限 企業裏建立用戶通常是受權一個內網網段登陸,最多見的網段寫法有兩種。
方法1:172.16.1.%(%爲通配符,匹配全部內容)。
方法2:172.16.1.0/255.255.255.0,可是不能使用172.16.1.0/24,是個小遺憾。
# 遠程登陸,帶參數-h
mysql> create user web01@'10.0.0.%' identified by '123';
[root@web01 mysql-5.6.43]# mysql -uweb01 -p123 -h10.0.0.7
登錄後的普通用戶,權限很低
標準的建用戶方法:
create user 'web'@'172.16.1.%' identified by 'web123';
• 查看用戶對應的權限
show grants for oldboy@localhost\G
• 刪除用戶
drop user 'user'@'主機域' 或者 drop user root@'127.0.0.1';
用戶優化:只保留 有密碼和有用戶名的
| root | 127.0.0.1 |
| root | localhost |
特殊的刪除方法:
mysql> delete from mysql.user where user='pizza' and host='localhost';
Query OK, 1 row affected (0.00 sec) mysql> flush privileges;
• 給用戶受權
create user 'pizza'@'localhost' identified by 'pizza123';
select user,host from mysql.user;
GRANT ALL ON *.* TO 'pizza'@'localhost';
SHOW GRANTS FOR 'pizza'@'localhost'\G
• 建立用戶的同時受權
grant all on *.* to pizza@'172.16.1.%' identified by 'pizzal123';
flush privileges; #<==能夠不用。
create user 'pizza'@'localhost' identified by 'pizza123';
GRANT ALL ON *.* TO 'pizza'@'localhost';
• 受權和root同樣的權限
grant all on *.* to system@'localhost' identified by 'pizzal123' with grant option; • 收回權限
REVOKE INSERT ON *.* FROM pizza@localhost;
• 能夠受權的用戶權限
INSERT,SELECT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE,
REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES,
LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW,
SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER,
CREATE TABLESPACE
• 開發用戶 擁有的基本權限
INSERT,SELECT, UPDATE, DELETE, CREATE, DROP
grant INSERT,SELECT, UPDATE, DELETE, CREATE, DROP on testdb.* to web01@‘10.0.0.%’;
• 工做博客受權:
grant select,insert,update,delete,create,drop on blog.* to 'blog'@'172.16.1.%' identified by 'blog123';
revoke create,drop on blog.* from 'blog'@'172.16.1.%';
最多:select,insert,update,delete • 注意: 思考一下若是在oldboy.*,設置了select,insert,update,delete 在oldboy.t1設置了select,
那麼用戶在t1表的最終權限應該是什麼。 回收權限的時候又該怎麼作?
實驗後的結論:
若是對於某個用戶在不一樣數據庫級別都設置了權限,最終權限相疊加,以加起來的最大權限爲準。
建議:不要多範圍受權
數據庫的啓動流程介紹
mysql最終啓動的是mysqld進程,經過他提供的啓動腳本,不能直接啓動mysqld
數據庫的關閉
• mysqladmin shutdown
• servive mysqld stop
• kill -9 ? 慎用
• 第三種爲利用系統進程管理命令關閉MySQL。
– kill pid #<==這裏的pid爲數據庫服務對應的進程號。
– killall mysqld #<==這裏的mysqld是數據庫服務對應的進程名字。
– pkill mysqld #<==這裏的mysqld是數據庫服務對應的進程名字。 可經過以下地址查看生產高併發環境野蠻粗魯殺死數據庫致使故障企業案例:
http://oldboy.blog.51cto.com/2561410/1431161
http://oldboy.blog.51cto.com/2561410/1431172
MySQL啓動報錯
停數據庫----去mysql/data目錄下--隨便改一個文件(目錄下的一個文件權限改爲root)---啓動數據庫
報錯
常規的報錯代碼整理 http://oldboy.blog.51cto.com/2561410/1728380
啓動以前都作了什麼?
一、程序在哪
二、啓動後去哪裏找數據
三、啓動以後分配多大內存
...
n、還有許許多多的問題
MySQL的初始化配置文件
預編譯配置項,即在使用cmake時,硬編碼設置的參數,指定了如安裝目錄、數據目錄、sock目錄
命令行設置,在命令行上配置參數
/application/mysql/bin/mysqld_safe 用來啓動mysql,由於設置過環境變量,能夠直接運行
mysqld_safe --socket=/tmp/mysql.sock --port=3307 &
連接,不能用老的方式了
mysql -uroot -ppizza -S /tmp/mysql.sock
初始化配置文件,/etc/my.cof
標籤的種類和影響的程序
選項文件示例
[mysqld]
basedir=/application/mysql
datadir=/application/mysql/data
socket=/application/mysql/tmp/mysql.sock
port=3306
server_id=10
log-error=/var/log/mysql.log
log-bin=/application/mysql/data/mysql-bin
binlog_format=row
skip_name_resolve
[mysql]
socket=/application/mysql/tmp/mysql.sock
優先級
mysql 啓動參數設置 1、預編譯時候設置參數,參數會硬編碼到程序中 2、命令行方式設定啓動參數 3、初始化的配置文件 2>3>1
MySQL爲咱們配置了不少配置文件,配置文件讀取順序以下
自定義配置文件位置,系統本身是找不到的
vim /tmp/aa.txt [mysqld] basedir=/application/mysql datadir=/application/mysql/data port=3307 socket=/tmp/mysql.sock
使用自定義的配置文件
/etc/init.d/mysqld stop
mysqld_safe --defaults-file=/tmp/aa.txt &
一個MySQL實例就是一個進程,多個線程,必定量預分配的內存空間
多實例就是,多個這樣的實例管理不一樣的數據,和一些日誌
思路
1、啓動多個mysqld進程 2、規劃多套數據 3、規劃多個端口 4、規劃多套日誌路徑
多實例配置
1、建立多套目錄 mkdir -p /data/330{7,8,9} 2、準備多套配置文件 vim /data/3307/my.cnf [mysqld] basedir=/application/mysql datadir=/data/3307 server-id=3307 port=3307 log-bin=/data/3307/mysql-bin socket=/data/3307/mysql.sock log-error=/data/3307/mysql.log vim /data/3308/my.cnf [mysqld] basedir=/application/mysql datadir=/data/3308 server-id=3308 port=3308 log-bin=/data/3308/mysql-bin socket=/data/3308/mysql.sock log-error=/data/3308/mysql.log vim /data/3309/my.cnf [mysqld] basedir=/application/mysql datadir=/data/3309 server-id=3309 port=3309 log-bin=/data/3309/mysql-bin socket=/data/3309/mysql.sock log-error=/data/3309/mysql.log 3、初始化多套數據 /application/mysql/scripts/mysql_install_db --basedir=/application/mysql/ --datadir=/data/3307 --user=mysql /application/mysql/scripts/mysql_install_db --basedir=/application/mysql/ --datadir=/data/3308 --user=mysql /application/mysql/scripts/mysql_install_db --basedir=/application/mysql/ --datadir=/data/3309 --user=mysql 4、啓動多個實例 mysqld_safe --defaults-file=/data/3307/my.cnf & mysqld_safe --defaults-file=/data/3308/my.cnf & mysqld_safe --defaults-file=/data/3309/my.cnf & 5、查看啓動端口 netstat -lnp |grep 330 6、分別鏈接測試 mysql -S /data/3307/mysql.sock -e "show variables like 'server_id';" mysql -S /data/3308/mysql.sock -e "show variables like 'server_id';" mysql -S /data/3309/mysql.sock -e "show variables like 'server_id';"
做業
1、列出MySQL在Linux下的兩種鏈接方式 2、簡述mysql修改密碼方法 3、簡述實例的構成 4、結合MySQL體系結構,說明一條SQL語句的執行過程 5、mysql的默認日誌文件在什麼位置 6、簡述MySQL的啓動方式 7、簡述MySQL配置文件讀取順序 8、配置MySQL多實例,端口分別爲3307 3308 3309 9、請介紹mysql鏈接命令的經常使用參數,並說明功能 10、請簡述MySQL的邏輯構成
• mysql:
– 用於數據庫鏈接管理
– 前面章節已經使用過(略。)
– 命令接口自帶命令
• 一、\h 或 help 或 ?
• 二、\G 鍵值對的方式排列
• 三、\T 或 tee 記錄到日誌
• 四、\c 或 CTRL+c 結束上一條命令
• 五、\s 或 status 查看數據庫基本狀態信息
• 六、\. 或 source 調用外部SQL腳本
• 七、\u 或use
– 將 用戶SQL 語句發送到服務器,管理數據庫
結構化查詢語言,MySQL接口程序只負責接受SQL,傳送給SQL層
– DDL:數據庫(對象)定義語言
– DCL:數據控制語言(grant、revoke)
– DML:數據(行)操做語言(update、delete、insert)
- DQL:數據查詢語言(show、select)
• mysqladmin:
– 命令行管理工具
• mysqldump:
– 備份數據庫和表的內容
• 在 mysql 中處理輸入文件:
• 若是這些文件包含 SQL 語句,則稱爲:
– 「腳本文件」
– 「批處理文件」
• 使用 SOURCE 命令:
mysql> SOURCE /data/mysql/world.sql
或者使用非交互式:
mysql</data/mysql/world.sql
• DBA的命令行客戶端工具
• 多項功能:
– 「強制迴應 (Ping)」服務器。
– 關閉服務器。
– 建立和刪除數據庫。
– 顯示服務器和版本信息。
– 顯示或重置服務器狀態變量。
– 設置口令
– 從新刷新受權表。
– 刷新日誌文件和高速緩存
– 啓動和中止複製
– 顯示客戶機信息 • 命令幫助及基本語法:
mysqladmin --help
mysqladmin -u<name> -p<password> commands • 例子:
mysqladmin version
mysqladmin status
mysqladmin ping
mysqladmin processlist
mysqladmin shutdown
mysqladmin variables
…
• 數據庫備份工具。
• 命令幫助及基本語法:
mysqldump –help
Usage: mysqldump [OPTIONS] database [tables]
OR mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]
OR mysqldump [OPTIONS] --all-databases [OPTIONS]
數據庫對象:庫、表
庫的名字,庫的基本屬性 create database blog;
• 查看完整的 SQL 類別列表:
mysql> HELP CONTENTS
...
Account Management
Administration
Compound Statements
Data Definition
Data Manipulation Data Types
...
• 有關特定 SQL 類別或語句的幫助:
mysql> HELP Data Manipulation
mysql> HELP JOIN
• 有關與狀態相關的 SQL 語句的幫助:
mysql> HELP STATUS
DDL操做: 對象: 庫: 定義什麼? 1、庫名字 2、庫的基本屬性 如何定義? create database lufei; create schema lf; show databases; create database llf CHARACTER SET utf8 ; show create database llf; drop database llf; help create database; 字符集: CHARACTER SET [=] charset_name 排序規則:COLLATE [=] collation_name 改庫的字符集: ALTER DATABASE [db_name] CHARACTER SET charset_name COLLATE collation_name mysql> alter database lf charset utf8mb4; mysql> show create database lf; 表: 表數據:數據行 表屬性(元數據):表名、列名字、列定義(數據類型、約束、特殊列屬性)、表的索引信息 定義什麼? 定義表的屬性。 use lufei; 建立: create table t1 (id int ,name varchar(20)); 查詢: show tables; show create table t1; desc 刪除 drop table t1; 修改: (1)在表中添加一列 alter table t1 add age int; (2)添加多列 alter table t1 add bridate datetime, add gender enum('M','F'); (3)在指定列後添加一列,沒有before(,這是一個無關緊要的選項,下降開發需求) alter table t1 add stu_id int after id; (4)在表中最前添加一列 alter table t1 add sid int first; (5)刪除列 alter table t1 drop sid; (6)修改列名 alter table t1 change name stu_name varchar(20); (7)修改列屬性 alter table t1 modify stu_id varchar(20); (8)修改表名 rename table t1 to student; alter table student rename to stu;
• 查看數據庫
show databases;
show databases like '%old%'; • 獲取命令幫助
? contents
?Administration
? show database
• 建立數據庫
CREATE DATABASE oldboy; #字符集和編譯指定相同.
• 獲取命令幫助
? contents
?Data Definition
? create database
• 查看建庫的語句
show create database oldboy\G
• 指定字符集建庫
CREATE DATABASE db_name CHARACTER SET
charset_name COLLATE collation_name
CREATE DATABASE oldgirl CHARACTER SET gbk COLLATE
gbk_chinese_ci;
show character set;#找字符集和校對規則.
• 改庫的字符集:
ALTER DATABASE [db_name] CHARACTER SET charset_name COLLATE collation_name
ALTER DATABASE oldgirl CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
• 刪庫 drop database oldboy;
• 切庫 use oldboy;
• 查看當前所在的庫 select database(); select user();
• 查看庫裏的表 show tables;
• 用戶: ‘user’@‘主機域’ • 幫助: ? Account Management • 經常使用命令: 1.查看當前用戶 2.建立用戶 3.查看用戶對應的權限 4.刪除用戶 5.給用戶受權 6.收回權限 7.工做博客受權
• 表的屬性:
– 字段、數據類型、索引
– 默認:字符集、引擎
• 創建表
create table <表名> (<字段名1> <類型1> , …<字段名n> <類型n>);
• 獲取幫助
help create table; • 查看錶結構:
desc student;
• 查看建表語句:
show create table student\G
• 更改表名
rename table student to test;
alter table test rename to student;
• 原表:
CREATE TABLE `test` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`name` char(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=UTF8; • 先添加性別列,長度爲4,內容非空
alter table test add sex char(4) NOT NULL;
• 指定添加年齡列到name列後面的位置,示例以下:
alter table test add age int(4) after name;
• 經過下面的命令在第一列添加qq字段。
alter table test add qq varchar(15) first; • 若要刪除字段,可採用以下命令。
alter table test drop qq;
• 若要同時添加兩個字段,可採用以下命令。
alter table test add age tinyint(2) first,add qq varchar(15);
• 修改字段類型的命令以下:
alter table test modify age char(4) after name;
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
• 修改字段名稱的命令以下:
alter table test change age oldboyage char(4) after name;
添加表字段
alter table table1 add transactor varchar(10) not Null;
alter table table1 add id int unsigned not Null auto_increment primary key
修改某個表的字段類型及指定爲空或非空
alter table 表名稱 change 字段名稱 字段名稱 字段類型 [是否容許非空];
alter table 表名稱 modify 字段名稱 字段類型 [是否容許非空];
alter table 表名稱 modify 字段名稱 字段類型 [是否容許非空];
修改某個表的字段名稱及指定爲空或非空
alter table 表名稱 change 字段原名稱 字段新名稱 字段類型 [是否容許非空]
刪除某一字段
ALTER TABLE mytable DROP 字段 名;
添加惟一鍵
ALTER TABLE `test2` ADD UNIQUE ( `userid`)
修改主鍵
ALTER TABLE `test2` DROP PRIMARY KEY ,ADD PRIMARY KEY ( `id` )
增長索引
ALTER TABLE `test2` ADD INDEX ( `id` )
ALTER TABLE `category ` MODIFY COLUMN `id` int(11) NOT NULL AUTO_INCREMENT FIRST ,ADD PRIMARY KEY (`id`);
第一步:給 id 增長auto_increment 屬性
alter table test modify id int(11) auto_increment;
第二步:給自增值設置初始值
alter table test auto_increment=0;
思考:change和modify該如何選擇?
修改主鍵的sql語句塊以下:
mailbox 表新增字段
DROP PROCEDURE IF EXISTS mailbox_column_update;
CREATE PROCEDURE mailbox_column_update() BEGIN
-- 新增刪除標誌列
IF NOT EXISTS(SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='cbs' AND table_name='mailbox' AND COLUMN_NAME='delete_flag') THEN
ALTER TABLE mailbox ADD delete_flag int DEFAULT 2 NOT NULL;
END IF;
-- 新增刪除日期列
IF NOT EXISTS(SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='cbs' AND table_name='mailbox' AND COLUMN_NAME='delete_date') THEN
ALTER TABLE mailbox ADD delete_date int DEFAULT 0 NOT NULL;
END IF;
-- 若是存在字段account_mail,則修改字段長度
IF EXISTS(SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='cbs' AND table_name='mailbox' AND COLUMN_NAME='email_account')
THEN
alter table mailbox modify column email_account varchar(320);
END IF;
-- 若是不存在主鍵列,則設置雙主鍵
IF ((SELECT count(*) FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA ='cbs' AND table_name='mailbox' AND CONSTRAINT_NAME ='PRIMARY' AND (COLUMN_NAME ='email_account' OR COLUMN_NAME = 'company_id'))=0)THEN
ALTER TABLE mailbox ADD primary key (company_id,email_account);
-- 若是隻存在一個主鍵列
ELSEIF ((SELECT count(*) FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA ='cbs' AND table_name='mailbox' AND CONSTRAINT_NAME ='PRIMARY' AND (COLUMN_NAME ='email_account' OR COLUMN_NAME = 'company_id'))<2)THEN
ALTER TABLE mailbox DROP PRIMARY KEY,ADD primary key (company_id,email_account);
END IF;
• 備份數據備用
mysqldump以SQL語句形式將數據導出來。
mysqldump -B --compact oldboy >/opt/bak.sql
• insert 插入數據
use lufei;
create table t1 (id int ,name varchar(20));
# 要根據 表結構 插入
insert into t1 values(1,'zhang3');
select * from t1;
insert into t1 values (2,'li4'),(3,'wang5'),(4,'ma6');
# 向指定列 插入
insert into t1(name) values ('xyz');
• 修改數據
update t1 set name='zhang33' ; --會更新表中全部行的name字段,比較危險。
update t1 set name='zhang55' where id=1;
--update在使用時通常都會有where條件去限制。
update test set id=6 where name='kaka';
練習:把ID爲2的名字改成bingbing.
• 防止不加條件誤刪:
mysql -U
update test set name='lanlan';
ERROR 1175 (HY000): You are using safe update mode
and you tried to update a table without a WHERE that uses a KEY column 至於防止誤操做致使上述數據庫故障案例的方法之一,
請參見http://oldboy.blog.51cto.com/2561410/1321061 • 刪除(delete)
delete from test; #邏輯刪除,一行一行刪。 刪除全部
delete from t1 where id=2; 刪除指定數據
truncate table test; #物理刪除,pages(block),效率高。 DDL操做
• 案例:不刪除,而是僞刪除。添加字段state,改變字段的值實現僞刪除
alter table test add state tinyint(2) not null default 1;
update test set state=1;
正常顯示:
select * from test where id=1;
update test set state=0 where name='oldboy';
- 導入world.sql - 應用腳本 登錄mysql mysql> source /server/tools/world.sql show databases;
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| world |
+--------------------+
4 rows in set (0.00 sec) - 建立用戶(能遠程連接的用戶),使用sqlyog(有聯想功能)登錄數據庫 - create user root@'10.0.0.%' identified '123';
- grant all on *.* to 'root'@'10.0.0.%'
• 查詢表中的數據
命令語法:select <字段1,字段2,...> from < 表名 > where < 表達式 > and < 表達式 >。
其中,select、from、where是不能隨便改的,是關鍵字,支持大小寫。
select <字段1,字段2,...> from < 表名 > where < 表達式 >
select user,host,password from mysql.user; select * from oldboy.test;
select id,name from oldboy.test;
select id,name from test where id=2;
select id,name from test where name='oldgirl';
select id,name from test where id>2;
select id,name from test where id>2 and id<4;
select id,name from test where id>2 or id<4;
select id,name from test;
select id,name from test order by id asc;
select id,name from test order by id desc;
select id,name from test limit 1,3;
help select;
• 基本語法
SELECT *|{[DISTINCT] column|select_expr [alias], ...]}
[FROM [database.]table]
[WHERE conditions]; • WHERE條件又叫作過濾條件,它從FROM子句的中間結果中去掉全部
條件conditions不爲TRUE(而爲FALSE或者NULL)的行
• WHERE子句跟在FROM子句後面
• 不能在WHERE子句中使用列別名 • 例1:where字句的基本使用
SELECT * FROM world.`city` WHERE CountryCode='CHN';
or
SELECT * FROM world.`city` WHERE CountryCode='chn'; 注意: WHERE中出現的字符串和日期字面量必須使用引號括起來
這裏,字符串字面量寫成大寫或小寫結果都同樣,即不區分大小寫進行查詢。
這和ORACLE不一樣,ORACLE中WHERE條件中的字面量是區分大小寫的 • 例2:where字句中的邏輯操做符:
SELECT * FROM world.`city` WHERE CountryCode='chn' AND district = 'anhui';
• 邏輯操做符介紹:
– and 邏輯與。只有當全部的子條件都爲true時,and才返回true。不然返回false或null
– or 邏輯或。只要有一個子條件爲true,or就返回true。不然返回false或null
– not 邏輯非。若是子條件爲true,則返回false;若是子條件爲false,則返回true
– xor 邏輯異或。當一個子條件爲true而另外一個子條件爲false時,其結果爲true;
當兩個條件都爲true或都爲false時,結果爲false。不然,結果爲null • 例3 :where字句中的範圍比較:
SELECT * FROM world.`city` WHERE population BETWEEN 100000 AND 200000 ; • 例4:where字句中的IN
SELECT * FROM city WHERE countrycode IN ('CHN','JPN'); • 例5:where字句中的like
– 語法:
like ‘匹配模式字符串’
– 實現模式匹配查詢或者模糊查詢:
測試一個列值是否匹配給出的模式
– 在‘匹配模式字符串’中,能夠有兩個具備特殊含義的通配字符:
%:表示0個或者任意多個字符
_:只表示一個任意字符 SELECT * FROM city WHERE countrycode LIKE 'ch%'; • ORDER BY子句用來排序行
• 若是SELECT語句中沒有ORDER BY子句,
那麼結果集中行的順序是 不可預料的
• 語法: SELECT expr
FROM table
[WHERE condition(s)]
[ORDER BY {column, expr, numeric_position} [Asc|DEsc]];
• 其中:
– Asc:執行升序排序。默認值
– DEsc:執行降序排序
– ORDER BY子句通常在SELECT語句的最後面 • 例1: 基本使用
SELECT * FROM city ORDER BY population;
• 例2:多個排序條件
SELECT * FROM city ORDER BY population,countrycode;
• 例3:以select字句列編號排序
SELECT * FROM city ORDER BY 5;
• 例4:desc asc
SELECT * FROM city ORDER BY 5 desc;
• 例5:NULL值的排序 在MySQL中,把NULL值當作一列值中的最小值對待。
所以,升序排序時,它出如今最前面
LIMIT • MySQL特有的子句。
• 它是SELECT語句中的最後一個子句(在order by後面)。
• 它用來表示從結果集中選取最前面或最後面的幾行。
• 偏移量offset的最小值爲0。
• 語法: limit <獲取的行數> [OFFSET <跳過的行數>]
或者 limit [<跳過的行數>,] <獲取的行數>
SELECT * FROM city ORDER BY 5 DEsc LIMIT 4; 注:先按照人口數量進行降序排序,而後使用 limit 從中挑出最前面的 4 行。 若是沒有 order by 子句,返回的 4 行就是不可預料的。
• 傳統的鏈接寫法(使用where) SELECT NAME,ci.countrycode ,cl.language ,ci.population
FROM city ci , countrylanguage cl WHERE ci.`CountryCode`=cl.countrycode; 注意:一旦給表定義了別名,那麼原始的表名就不能在出如今該語句 的其它子句中了 • NATURAL JOIN子句
• 自動到兩張表中查找全部同名同類型的列拿來作鏈接列,進行相等
鏈接 SELECT NAME,countrycode ,LANGUAGE ,population
FROM city NATURAL JOIN countrylanguage WHERE population > 1000000
ORDER BY population; 注意:在 select 子句只能出現一個鏈接列 • 使用using子句
SELECT NAME,countrycode ,LANGUAGE ,population
FROM city JOIN countrylanguage USING(countrycode); • UNION [DISTINCT]
• UNION ALL
• 語法:
SELECT ...
UNION [ALL | DISTINCT]
SELECT ...
[UNION [ALL | DISTINCT]
SELECT ...]
• UNION用於把兩個或者多個select查詢的結果集合併成一個
• 進行合併的兩個查詢,其SELECT列表必須在數量和對應列的數據類型上保持一致
• 默認會去掉兩個查詢結果集中的重複行
• 默認結果集不排序
• 最終結果集的列名來自於第一個查詢的SELECT列表 • 「Group By」從字面意義上理解就是根據「By」指定的規則對數據進行分組,
所謂的分組就是將一個「數據集」劃分紅若干個「小區域」,而後針對若干個 「小區域」進行數據處理。
• Having與Where的區別
– where 子句的做用是在對查詢結果進行分組前,將不符合where條件的行去掉,
即在分組以前過濾數據,where條件中不能包含聚組函數,使用where條件過濾出特定的行。
– having 子句的做用是篩選知足條件的組,即在分組以後過濾數據,
條件中常常包含聚 組函數,使用having 條件過濾出特定的組,也能夠使用多個分組標準進行分組。 • 子查詢定義
– 在一個表表達中能夠調用另外一個表表達式,這個被調用的表表達式叫作子查詢( subquery),
我麼也稱做子選擇(subselect)或內嵌選擇(inner select)。
子查詢 的結果傳遞給調用它的表表達式繼續處理。
– 子查詢(inner query)先執行,而後執行主查詢(outer query)
– 子查詢按對返回結果集的調用方法,可分爲:where型子查詢,from型子查詢及exists 型子查詢。
• 使用子查詢原則
– 一個子查詢必須放在圓括號中。
– 將子查詢放在比較條件的右邊以增長可讀性。
子查詢不包含 ORDER BY 子句。對一個 SELECT 語句只能用一個 ORDER BY 子句,而且
若是指定了它就必須放在主 SELECT 語句的最後。
– 在子查詢中能夠使用兩種比較條件:
單行運算符(>, =, >=, <, <>, <=) 和多行運算符 (IN, ANY, ALL)。
查詢以前,先看一下表的結構
DESC world.city SELECT id ,NAME FROM world.city; SELECT * FROM world.`city`;
-- select 條件查詢 where
注意: WHERE中出現的字符串和日期字面量必須使用引號括起來
這裏,字符串字面量寫成大寫或小寫結果都同樣,即不區分大小寫進行查詢。
這和ORACLE不一樣,ORACLE中WHERE條件中的字面量是區分大小寫的 ---- 1、查詢中國(CHN)全部的城市信息 SELECT * FROM world.`city` WHERE countrycode='CHN'; ---- 2、查詢中國(CHN)安徽省全部的城市信息。 AND SELECT * FROM world.`city` WHERE countrycode='CHN' AND district='anhui'; ---- 3、查詢世界上人口數量在10w-20w城市信息 BETWEEN AND SELECT * FROM world.`city` WHERE population BETWEEN 100000 AND 200000 ; ---- 4、中國或者日本的全部城市信息 IN where字句中的IN SELECT * FROM world.city WHERE countrycode IN ('CHN','JPN'); ---- 5、模糊查詢 LIKE SELECT * FROM world.city WHERE countrycode LIKE 'ch%'; -- select 排序並限制 ORDER BY ---- 按照人口數量排序輸出中國的城市信息(ASC\DESC) ASC 升序 DESC 降序
order by 字句通常在select語句的後面
SELECT * FROM world.`city` WHERE countrycode='CHN' ORDER BY population ASC; SELECT * FROM world.`city` WHERE countrycode='CHN' ORDER BY population DESC; ---- 按照多列排序人口+省排序
SELECT * FROM world.`city` WHERE countrycode='CHN'
ORDER BY Population,District DESC; 多個條件用,分割,
---出現的效果是,按照最後一個排序,但有時候也不是按照最後一個,會出現意想不到的效果
---通常排序時,最好仍是使用單列 SELECT * FROM world.`city` WHERE countrycode='CHN' ORDER BY id DESC ; ---安裝列所在位置,排序 SELECT * FROM city ORDER BY 5 DESC ; ---就是按照第5列population --- NULL值的排序,在MySQL中,把NULL值當作一列的最小值
1-10 LIMIT SELECT * FROM world.`city` WHERE countrycode='CHN' ORDER BY 5 DESC LIMIT 20; 11-20 SELECT * FROM world.`city` WHERE countrycode='CHN' ORDER BY 5 DESC LIMIT 10,10 ; --至關於 SELECT * FROM world.`city` WHERE countrycode='CHN' ORDER BY 5 DESC LIMIT 10 OFFSET 10 ;
-- 錶鏈接查詢 DESC city DESC countrylanguage 傳統的鏈接寫法(使用where) ---- 中國全部城市信息+使用語言(city+countrylanguage)
--一、從city中顯示城市名 SELECT NAME ,countrycode ,population FROM city WHERE countrycode ='CHN'
--二、從countrycode中顯示語言 SELECT countrycode ,LANGUAGE FROM countrylanguage; --三、連表 SELECT ci.NAME ,ci.countrycode ,ci.population,cl.language FROM city AS ci , countrylanguage AS cl WHERE ci.countrycode ='CHN' AND ci.CountryCode=cl.CountryCode; -- name 能夠直接使用, SELECT NAME,ci.countrycode ,cl.language ,ci.population FROM city ci , countrylanguage cl WHERE ci.countrycode='chn' AND ci.`CountryCode`=cl.countrycode; -- 使用NATURAL JOIN SELECT NAME,countrycode ,LANGUAGE ,population FROM city NATURAL JOIN countrylanguage WHERE population > 10000000 ORDER BY population; -- 使用JOIN USING SELECT NAME,countrycode ,LANGUAGE ,population FROM city JOIN countrylanguage USING(countrycode); NATURAL JOIN 和 JOIN USING 都不經常使用
---- 查詢青島這個城市,所在的國傢俱體叫什麼名字 使用 JOIN ON DESC city DESC country --一、查看青島 SELECT NAME,countrycode FROM city WHERE NAME='qingdao'; --二、查看中國城市名 SELECT NAME FROM country WHERE CODE='CHN'; --三、連表 -------------------------------- SELECT ci.name ,ci.countrycode,ci.population ,co.name FROM city AS ci JOIN country AS co ON ci.countrycode=co.code AND ci.name='qingdao'; ---------------------------------
group by +聚合函數(avg()、max()、min()、sum()) SELECT countrycode ,SUM(population) FROM city WHERE countrycode = 'chn' GROUP BY countrycode; union 用來替換 or 、in() 性能更好些 SELECT * FROM world.city WHERE countrycode IN ('CHN','JPN'); 改寫爲: SELECT * FROM world.city WHERE countrycode ='CHN' union SELECT * FROM world.city WHERE countrycode ='JPN';
兩個SQL須要是相同的結
尤爲是在進行數據庫遷移的時候,必定要注意字符集
• 字符集(Charset):
是一個系統支持的全部抽象字符的集合。
字符是各類文字和符號的總稱, 包括各國家文字、標點符號、圖形符號、數字等。
• MySQL數據庫的字符集:
– 字符集(CHARACTER)
– 校對規則(COLLATION)
• MySQL中常見的字符集:
– UTF8 ,utf8mb4
– LATIN1 編譯默認的,開發者的母語
– GBK
• 常見校對規則: 即排序規則
– ci:大小寫不敏感 aA-zZ
– cs或bin:大小寫敏感 a-z A-Z
• 咱們能夠使用如下命令查看:
– show charset;
– show collation;
字符集的級別
• 操做系統級別
控制的是系統相關的顯示,和一些依賴於操做系統的應用
source /etc/sysconfig/i18n
[root@db02 logs]# echo $LANG
zh_CN.UTF-8
• 操做系統客戶端級別(SSH)
控制的是用戶的輸入和展現
• 服務端字符集
控制的是,存到mysql中時,字符集控制
• MySQL實例級別
– 方法1:在編譯安裝時候就指定以下服務器端字符集。
cmake .
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_EXTRA_CHARSETS=all \
– 方法2:
[mysqld] character-set-server=utf8
• 數據庫中的庫級別
CREATE DATABASE `oldboy` /*!40100 DEFAULT CHARACTER SET utf8 */
create database oldboy DEFAULT CHARACTER SET UTF8 DEFAULT COLLATE
= utf8_general_ci;
• 獲取幫助並查詢
help create database;
show character set;
• 表級別(含字段級別)
CREATE TABLE `test` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`name` char(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8
• MySQL客戶端級別(鏈接及返回結果)
方法1:臨時生效單條命令法。
mysql> set names utf8;
Query OK, 0 rows affected (0.00 sec)
方法2:經過修改my.cnf實現修改mysql客戶端的字符集,配置方法以下。
[client]
default-character-set=utf8
• 程序代碼級別
• 生產環境更改數據庫(含數據)字符集的方法
alter database oldboy CHARACTER SET utf8 collate
utf8_general_ci;
alter table t1 CHARACTER SET latin1;
注意:更改字符集時,必定要保證由小往大改,後者必須是前者的嚴格超集。
注意事項:
種類:
經常使用的是datetime和timestamp
列屬性的類別:
primary key:主鍵:非空、惟一
unique:惟一
• 考慮哪些數據類型和字符集能夠最大限度地減小存儲和磁盤 I/O。
• 使用固定長度數據類型:
– 若是存儲的全部字符串值的長度相同
• 使用可變長度數據類型:
– 若是存儲的字符串值不一樣
– 對於多字節字符集
• 對於頻繁使用的字符,使用佔用空間較少的多字節字符集。
– 使用基本多文種平面 (Basic Multilingual Plane, BMP) 以外的其餘 Unicode 字符集
INFORMATION_SCHEMA,經過這個庫提供的一些視圖,咱們能夠很是輕鬆的去獲取
對於數據庫的,統計信息。咱們也把這些叫作元數據
對於數據庫,兩個信息
• 查詢 INFORMATION_SCHEMA 數據庫表。
– 其中包含 MySQL 數據庫服務器所管理的全部對象的相關數據
• 使用 SHOW 語句。
– 用於獲取數據庫和表信息的 MySQL 專用語句
• 使用 DESCRIBE(或 DESC)語句。
– 用於檢查表結構和列屬性的快捷方式
• 使用 mysqlshow 客戶端程序。
– SHOW 語法的命令行程序
• 充當數據庫元數據的中央系統信息庫
– 模式和模式對象
– 服務器統計信息(狀態變量、設置、鏈接)
• 採用表格式以實現靈活訪問
– 使用任意 SELECT 語句
• 是「虛擬數據庫」
– 表並不是「真實」表(基表),而是「系統視圖」
– 根據當前用戶的特權動態填充表
INFORMATION_SCHEMA 表
列出 INFORMATION_SCHEMA 數據庫中全部的表:
mysql> use information_schema
mysql> show tables;
| CHARACTER_SETS |
| COLLATIONS |
| COLLATION_CHARACTER_SET_APPLICABILITY |
| COLUMNS |
| COLUMN_PRIVILEGES |
...
| USER_PRIVILEGES |
| VIEWS
查看數據庫一共有多少張表
查看元數據中的表的元數據
mysql> desc tables; +-----------------+---------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-----------------+---------------------+------+-----+---------+-------+ | TABLE_CATALOG | varchar(512) | NO | | | | | TABLE_SCHEMA | varchar(64) | NO | | | | | TABLE_NAME | varchar(64) | NO | | | | | TABLE_TYPE | varchar(64) | NO | | | | | ENGINE | varchar(64) | YES | | NULL | | | VERSION | bigint(21) unsigned | YES | | NULL | | | ROW_FORMAT | varchar(10) | YES | | NULL | | | TABLE_ROWS | bigint(21) unsigned | YES | | NULL | | | AVG_ROW_LENGTH | bigint(21) unsigned | YES | | NULL | | | DATA_LENGTH | bigint(21) unsigned | YES | | NULL | | | MAX_DATA_LENGTH | bigint(21) unsigned | YES | | NULL | | | INDEX_LENGTH | bigint(21) unsigned | YES | | NULL | | | DATA_FREE | bigint(21) unsigned | YES | | NULL | | | AUTO_INCREMENT | bigint(21) unsigned | YES | | NULL | | | CREATE_TIME | datetime | YES | | NULL | | | UPDATE_TIME | datetime | YES | | NULL | | | CHECK_TIME | datetime | YES | | NULL | | | TABLE_COLLATION | varchar(32) | YES | | NULL | | | CHECKSUM | bigint(21) unsigned | YES | | NULL | | | CREATE_OPTIONS | varchar(255) | YES | | NULL | | | TABLE_COMMENT | varchar(2048) | NO | | | | +-----------------+---------------------+------+-----+---------+-------+ 21 rows in set (0.00 sec) 查看數據庫一共有多少張表 mysql> select count(TABLE_NAME) from tables; +-------------------+ | count(TABLE_NAME) | +-------------------+ | 142 | +-------------------+ 1 row in set (0.01 sec)
對 INFORMATION_SCHEMA 使用 SELECT
• 指定要檢索哪一個表和哪些列。 • 經過使用 WHERE 子句,可僅檢索特定條件。 • 對結果分組或排序。 • 使用 JOIN、UNION 和子查詢。 • 將結果檢索到其餘表中。 • 基於 INFORMATION_SCHEMA 表建立視圖 例子:
查看world庫下的全部表的表名,引擎 mysql> SELECT TABLE_NAME, ENGINE -> FROM INFORMATION_SCHEMA.TABLES -> WHERE TABLE_SCHEMA = 'world';
mysql> SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME -> FROM INFORMATION_SCHEMA.COLUMNS -> WHERE DATA_TYPE = 'set';
mysql> SELECT CHARACTER_SET_NAME, COLLATION_NAME -> FROM INFORMATION_SCHEMA.COLLATIONS -> WHERE IS_DEFAULT = 'Yes';
每一個庫下面的表數量的統計 mysql> SELECT TABLE_SCHEMA, COUNT(*) -> FROM INFORMATION_SCHEMA.TABLES -> GROUP BY TABLE_SCHEMA;
只能查詢 mysql> DELETE FROM INFORMATION_SCHEMA.VIEWS; ERROR 1044 (42000): Access denied for user 'root'@'localhost' to database 'information_schema'
show是基於information_schema表提早作好的視圖函數
• SOHW databases:列出全部數據庫
• SHOW TABLES:列出默認數據庫中的表
• SHOW TABLES FROM <database_name>:列出指定數據庫中的表
• SHOW COLUMNS FROM <table_name>:顯示錶的列結構
• SHOW INDEX FROM <table_name>:顯示錶中有關索引和索引列的信息
• SHOW CHARACTER SET:顯示可用的字符集及其默認整理
• SHOW COLLATION:顯示每一個字符集的整理
• SHOW STATUS:列出當前數據庫狀態
• SHOW VARIABLES:列出數據庫中的參數定義值
上面的命令重點掌握
配合模糊查詢獲得咱們須要的信息
mysql> show status like '%lock%'; +------------------------------------------+-------+ | Variable_name | Value | +------------------------------------------+-------+ | Com_lock_tables | 0 | | Com_unlock_tables | 0 | | Handler_external_lock | 0 | | Innodb_row_lock_current_waits | 0 | | Innodb_row_lock_time | 0 | | Innodb_row_lock_time_avg | 0 | | Innodb_row_lock_time_max | 0 | | Innodb_row_lock_waits | 0 | | Key_blocks_not_flushed | 0 | | Key_blocks_unused | 6698 | | Key_blocks_used | 0 | | Performance_schema_locker_lost | 0 | | Performance_schema_rwlock_classes_lost | 0 | | Performance_schema_rwlock_instances_lost | 0 | | Qcache_free_blocks | 1 | | Qcache_total_blocks | 1 | | Table_locks_immediate | 119 | | Table_locks_waited | 0 | +------------------------------------------+-------+ 18 rows in set (0.00 sec)
顯示有關數據庫和表的結構的信息
– 與 SHOW 語句類似
通常語法:
shell> mysqlshow [options] [db_name [table_name [column_name]]]
選項能夠是標準鏈接參數。
顯示全部數據庫或特定數據庫、表和/或列的相關信息:
備份的普通寫法:mysqldump -uroot -ppizza123 world country >> /backup/world.bak.sql
若是有100條,要寫100次
能夠在NFORMATION_SCHEMA中查到world下的全部表
select table_schema,country from tables where table schema='world';
請按照下面的例子,按照需求拼接上面的命令並輸出到文件
注意:空格也是要標識出來的
索引類型介紹
查詢索引信息
mysql> desc test;
+-------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | char(20) | NO | MUL | NULL | |
| state | tinyint(2) | NO | | 1 | |
+-------+------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
刪除索引
mysql> alter table test drop index index_name; Query OK, 0 rows affected (0.20 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> desc test; +-------+------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | char(20) | NO | | NULL | | | state | tinyint(2) | NO | | 1 | | +-------+------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec)
或者drop index index_name on test;
查詢
desc test;
或
show index from test\G
MySQL中的約束索引
1、主鍵索引:只能有一個主鍵。 主鍵索引:列的內容是惟一值,高中學號. 表建立的時候至少要有一個主鍵索引,最好和業務無關。
走主鍵索引的查詢效率是最高的 2、普通索引 加快查詢速度,工做中優化數據庫的關鍵。 在合適的列上創建索引,讓數據查詢更高效。 create index index_name on test(name); alter table test add index index_name(name); 用了索引,查一堆內容。 在where條件關鍵字後面的列創建索引纔會加快查詢速度. select id,name from test where state=1 order by id group by name; 3、惟一索引 內容惟一,但不是主鍵。 create unique index index_name on test(name);
建立主鍵索引
1.創建表時 CREATE TABLE `test` ( `id` int(4) NOT NULL AUTO_INCREMENT, `name` char(20) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=UTF8; 2.創建表後增長 CREATE TABLE `test` ( `id` int(4) NOT NULL, `name` char(20) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=UTF8; 增長自增主鍵 alter table test change id id int(4) primary key not null auto_increment;
使用字段前綴建立索引及聯合索引
1.前綴索引:根據字段的前N個字符創建索引 create index index_name on test(name(8)); 2.聯合索引:多個字段創建一個索引。 where a女生 and b身高165 and c身材好 index(a,b,c) 特色:前綴生效特性。 a,ab,abc 能夠走索引。 b ac bc c 不走索引。 原則:把最經常使用來做爲條件查詢的列放在前面。
實例:
alter table test add sex char(4) not null;
create index ind_name_sex on test(name,sex);
explain select id,name from test where name='oldboy'\G
explain select id,name from test where sex='nv'\G
explain select id,name from test where name='oldgirl' and sex='nv'\G
聯合主鍵是聯合索引的特殊形式:
PRIMARY KEY (`Host`,`User`)
alter table test add sex char(4) not null;
create index ind_name_sex on test(name,sex);
前綴加聯合索引
create index index_name on test(name(8),sex(2));
用expain查看SQL的執行計劃
沒有索引
mysql> explain select id,name from test where name='pizza'\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: test type: ALL 表示MySQL在表中找到所需行的方式,又稱「訪問類型」 possible_keys: NULL key: NULL key_len: NULL 越小越好 ref: NULL rows: 1 Extra: Using where 1 row in set (0.08 sec) 常見的type
ALL、index、range、ref、eq_ref、const、system、null
從左到右,性能從最差到最好
mysql> alter table test add index index_name(name); Query OK, 0 rows affected (0.14 sec) Records: 0 Duplicates: 0 Warnings: 0
有索引 mysql> explain select id,name from test where name='pizza'\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: test type: ref possible_keys: index_name key: index_name key_len: 60 ref: const rows: 1 Extra: Using where; Using index 1 row in set (0.00 sec)
explain select SQL_NO_CACHE * from test where name='oldboy'\G
SQL_NO_CACHE的做用是禁止緩存查詢結果。
explain中各type類型的詳解
ALL:
Full Table Scan, MySQL將遍歷全表以找到匹配的行
若是顯示ALL,說明:
查詢沒有走索引:
1、語句自己的問題 2、索引的問題,沒創建索引 index:
Full Index Scan,index與ALL區別爲index類型只遍歷索引樹 例子: explain select count(*) from stu ; range:
索引範圍掃描,對索引的掃描開始於某一點,返回匹配值域的行。 顯而易見的索引範圍掃描是帶有between或者where子句裏帶有<,>查詢。 where 條件中有範圍查詢或模糊查詢時 > < >= <= between and in () or like 'xx%' 當mysql使用索引去查找一系列值時,例如IN()和OR列表,也會顯示range(範圍掃描)
固然性能上面是有差別的。 ref:
使用非惟一索引掃描或者惟一索引的前綴掃描,返回匹配某個單獨值的記錄行 where stu_name='xiaoming' explain select * from stu where stu_name='aa'; eq_ref:
相似ref,區別就在使用的索引是惟一索引,對於每一個索引鍵值,表中只有一條記錄匹配,簡單來講, 就是多表鏈接中使用primary key或者 unique key做爲關聯條件 join條件使用的是primary key或者 unique key const、system:
當MySQL對查詢某部分進行優化,並轉換爲一個常量時,使用這些類型訪問。 如將主鍵置於where列表中,MySQL就能將該查詢轉換爲一個常量 explain select * from city where id=1; NULL:
MySQL在優化過程當中分解語句,執行時甚至不用訪問表或索引, 例如從一個索引列裏選取最小值能夠經過單獨索引查找完成。
或者走的緩存中已經存在的
explain中的Extra
避免出現 Using temporary Using filesort Using join buffer 出現的緣由是: 排序 order by ,group by ,distinct,排序條件上沒有索引 explain select * from city where countrycode='CHN' order by population; 解決辦法: 在join 的條件列上沒有創建索引
將前一個結果保存爲視圖,再排序
數據庫索引的設計原則
爲了使索引的使用效率更高,在建立索引時
必須考慮在哪些字段上建立索引和建立什麼類型的索引。 那麼索引設計原則又是怎樣的? 1.選擇惟一性索引 惟一性索引的值是惟一的,能夠更快速的經過該索引來肯定某條記錄。 例如,學生表中學號是具備惟一性的字段。爲該字段創建惟一性索引能夠很快的肯定某個學生的信息。 若是使用姓名的話,可能存在同名現象,從而下降查詢速度。 主鍵索引和惟一鍵索引,在查詢中使用是效率最高的 2.爲常常須要排序、分組和聯合操做的字段創建索引 常常須要ORDER BY、GROUP BY、DISTINCT和UNION等操做的字段,排序操做會浪費不少時間。 若是爲其創建索引,能夠有效地避免排序操做。 3.爲常做爲查詢條件的字段創建索引 若是某個字段常常用來作查詢條件,那麼該字段的查詢速度會影響整個表的查詢速度。所以, 爲這樣的字段創建索引,能夠提升整個表的查詢速度。 可是,是否是真的適合去作索引,還要去統計一下這個列,去重以後的數量
和總行數對比,佔的數量過小,好比性別,就不合適做爲索引列 select count(DISTINCT population ) from city; select count(*) from city; 4.儘可能使用前綴來索引 若是索引字段的值很長,最好使用值的前綴來索引。例如,TEXT和BLOG類型的字段,進行全文檢索 會很浪費時間。若是隻檢索字段的前面的若干個字符,這樣能夠提升檢索速度。 ------------------------以上的是重點關注的,如下是能保證則保證的-------------------- 5.限制索引的數目 索引的數目不是越多越好。每一個索引都須要佔用磁盤空間,索引越多,須要的磁盤空間就越大。 修改表時,對索引的重構和更新很麻煩。越多的索引,會使更新表變得很浪費時間。 6.儘可能使用數據量少的索引 若是索引的值很長,那麼查詢的速度會受到影響。例如,對一個CHAR(100)類型的字段進行全文 檢索須要的時間確定要比對CHAR(10)類型的字段須要的時間要多。 7.刪除再也不使用或者不多使用的索引 表中的數據被大量更新,或者數據的使用方式被改變後,原有的一些索引可能再也不須要。數據庫管理 員應當按期找出這些索引,將它們刪除,從而減小索引對更新操做的影響。 ------------------------------2、開發規範----------------------------------------- 不走索引的狀況: 重點關注: 1) 沒有查詢條件,或者查詢條件沒有創建索引 select * from tab; 全表掃描。 select * from tab where 1=1; 在業務數據庫中,特別是數據量比較大的表。 是沒有全表掃描這種需求。 1、對用戶查看是很是痛苦的。 2、對服務器來說毀滅性的。 (1)select * from tab; SQL改寫成如下語句: selec * from tab order by price limit 10 須要在price列上創建索引 (2) select * from tab where name='zhangsan' name列沒有索引 改: 1、換成有索引的列做爲查詢條件 2、將name列創建索引 2) 查詢結果集是原表中的大部分數據,應該是30%以上。 查詢的結果集,超過了總數行數30%,優化器以爲就沒有必要走索引了。 假如:tab表 id,name id:1-100w ,id列有索引 select * from tab where id>500000; 若是業務容許,能夠使用limit控制。 怎麼改寫 ? 結合業務判斷,有沒有更好的方式。若是沒有更好的改寫方案 儘可能不要在mysql存放這個數據了。放到redis裏面。 3) 索引自己失效,統計數據不真實 索引有自我維護的能力。 對於表內容變化比較頻繁的狀況下,有可能會出現索引失效。 4) 查詢條件使用函數在索引列上,或者對索引列進行運算,運算包括(+,-,*,/,! 等) 例子: 錯誤的例子:select * from test where id-1=9; 正確的例子:select * from test where id=10; 5)隱式轉換致使索引失效.這一點應當引發重視.也是開發中常常會犯的錯誤. 因爲表的字段tu_mdn定義爲varchar2(20),但在查詢時把該字段做爲number類型以where條件傳給數據庫, 這樣會致使索引失效. 錯誤的例子:select * from test where tu_mdn=13333333333; 正確的例子:select * from test where tu_mdn='13333333333'; ------------------------ mysql> alter table tab add index inx_tel(telnum); Query OK, 0 rows affected (0.03 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> mysql> desc tab; +--------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+-------------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | varchar(20) | YES | | NULL | | | telnum | varchar(20) | YES | MUL | NULL | | +--------+-------------+------+-----+---------+-------+ 3 rows in set (0.01 sec) mysql> select * from tab where telnum='1333333'; +------+------+---------+ | id | name | telnum | +------+------+---------+ | 1 | a | 1333333 | +------+------+---------+ 1 row in set (0.00 sec) mysql> select * from tab where telnum=1333333; +------+------+---------+ | id | name | telnum | +------+------+---------+ | 1 | a | 1333333 | +------+------+---------+ 1 row in set (0.00 sec) mysql> explain select * from tab where telnum='1333333'; +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ | 1 | SIMPLE | tab | ref | inx_tel | inx_tel | 63 | const | 1 | Using index condition | +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ 1 row in set (0.00 sec) mysql> explain select * from tab where telnum=1333333; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | tab | ALL | inx_tel | NULL | NULL | NULL | 2 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec) mysql> explain select * from tab where telnum=1555555; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | tab | ALL | inx_tel | NULL | NULL | NULL | 2 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec) mysql> explain select * from tab where telnum='1555555'; +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ | 1 | SIMPLE | tab | ref | inx_tel | inx_tel | 63 | const | 1 | Using index condition | +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ 1 row in set (0.00 sec) mysql> ------------------------ 6) <> ,not in 不走索引 EXPLAIN SELECT * FROM teltab WHERE telnum <> '110'; EXPLAIN SELECT * FROM teltab WHERE telnum NOT IN ('110','119'); ------------ mysql> select * from tab where telnum <> '1555555'; +------+------+---------+ | id | name | telnum | +------+------+---------+ | 1 | a | 1333333 | +------+------+---------+ 1 row in set (0.00 sec) mysql> explain select * from tab where telnum <> '1555555'; ----- 單獨的>,<,in 有可能走,也有可能不走,和結果集有關,儘可能結合業務添加limit or或in 儘可能改爲union EXPLAIN SELECT * FROM teltab WHERE telnum IN ('110','119'); 改寫成: EXPLAIN SELECT * FROM teltab WHERE telnum='110' UNION ALL SELECT * FROM teltab WHERE telnum='119' ----------------------------------- 7) like "%_" 百分號在最前面不走 EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '31%' 走range索引掃描 EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '%110' 不走索引 %linux%類的搜索需求,能夠使用elasticsearch %linux培訓% 8) 單獨引用複合索引裏非第一位置的索引列. 列子: 複合索引: DROP TABLE t1 CREATE TABLE t1 (id INT,NAME VARCHAR(20),age INT ,sex ENUM('m','f'),money INT); ALTER TABLE t1 ADD INDEX t1_idx(money,age,sex); DESC t1 SHOW INDEX FROM t1 走索引的狀況測試: EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND age=30 AND sex='m'; EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND age=30 ; EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND sex='m'; ----->部分走索引 不走索引的: EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE age=20 EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE age=30 AND sex='m'; EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE sex='m'; ------------------------------------------------
索引的企業應用場景
企業SQL優化思路: 1、把一個大的不使用索引的SQL語句按照功能進行拆分 2、長的SQL語句沒法使用索引,能不能變成2條短的SQL語句讓它分別使用上索引。 3、對SQL語句功能的拆分和修改 4、減小「爛」SQL 由運維(DBA)和開發交流(確認),共同肯定如何改,最終由DBA執行 5、制定開發流程 不適合走索引的場景: 1、惟一值少的列上不適合創建索引或者創建索引效率低。例如:性別列 2、小表能夠不創建索引,100條記錄。 3、對於數據倉庫,大量全表掃描的狀況,建索引反而會慢 查看錶的惟一值數量: select count(distinct user) from mysql.user; select count(distinct user,host) from mysql.user; 建索引流程: 1、找到慢SQL。 show processlist; 記錄慢查詢日誌。 2、explain select句,條件列多。 3、查看錶的惟一值數量: select count(distinct user) from mysql.user; select count(distinct user,host) from mysql.user; 條件列多。能夠考慮創建聯合索引。 4、創建索引(流量低谷) force index 5、拆開語句(和開發)。 6、like '%%'不用mysql
文件系統: - 操做系統組織和存取數據的一種機制。 - 文件系統是一種軟件。 類型:ext2 3 4 ,xfs 數據 - 無論使用什麼文件系統,數據內容不會變化 - 不一樣的是,存儲空間、大小、速度。 MySQL引擎: - 能夠理解爲,MySQL的「文件系統」,只不過功能更增強大。 MySQL引擎功能: - 除了能夠提供基本的存取功能,還有更多功能事務功能、鎖定、備份和恢復、優化以及特殊功能。
MySQL 提供如下存儲引擎:
- InnoDB
- MyISAM
InnoDB 和 MyISAM最經常使用
- MEMORY
- ARCHIVE
- FEDERATED
- EXAMPLE
- BLACKHOLE
- MERGE
- NDBCLUSTER
- CSV
還能夠使用第三方存儲引擎(TokuDB)。用於zabbix和爬蟲的存儲,inno操做頗有效,壓縮性
重點理解:事務、鎖定粒度(行)、備份和恢復、自動故障恢復
查看
1、使用 SELECT 確認會話存儲引擎: SELECT @@default_storage_engine;
查看全部的存儲引擎
show engines; 2、使用 SHOW 確認每一個表的存儲引擎: SHOW CREATE TABLE City\G SHOW TABLE STATUS LIKE 'CountryLanguage'\G 3、使用 INFORMATION_SCHEMA 確認每一個表的存儲引擎: SELECT TABLE_NAME, ENGINE
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'world'
AND TABLE_SCHEMA = 'world';
+-----------------+--------+
| TABLE_NAME | ENGINE |
+-----------------+--------+
| city | InnoDB |
| country | InnoDB |
| countrylanguage | InnoDB |
| test | InnoDB |
+-----------------+--------+
四、mysql> show variables like '%engine%';
+----------------------------+--------+
| Variable_name | Value |
+----------------------------+--------+
| default_storage_engine | InnoDB |
| default_tmp_storage_engine | InnoDB |
| storage_engine | InnoDB |
+----------------------------+--------+
3 rows in set (0.00 sec)
下列查詢語句都對應查詢了什麼?
show engines;
show create table city;
show table status like 'city'\G
select table_schema,table_name,engine from information_schema.tables where table_schema='world';
select table_schema,table_name,engine from information_schema.tables where table_schema='mysql';
select table_schema,table_name,engine from information_schema.tables where engine='csv';
設置
0、在編譯的時候也能夠設置
1、在啓動配置文件中設置服務器存儲引擎:
vim /etc/my.cnf [mysqld] default-storage-engine=<Storage Engine> 2、使用 SET 命令爲當前客戶機會話設置: SET @@storage_engine=<Storage Engine>; 3、在 CREATE TABLE 語句指定: CREATE TABLE t (i INT) ENGINE = <Storage Engine>;
表空間的概念由orcle引入
InnoDB 系統表空間
- 默認狀況下,InnoDB 元數據、撤消日誌和緩衝區存儲在系統「表空間」中。
- 這是單個邏輯存儲區域,能夠包含一個或多個文件。
- 每一個文件能夠是常規文件或原始分區。
- 最後的文件能夠自動擴展。
如今已經不用於生產數據的存儲了,只用於存系統文件。
經過添加數據文件增長表空間大小。 在 my.cnf 文件中使用 innodb_data_file_path 選項。 [mysqld] innodb_data_file_path=datafile_spec1[;datafile_spec2]... 配置示例:建立一個表空間,
其中包含一個名爲 ibdata1 且大小爲 50 MB(固定)的數據文件和
一個名爲 ibdata2 且大小爲 50 MB(自動擴展)的數據文件: [mysqld] innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend 默認狀況下將文件放置在 data 目錄中。 若是須要,顯式指定文件位置。
innodb_data_file_path=ibdata1:12M;ibdata2:50M:autoextend ----錯誤的配置XXX
innodb_data_file_path=ibdata1:76M;ibdata2:50M:autoextend ----正確的配置,看實際而定
查看錶空間設置
修改以前:
mysql> show variables like '%data%';
+-------------------------------+---------------------------------+
| Variable_name | Value |
+-------------------------------+---------------------------------+
| character_set_database | utf8 |
| collation_database | utf8_general_ci |
| datadir | /application/mysql-5.6.43/data/ |
| innodb_data_file_path | ibdata1:12M:autoextend |
修改以前先看一下,文件的大小,不然就是錯誤的修改,將致使數據庫啓動時報錯,沒法啓動
[root@web01 data]# du -h ibdata1
12M ibdata1
這第一個的大小,不能大也不能小
innodb_data_file_path=ibdata1:12M;ibdata2:50M:autoextend
修改後,重啓,再次查看
mysql> show variables like '%data%';
+-------------------------------+------------------------------------+
| Variable_name | Value |
+-------------------------------+------------------------------------+
| character_set_database | utf8 |
| collation_database | utf8_general_ci |
| datadir | /application/mysql-5.6.43/data/ |
| innodb_data_file_path | ibdata1:12M;ibdata2:50M:autoextend |
已經改變了!
最好在裝完軟件後就設置好
除了系統表空間以外,InnoDB 還在數據庫目錄中建立另外的表空間,用於每一個 InnoDB 表的 .ibd 文件。 InnoDB 建立的每一個新表在數據庫目錄中設置一個 .ibd 文件來搭配表的 .frm 文件。
固然,也會想系統空間存放元數據信息(存在哪一個庫,空間佔用是多少,索引信息) 能夠使用 innodb_file_per_table 選項控制此設置, 更改該設置僅會更改已建立的新表的默認值。 注:在mysql5.6開始,默認的配置爲: | innodb_file_per_table | ON |
在mysql內部有專門刪除或者導入ibd的功能
alter table test discard tablespace;
簡介
一組數據操做執行步驟,這些步驟被視爲一個工做單元
- 用於對多個語句進行分組
- 能夠在多個客戶機併發訪問同一個表中的數據時使用
全部步驟都成功或都失敗
- 若是全部步驟正常,則執行
- 若是步驟出現錯誤或不完整,則取消
Atomic(原子性)
全部語句做爲一個單元所有成功執行或所有取消。
Consistent(一致性)
若是數據庫在事務開始時處於一致狀態,則在執行該事務期間將保留一致狀態。
Isolated(隔離性)
事務之間不相互影響。
Durable(持久性)
事務成功完成後,所作的全部更改都會準確地記錄在數據庫中。所作的更改不會丟失。
標準的事務語句,就只是DML語句,insert、update、delete
只要看到有DML標準語句,系統不須要begin就開始事務了,這是5.6後的新特性
START TRANSACTION(或 BEGIN):顯式開始一個新事務
SAVEPOINT:分配事務過程當中的一個位置,以供未來引用
COMMIT:永久記錄當前事務所作的更改,說明事務要提交,要完成了
ROLLBACK:取消當前事務所作的更改
ROLLBACK TO SAVEPOINT:取消在 savepoint 以後執行的更改
RELEASE SAVEPOINT:刪除 savepoint 標識符
SET AUTOCOMMIT:爲當前鏈接禁用或啓用默認 autocommit 模式
查看autocommit的狀態
mysql> show variables like '%autocommit%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set (0.00 sec)
在事務性的應用場景下,要改爲OFF,避免寫一句就提交,寫一句就提交
查看全局的
show global variables like '%autocommit%';
在MySQL5.5開始,開啓事務時再也不須要begin或者start transaction語句。
而且,默認是開啓了Autocommit模式,做爲一個事務隱式提交每一個語句。 在有些業務繁忙企業場景下,這種配置可能會對性能產生很大影響,但對於安全性上有很大提升。 未來,咱們須要去權衡咱們的業務需求去調整是否自動提交。 咱們能夠經過如下命令進行修改關閉(0是關閉,1是開啓): SET GLOBAL AUTOCOMMIT=0; - 全部新建會話
SET SESSION AUTOCOMMIT=0; - 當前會話 SELECT @@AUTOCOMMIT; - 查看設置結果 咱們也能夠修改配置文件讓其永久生效: vim /etc/my.cnf [mysqld] AUTOCOMMIT=0
用於隱式提交的 SQL 語句: START TRANSACTION,也就是以前有一個Begin或者START TRANSACTION SET AUTOCOMMIT = 1 致使提交的非事務語句: DDL語句: (ALTER、CREATE 和 DROP) DCL語句: (GRANT、REVOKE 和 SET PASSWORD) 鎖定語句:(LOCK TABLES 和 UNLOCK TABLES) 致使隱式提交的語句示例: TRUNCATE TABLE LOAD DATA INFILE SELECT FOR UPDATE
Redo是什麼?
redo,顧名思義「重作日誌」,是事務日誌的一種。
做用是什麼?
在事務ACID過程當中,實現的是「D」持久化的做用。
記錄數據頁的變化
每次都提交,過多的IO操做會影響性能,因此有了Redo
undo是什麼?
undo,顧名思義「回滾日誌」,是事務日誌的一種。
做用是什麼?
在事務ACID過程當中,實現的是「A、C」原子性和一致性的做用。
什麼是「鎖」?
「鎖」顧名思義就是鎖定的意思。
「鎖」的做用是什麼?
在事務ACID過程當中,「鎖」和「隔離級別」一塊兒來實現「I」隔離性的做用。
避免爭搶資源
鎖的粒度:
一、MyIasm:低併發鎖——表級鎖
二、Innodb:高併發鎖——行級鎖
四種隔離級別
READ UNCOMMITTED 容許事務查看其餘事務所進行的未提交更改 READ COMMITTED 容許事務查看其餘事務所進行的已提交更改 REPEATABLE READ****** 確保每一個事務的 SELECT 輸出一致
InnoDB 的默認級別 SERIALIZABLE 將一個事務的結果與其餘事務徹底隔離
mysql> show variables like '%iso%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
配置方法: [mysqld] log-error=/data/mysql/mysql.log 查看配置方式: mysql> show variables like '%log%error%';
mysql> show variables like '%log_error%';
+---------------------+--------------+
| Variable_name | Value |
+---------------------+--------------+
| binlog_error_action | IGNORE_ERROR |
| log_error | ./web01.err |
+---------------------+--------------+
2 rows in set (0.00 sec)
不進行設置,默認在上面的目錄 做用: 記錄mysql數據庫的通常狀態信息及報錯信息,是咱們對於數據庫常規報錯處理的經常使用日誌。
配置方法: [mysqld] general_log=on general_log_file=/data/mysql/server2.log 查看配置方式: show variables like '%gen%'; 做用: 記錄mysql全部執行成功的SQL語句信息,能夠作審計用,可是咱們不多開啓
1、二進制日誌都記錄了什麼? 已提交的數據記錄,以event的形式記錄到二進制文件中
只記錄增刪改 2、二進制記錄格式有哪些? row:行模式,即數據行的變化過程,上圖中Age=19修改爲Age=20的過程事件。
行模式相比語句模式,臃腫,它要記錄每一行的變化 statement:語句模式,上圖中將update語句進行記錄。
記錄函數類的操做,不是特別的準確,好比插入了一個時間函數now() mixed:以上二者的混合模式。 3、三種模式有什麼優缺點? 4、binlog的做用 備份恢復、複製
查看模式的設置
mysql> show variables like '%binlog_format%';
+---------------+-----------+
| Variable_name | Value |
+---------------+-----------+
| binlog_format | STATEMENT |
+---------------+-----------+
1 row in set (0.00 sec)
二進制日誌是否開啓的查看
mysql> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | OFF | 關閉的
+---------------+-------+
1 row in set (0.00 sec
二進制日誌管理
1、開啓二進制日誌 set sql_log_bin=0 在會話級別修改成臨時關閉 vi /etc/my.cnf log-bin=/data/mysql/mysql-bin 在全局打開binlog 2、設置二進制日誌記錄格式(建議是ROW): 配置文件中修改: binlog-format=ROW 命令行修改 mysql> SET GLOBAL binlog_format = 'STATEMENT'; mysql> SET GLOBAL binlog_format = 'ROW'; mysql> SET GLOBAL binlog_format = 'MIXED'; 3、查看binlog設置 show variables like '%binlog%';
+-----------------------------------------+----------------------+
| Variable_name | Value |
+-----------------------------------------+----------------------+
| binlog_cache_size | 32768 |
| binlog_checksum | CRC32 |
| binlog_direct_non_transactional_updates | OFF |
| binlog_error_action | IGNORE_ERROR |
| binlog_format | STATEMENT |
| binlog_gtid_simple_recovery | OFF |
| binlog_max_flush_queue_time | 0 |
| binlog_order_commits | ON |
| binlog_row_image | FULL |
| binlog_rows_query_log_events | OFF |
| binlog_stmt_cache_size | 32768 |
| binlogging_impossible_mode | IGNORE_ERROR |
| innodb_api_enable_binlog | OFF |
| innodb_locks_unsafe_for_binlog | OFF |
| max_binlog_cache_size | 18446744073709547520 |
| max_binlog_size | 1073741824 |
| max_binlog_stmt_cache_size | 18446744073709547520 |
| simplified_binlog_gtid_recovery | OFF |
| sync_binlog | 0 |何時寫入到磁盤上
設置爲1 ,每次事務提交commit就binlog cache刷新,0就是達到內存大小才寫入
+-----------------------------------------+----------------------+
19 rows in set (0.00 sec)
設置文件中的內容
cat /etc/my.cnf
-------------------------------------------
[mysqld]
basedir=/appliacation/mysql
datadir=/application/mysql/data
soket=/appliacation/mysql/tmp/mysql.sock
port=3306
server_id=10
log-error=/var/log/mysql.log
log-bin=/application/mysql/data/mysql-bin
binlog_format=row
skip_name_resolve
innodb_data_file_path=ibdata1:76M;abdata2:50M:autoexend
default_storage_engine=innodb
character-set-server=utf8
antocommit=0
sync_binlog=1
[mysql]
socket=/application/mysql/tmp/mysql.sock
default-character-set=utf8
--------------------------------------------
查詢二進制日誌文件
ls -l /data/mysql/mysql-bin*
或者在mysql中使用命令
mysql> SHOW BINARY LOGS;
+---------------+-----------+
| Log_name | File_size |
+---------------+-----------+
| binlog.000015 | 724935 |
| binlog.000016 | 733481 |
查看當前在使用的binlog
mysql> SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| binlog.000016 | 733481 | world_innodb | manual,mysql
刷新二進制日誌
flush logs
截取二進制日誌
mysqlbinlog --start-position= --stop-position= >a.sql
刪除二進制:
默認狀況下,不會刪除舊的日誌文件。
根據存在時間刪除日誌:
SET GLOBAL expire_logs_days = 7;
…或者…
PURGE BINARY LOGS BEFORE now() - INTERVAL 3 day; 刪除3天以前的,手工
根據文件名刪除日誌:
PURGE BINARY LOGS TO 'mysql-bin.000010'; 刪除到那個文件
help purge binary logs 查看幫助
reset master 重第一個開始從新開始記錄,以前都刪除了
問題:
一、什麼是事件?
二、什麼是position?
獲取二進制日誌的內容及事件,在一系列sql操做後,並commit後,能夠看到日誌內容
shell中使用mysqlbinlog /data/mysql/mysql-bin.000016
或者
sql中使用show binlog events in ‘mysql-bin.000016
可是看不到DML詳細的命令,能夠使用參數(mysqlbinlog --help|more)--base64-output=decode-rows 改變輸出
mysqlbinlog --base64-output=decode-rows -v /data/mysql/mysql-bin.000016
命令小結
show binary logs; 查詢二進制日誌文件 show binlog events in 'my-bin.000002' 查看日誌中的事件 show master status; 查看當前在使用的binlog mysqlbinlog --base64-output=decode-rows -v my-bin.000002 查看日誌轉碼後的 詳細結果,有DML語句的執行過程 mysqlbinlog --start-position=120 --stop-position=721 my-bin.000002 截取 mysqlbinlog --start-position=340 --stop-position=721 my-bin.000002 >/tmp/binlog.sql
二進制日誌管理實戰
1、經過截取binlog恢復損壞數據
set sql_log_bin=0 臨時關閉二進制日誌記錄,不記錄恢復語句
commit
source //tmp/binlog.sql
二、若是咱們沒有提早去備份binlog,未來在誤操做以後,有如何恢復呢?
去截取到誤操做以前的全部操做,沒有開始標記了
mysqlbinlog --stop-position=721 my-bin.000002 >/tmp/binlog.sql
3、二進制日誌翻轉實現閃回數據(擴展)
一年多的二進制文件,極大,極多,如何快速恢復
慢查詢日誌 是將mysql服務器中影響數據庫性能的相關SQL語句記錄到日誌文件 經過對這些特殊的SQL語句分析,改進以達到提升數據庫性能的目的。 慢日誌設置 long_query_time : 設定慢查詢的閥值,超出次設定值的SQL即被記錄到慢查詢日誌,缺省值爲10s slow_query_log : 指定是否開啓慢查詢日誌 slow_query_log_file : 指定慢日誌文件存放位置,能夠爲空,系統會給一個缺省的文件host_name-slow.log min_examined_row_limit:查詢檢查返回少於該參數指定行的SQL不被記錄到慢查詢日誌 log_queries_not_using_indexes: 不使用索引的慢查詢日誌是否記錄到索引
配置例子
slow_query_log=1
slow_query_log_file=/data/slow/slow.log (必需要有這個文件,且有權限
long_query_time=0.5 (單位是s,)
log_queries_not_using_indexes
加入到/etc/my.cnf
# min_examined_row_limit=100 (少於100行,認爲他沒問題,儘可能不用,若是查詢半小時,返回少於100)
mysql中查看配置
mysql> show variables like '%slow%';
+---------------------------+---------------------+
| Variable_name | Value |
+---------------------------+---------------------+
| log_slow_admin_statements | OFF |
| log_slow_slave_statements | OFF |
| slow_launch_time | 2 |
| slow_query_log | ON |
| slow_query_log_file | /data/slow/slow.log |
+---------------------------+---------------------+
5 rows in set (0.00 sec)
查看慢查詢超時時間
mysql> show variables like '%long_que%';
+-----------------+----------+
| Variable_name | Value |
+-----------------+----------+
| long_query_time | 0.500000 |
+-----------------+----------+
1 row in set (0.00 sec)
查看 不使用 索引 是否記錄的設置
mysql> show variables like '%indexes%';
+----------------------------------------+-------+
| Variable_name | Value |
+----------------------------------------+-------+
| log_queries_not_using_indexes | ON |
| log_throttle_queries_not_using_indexes | 0 |
+----------------------------------------+-------+
2 rows in set (0.00 sec)
mysqldumpslow 如何處理慢日誌
記錄到慢日誌中的日誌是沒有順序的,它是追加的模式
mysqldumpslow命令
mysqldumpslow -s c -t 10 /data/slow/slow.log 次數
mysqldumpslow -s at -t 10 /data/slow/slow.log 時間
這會輸出記錄次數最多的10條SQL語句,其中: -s 是表示按照何種方式排序,
c、t、l、r分別是按照記錄次數、時間、查詢時間、返回的記錄數來排序,
ac、at、al、ar,表示相應的倒敘; -t 是top n的意思,即爲返回前面多少條的數據;
----擴展工具---
pt-query-diagest 自動作判斷,先優化哪個 percona-toolkit 裏面的
mysqlsla
重要的是先找到,哪條語句最慢,並且執行次數最多
理論狀況下,只要有二進制日誌文件在,我就能夠將數據庫恢復到任意時刻
可是,有一個前提,必須是全量
並且,二進制文件只適合短時間的恢復
運維工做的核心簡單歸納就兩件事:
備份的類型
備份方式
邏輯備份(文本表示:SQL 語句) (1)mysqldump---->建庫、建表、數據插入 (2)基於二進制日誌:數據庫的全部變化類的操做 (3)基於複製的備份:將二進制日誌實時傳送到另外一臺機器而且恢復 物理備份(數據文件的二進制副本) (1)xtrabackup進行物理備份 (2)拷貝數據文件(冷備) 增量備份(刷新二進制日誌) 基於複製的備份
一、mysqldump
mysql原生自帶很好用的邏輯備份工具
二、mysqlbinlog
實現binlog備份的原生態命令
三、xtrabackup
precona公司開發的性能很高的物理備份工具
優勢:邏輯備份工具,都是SQL語句,都是文本格式,便於查看和編輯,更便於壓縮
缺點:備份效率慢
mysqldump經常使用參數 -u -p -h -S -P 首先是連接到數據庫 -A, --all-databases 全庫備份
例子:mysqldump -uroot -p123 -A >/backup/full.sql -B,單庫備份
- 例子:
mysqldump -uroot -p123 -B lufei >/backup/lufei.sql
mysqldump -uroot -p123 lufei >/backup/lufei1.sql
- 區別:
加-B,增長建庫(create)及「use庫」的語句,在未來恢復時,不須要手工進行建庫和use
不加-B,須要恢復時,先建立庫,use到庫下再進行恢復
- 另外,-B選項還能夠實現,同時備份多個庫,備份到同一個文件中
mysqldump -uroot -p123 -B lufei oldboy>/backup/lufei_oldboy.sql
不加-B,去備份,他的功能是備份路飛數據庫下的oldboy表
mysqldump -uroot -p123 lufei oldboy>/backup/lufei_oldboy.sql
mysqldump 庫1 表1 表2 表3 >庫1.sql
生產環境下,也要加的額外參數 -R, --routines 備份存儲過程和函數數據 --triggers 備份觸發器數據
mysqldump -uroot -p123 -A -R --triggers >/backup/full.sql 備份多個表: mysqldump 庫1 表1 表2 表3 >庫1.sql mysqldump 庫2 表1 表2 表3 >庫2.sql -F, --flush-logs 備份時刷新binlog日誌(回顧binlog),爲了方便未來二進制截取時的起點 天天晚上0點備份數據庫 mysqldump -A -B -F >/opt/$(date +%F).sql
提示:每一個庫都會刷新一次.
即,-F會根據有多少個庫,刷新出多少個二進制文件 [root@db02 ~]# ll /application/mysql/logs/ -rw-rw---- 1 mysql mysql 168 Jun 21 12:06 oldboy-bin.000001 -rw-rw---- 1 mysql mysql 168 Jun 21 12:06 oldboy-bin.000002 -rw-rw---- 1 mysql mysql 210 Jun 21 12:07 oldboy-bin.index
一個解決每一個庫都會刷新的參數 --master-data={1|2} 告訴你備份時刻的binlog位置,通常咱們選擇使用2,以註釋的方式記錄二進制日誌位置 2 註釋 1 非註釋,要執行(主從複製) mysqldump -uroot -p123 -A --master-data=2 >/backup/full.sql
看一下記錄: [root@db02 logs]# sed -n '22p' /opt/t.sql -- CHANGE MASTER TO MASTER_LOG_FILE='oldboy-bin.000005', MASTER_LOG_POS=344; [root@db02 logs]# mysqldump -B --master-data=2 oldboy >/opt/t.sql 鎖表:適合全部引擎(myisam,innodb) (溫備份) -x, --lock-all-tables -l, --lock-tables mysqldump -B -x oldboy >/opt/t.sql 有了--master-data 就不用鎖表參數了 基於事務引擎:不用鎖表就能夠得到一致性的備份. 生產中99% 使用innodb事務引擎. ACID四大特性中的隔離性 --single-transaction 對innodb引擎進行熱備
mysqldump -uroot -p123 -A -R --triggers --master-data=2 --single-transaction >/backup/full.sql
這是比較合適的備份方式
熱備,就是不須要鎖表,它是以快照的方式實現熱備 舉例子:查人數,把教室的學員照個相,在相片上點數 壓縮備份:壓縮比很高 mysqldump -B --master-data=2 oldboy|gzip >/opt/t.sql.gz 解壓: zcat t.sql.gz >t1.sql gzip -d t.sql.gz #刪壓縮包 適合多引擎混合(例如:myisam與innodb混合)的備份命令以下: mysqldump -A -R --triggers --master-data=2 --single-transaction |gzip >/opt/all_$(date +%F).sql.gz
使用source命令進行恢復:
mysql>set sql_log_bin=0; 臨時不向二進制文件記錄
mysql> source /opt/xxx.sql;
背景環境: 正在運行的網站系統,mysql數據庫,數據量25G,日業務增量10-15M。 備份方式: 天天23:00點,計劃任務調用mysqldump執行全備腳本 故障時間點: 上午10點,誤刪除了一個表 如何恢復? 思路: 1、斷開業務,防止對數據庫二次傷害,掛出維護頁面 2、搭建備用庫,恢復全備 3、截取昨天晚上23:00以後到上午10點誤刪除操做以前的二進制日誌 4、恢復到備用庫,驗證數據可用性和完整性 5、兩種方案恢復前端應用 5.1 備用庫導出誤刪除的表,導入到生產庫,開啓業務 5.2 直接將應用切割到備用庫,替代生產庫,開啓業務 ------------------ 模擬故障並恢復:
0、爲了模擬 二進制全清除,
mysql>reset master;
刪除原庫數據
cd /application/mysql/data
\rm -rf *
pkill mysqld
初始化
/application/mysql/script/mysql_install_db --basedir=/application/mysql --datadir=/application/data --user=mysql
啓動
/etc/init.d/mysqld start
mysql 1、插入原始數據: mysql> create database oldboy; mysql> use oldboy mysql> create table t1 (id int,name varchar(20)); mysql> insert into t1 values (1,'zhang3'); mysql> insert into t1 values (2,'li4'); mysql> insert into t1 values (3,'wang5'); mysql> commit; 2、模擬前一天晚上23:00全備 mysqldump -A -R --triggers --master-data=2 --single-transaction |gzip >/backup/all_$(date +%F).sql.gz 3、模擬白天(23:00-10:00)業務對數據的修改 mysql> insert into t1 values (4,'zhang33'); mysql> insert into t1 values (5,'li44'); mysql> insert into t1 values (6,'wang54'); mysql> commit; 4、模擬故障 drop table t1; 5、恢復 (1)準備全備,並獲取到備份文件中的binlog的截取起點 gunzip all_2018-04-04.sql.gz -- CHANGE MASTER TO MASTER_LOG_FILE='my-bin.000004', MASTER_LOG_POS=731; (2)截取二進制日誌
查看刪庫前的日誌
mysql>show binlog events in 'my-bin.000004',找到刪除以前的位置
mysqlbinlog --start-position=731 --stop-position=1126 /data/binlog/my-bin.000004 >/backup/binlog.sql ----- show binlog events in 'my-bin.000004'; ----》drop以前的position爲1126 ----- (3)恢復全備+binlog set sql_log_Bin=0; source /backup/all_2018-04-04.sql; source /backup/binlog.sql
Xtrabackup介紹
percona公司的備份工具,性能比較高。物理備份工具。 特色: 物理備份工具,在同級數據量基礎上,都要比邏輯備份性能要好的多。 特別是在數據量比較大的時候,體現的更加明顯。 備份方式: 1、拷貝數據文件 2、拷貝數據頁 備份原理(innodb): 1、對於innodb表,能夠實現熱備 (1)在數據還有修改操做的時刻,直接將數據文件中的數據頁備份 此時,備份走的數據對於當前mysql來說是不一致。 (2)將備份過程當中的redo和undo一併備走。 (3)爲了恢復的時候,只要保證備份出來的數據頁LSN 能和redo LSN匹配, 未來恢復的就是一致的數據。redo應用和undo的應用。 2、對與myisam表,實現自動鎖表拷貝文件。
Xtrabackup安裝
1、安裝 wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo yum -y install perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.4/binary/redhat/6/x86_64/percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm yum -y install percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm 備份命令: xtrabackup innobackupex ******
依賴配置文件,須要配置好
Xtrabackup全備份及恢復實戰
建立備份目錄 mkdir /server/backup -p
全備完整命令 innobackupex --user=root --password=oldboy123
--socket=/application/mysql-5.6.34/tmp/mysql.sock
--no-timestamp /server/backup/full
由於是新庫,且配置文件中指定可sock簡單的命令
innobackupex /server/backup/
默認是備份到以時間戳做爲目錄名的目錄中,加參數後,備份到指定目錄
innobackupex --no-timestamp /server/backup/full
全備的回覆例子: 一、恢復數據前的準備(合併xtabackup_log_file和備份的物理文件),由於備份時把redo和undo也備走了
-use-memory:恢復的時候,單獨指定一個內存,屬於優化的細節
--apply-log:作操做-->恢復數據前的準備(合併xtabackup_log_file和備份的物理文件) innobackupex --apply-log --use-memory=32M /server/backup/full/
二、模擬故障
停庫: Kill -9 pid lsof -i :3306 破壞數據: cd /application/mysql/data mv data /opt/ 或者 \rm -rf *
三、恢復 cp -a /server/backup/full/ /application/mysql/data
或者
innobackupex --copy-back /server/backup/full/
注意:恢復時,要確認數據路徑是空的,而且數據庫是停掉的
chown -R mysql.mysql /application/mysql/data 啓動: /etc/init.d/mysqld start mysql -e "select * from oldboy.test" 注:咱們還能夠使用—copy-back參數進行恢復
Xtrabackup實現增量備份與恢復實戰
1、全備: innobackupex --user=root --password=123 --no-timestamp /backup/full/ 2、模擬數據變化 3、第一增量: innobackupex --user=root --password=123 --incremental --no-timestamp --incremental-basedir=/backup/full/ /backup/inc1 4、模擬數據變化 5、第二次增量: innobackupex --user=root --password=123 --incremental --no-timestamp --incremental-basedir=/backup/inc1 /backup/inc2 6、模擬數據損壞 7、恢復數據: innobackupex --apply-log --redo-only /backup/full
沒法直接恢復,要依賴全備,合併 innobackupex --apply-log --redo-only --incremental-dir=/backup/inc1 /backup/full innobackupex --apply-log --incremental-dir=/backup/inc2 /backup/full innobackupex --apply-log /backup/full
--redo-only:只把已提交的事務合併,不合並undo。除了最後一次增量,都要加上這個參數
把原有的數據刪掉,必須是空的
cd /application/mysql/data
\rm -rf *
停庫
pkill mysqld
innobackupex --copy-back /backup/full/
Xtrabackup企業級增量備份實戰
背景: 某大型網站,mysql數據庫,數據量500G,每日更新量100M-200M 備份策略: xtrabackup,每週日0:00進行全備,週一到週六00:00進行增量備份。 故障場景: 週三上午10點出現數據庫意外刪除表操做。 如何恢復?
思路:
一、停業務,掛維護頁
二、找備用庫
三、合併full+inc1+inc2
四、截取週二晚上inc2備份後到週三上午10點,t1表刪除以前的binlog日誌
五、將合併後的full+截取的binlog恢復到備用庫
六、驗證數據可用性和完整性
七、使用備用庫替代生產庫使用 或者 將t1表導出並導入回生產庫
八、業務恢復
-----------------
-----------------
思考:以上恢復策略是否能夠優化?
爲了恢復1G表,須要將整個全備恢復,有必要嗎?有什麼好的解決辦法?
drop table t1;
create table t1 (id int,name varchar(20)); 建立表結構,和原來的表結構如出一轍
alter table t1 discard tablespace; 在數據庫內部刪除
cd /application/mysql/data/oldboy
cp /backup/full/oldboy/t1.ibd ./ 將備份中的.ibd文件拷貝到新建的表下面
chown -R mysql.mysql * 修改文件的權限歸屬
alter table t1 import tablespace; 導入數據
複製能爲咱們作什麼?
複製是 MySQL 的一項功能,容許服務器將更改從一個實例複製到另外一個實例。
- 主服務器將全部數據和結構更改記錄到二進制日誌中。
- 從屬服務器從主服務器請求該二進制日誌並在本地應用其內容。
主從複製的前提
1.1 兩臺以上mysql實例 多臺物理機 多個mysql實例 1.2 主庫要開啓二進制日誌 1.3 主庫要提供複製相關的用戶 replication slave,一個比較特殊的權限 grant replication slave on *.* to repl@'10.0.0.%' identified by '123'; 1.4 從庫須要將和主庫相差的數據,進行追加 通常狀況下能夠人爲備份主庫數據,恢復到從庫上 1.5 從應該從恢復以後的時間點,開始自動從主庫獲取新的二進制日誌開始應用 咱們須要人爲告訴從庫,從哪開始自動開始複製二進制日誌(file+position),另外還須要告訴從庫user,passwd,port,ip change master to 命令根據mster.info中的參數 來鏈接主庫
複製中的線程
1、主庫 Dump thread:在複製過程當中,主庫發送二進制日誌的線程 2、從庫 IO thread:向主庫請求二進制日誌,而且接受二進制日誌的線程 SQL thread:執行請求過來的二進制線程
複製中的文件
1、主庫 binlog:主庫的二進制文件 2、從庫 Relay-log:中繼日誌,存儲請求過來的二進制日誌 Relay-index: Master.info:
一、從庫鏈接主庫的重要參數(user,passwd,ip,port)
二、上次獲取過的主庫二進制日誌的位置 Relay-log.info:存儲從庫SQL線程已經執行過的relaylog日誌位置
主從複製的工做原理
3.1 從庫,IO線程,讀取master.info中的信息, 獲取到鏈接參數(user\passwd\ip\port)+上次請求過的主庫的binlog的位置(例子:mysql-bin.000003,position=640) 3.2 IO線程使用連接到主庫,拿着位置信息(mysql-bin.000003,position=640),問主庫有沒有比這個更新的二進制日誌。 3.3 主庫查詢二進制日誌,並對比從庫發送過來的位置信息(mysql-bin.000003,position=640),若是有新的二進制日誌,會經過 dump thread發送給從庫。 3.4 從庫經過IO線程,接受主庫發來的二進制日誌,存儲到TCP/IP緩存中,而且返回「ACK」確認給主庫,這時主庫收到ACK後, 就認爲複製完成了,能夠繼續其餘工做了。 3.5 從庫更新master.info,二進制日誌位置更新爲新的位置信息。 3.6 從庫IO線程會將TCP/IP緩存中的日誌,存儲到relay-log中繼日誌文件中。 3.7 從庫SQL線程,讀取relay-log.info,獲取到上次執行到的relaylog日誌位置,以這個位置信息做爲起點,日後繼續執行中繼日誌。 3.8 SQL線程執行完成全部relay以後,會更新relay-log.info信息爲新位置信息。 到此爲止,一次完整的複製過程就完成了。
思路: 1、兩個節點 2、主庫binlog開啓,從庫開啓relay-log 3、server-id不一樣 4、主庫建立複製帳戶 5、主庫備份並記錄二進制文件和position 6、從庫change master to鏈接主庫 7、啓動從庫複製 8、驗證主從 詳細配置過程,請看配置文檔。
配置步驟
主從複製搭建實戰: 1、準備環境 思路: 1、兩個以上節點(多實例) 3307:master 3308:slave1 3309:slave2 2、主庫binlog開啓,從庫開啓relay-log(默認在數據目錄下生成) vim /data/3307/my.cnf log-bin=/data/3307/mysql-bin binlog_format=row 3、server-id不一樣 [root@db02 data]# cat /data/3307/my.cnf |grep server-id server-id=3307 [root@db02 data]# cat /data/3308/my.cnf |grep server-id server-id=3308 [root@db02 data]# cat /data/3309/my.cnf |grep server-id server-id=3309 4、關閉數據庫的自動域名解析 每一個節點都加入如下配置:vim /data/3307{8|9}/my.cnf skip-name-resolve 5、啓動多實例 mysqld_safe --defaults-file=/data/3307/my.cnf & mysqld_safe --defaults-file=/data/3308/my.cnf & mysqld_safe --defaults-file=/data/3309/my.cnf & 6、主庫建立複製帳戶 鏈接到主庫: mysql -S /data/3307/mysql.sock grant replication slave on *.* to repl@'10.0.0.%' identified by '123'; 7、從庫數據的追加 (1)不須要追加的狀況 主和從同時搭建的新環境,就不須要備份主庫數據,恢復到從庫了,直接從第一個binlog(mysql-bin.000001)的開頭位置(120) (2)若是主庫已經工做了很長時間了,咱們通常須要備份主庫數據,恢復到從庫,而後從庫從備份的時間點起自動進行復制 重點針對第二種狀況進行演示: 備份主庫: mysqldump -S /data/3307/mysql.sock -A -R --triggers --master-data=2 --single-transaction >/tmp/full.sql sed -n '22p' /tmp/full.sql 下面須要用到這個信息 -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=325 恢復到從庫: mysql -S /data/3308/mysql.sock mysql> set sql_log_bin=0; mysql> source /tmp/full.sql 8、從庫開啓主從複製: mysql -S /data/3308/mysql.sock help change master to 執行命令: CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_USER='repl', MASTER_PASSWORD='123', MASTER_PORT=3307, MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=325; 開啓主從(開啓IO和SQL線程): start slave; 9、查看主從狀態: show slave status\G Slave_IO_Running: Yes Slave_SQL_Running: Yes -------------- 10、主從重要狀態信息介紹 show slave status\G Slave_IO_Running: Yes Slave_SQL_Running: Yes Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error:
mysql> show slave status\G ***************** 1. row ********************* Slave_IO_State: Queueing master event to the relay log ... Master_Log_File: mysql-bin.005 Read_Master_Log_Pos: 79 Relay_Log_File: slave-relay-bin.005 Relay_Log_Pos: 548 Relay_Master_Log_File: mysql-bin.004 Slave_IO_Running: Yes 主要看這兩 Slave_SQL_Running: Yes 主要看這兩 ... Exec_Master_Log_Pos: 3769 ... Seconds_Behind_Master: 8
主從複製故障及解決 stop slave; #<==臨時中止同步開關。 set global sql_slave_skip_counter = 1 ; #<==將同步指針向下移動一個,若是屢次不一樣步,能夠重複操做。 start slave; /etc/my.cnf slave-skip-errors = 1032,1062,1007 如何避免:從庫只讀 read_only
IO線程故障:
一、主庫鏈接不上
user、password、port、ip 錯誤
解決方案:
stop slave;
reset slave all; 清理master.info。從新開始
change master to
start slave;
防火牆
網絡不通
skip-name-resolve
stop slave;
start slave;
二、主庫二進制日誌丟失或損壞
解決方案:
stop slave;
reset slave all;
從新備份恢復
change master to
start slave;
SQL線程故障:
查看狀態,發現SQL線程被關閉,且出現下面的問題
執行relaylog日誌新事件
一、刪除、修改對象的操做時,沒有這個對象
二、建立對象時,對象已存在
三、主鍵衝突
從庫作寫入操做,會致使以上問題出現
處理方法:
stop slave;
set global sql_slave_skip_counter = 1; 跳過錯誤
start slave;
/etc/my.cnf
slave-skip-errors = 1032,1062,1007 跳過指定代號表明的錯誤
可是,以上操做有時是有風險的,最安全的作法就是從新構建主從。
怎麼預防以上問題?
從庫加入配置文件
設置成只讀庫
set global read_only=1;
vim /etc/my.cnf
read_only=1 ---->只能控制普通用戶,控制不了管理員,從庫設置成只讀庫
------------------
主從異常——主從延時過長
show slave status \G 查看狀態
Seconds_Behind_Master:0 主從延時爲0
默認的主從複製機制是異步的一個過程。
主庫緣由:
一、主庫作修改操做以後,纔會記錄二進制日誌。
sync_binlog=0/1
官方文檔
If the value of this variable is greater than 0,
the MySQL server synchronizes its binary log to disk (using fdatasync())
after sync_binlog commit groups are written to the binary log.
The default value of sync_binlog is 0, which does no synchronizing to disk—in this case,
the server relies on the operating system to flush the binary log's contents from time to time as for any other file.
A value of 1 is the safest choice because in the event of a crash you lose at most one commit group from the binary log.
However, it is also the slowest choice (unless the disk has a battery-backed cache, which makes synchronization very fast)
---------------------總結成兩句話
1:表示:每次事務commit,刷新binlog到磁盤
0:系統決定binlog什時候刷新到磁盤
二、主庫的壓力特別大(大事務、多事務)
三、從庫數量多,致使dump線程繁忙
-------------------
從庫緣由:
一、relay-log寫入慢
二、SQL線程慢(主從硬件差別比較大)
-----------------------------
儘量的避免主從延時
一、sync_binlog=1
二、大事務拆成小事務,多事務進行分離
三、使用多級主從,分庫分表架構
四、將binlog放到ssd或者flash上,高性能存儲
五、將relay放到ssd或者flash上
六、儘可能選擇和主庫一致硬件和配置
1、延時複製 2、SQL多線程 3、複製過濾 4、半同步複製 5、GTID複製
詳細
- 主從複製高級功能——半同步複製 出發點:保證主從數據一致性的問題,安全的考慮 5.5出現的概念,可是不建議使用,性能太差,和以前不一樣的是ack返回的時間點晚了一步,必須在二進制文件寫入relay後 5.6之後出現group commit 組提交功能,來提高開啓版同步複製的性能 5.7加強半同步複製的新特性:after sync; ------ 加載插件 主: INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; 從: INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; 查看是否加載成功: show plugins; 啓動: 主: SET GLOBAL rpl_semi_sync_master_enabled = 1; 從: SET GLOBAL rpl_semi_sync_slave_enabled = 1; 重啓從庫上的IO線程 STOP SLAVE IO_THREAD; START SLAVE IO_THREAD; 查看是否在運行 主: show status like 'Rpl_semi_sync_master_status'; 從: show status like 'Rpl_semi_sync_slave_status'; ----- 補充: rpl_semi_sync_master_timeout | 10000 默認狀況,到達10秒鐘尚未ack,主從關係自動切換爲普通複製 若是是1主多從的半同步複製,只要有一臺落地relaylog,返回ack,此次半同步就完成了。 --------------------------------------
- 主從複製高級功能——延時從庫 會專門找一個節點,配置成延時節點,儘量防止邏輯損壞,通常狀況下這個節點會被用備份 咱們配置的是SQL_thread的延時,通常會設置到3-6小時 mysql>stop slave; mysql>CHANGE MASTER TO MASTER_DELAY = 60; mysql>start slave; mysql> show slave status \G SQL_Delay: 300 取消延時: mysql> stop slave; mysql> CHANGE MASTER TO MASTER_DELAY = 0; mysql> start slave; -----------------------
- 主從複製高級功能——複製過濾
挑着複製,只想複製某些內容
主庫方面控制(不建議使用):有分風險
show master status; 白名單:只記錄白名單中列出的庫的二進制日誌 binlog-do-db 黑名單:不記錄黑名單列出的庫的二進制日誌 binlog-ignore-db 從庫方面控制:
show slave status\G 查看信息 白名單:只執行白名單中列出的庫或者表的中繼日誌 --replicate-do-db=test 庫 --replicate-do-table=test.t1 庫下的表 --replicate-wild-do-table=test.x* 模糊 黑名單:不執行黑名單中列出的庫或者表的中繼日誌 --replicate-ignore-db --replicate-ignore-table --replicate-wild-ignore-table 只複製world數據庫的數據
主:只記錄world的二進制日誌,可是風險大
從:寫入配置文件/data/3308/my.cnf
replicate-do-db=world --------------
主從複製新特性——GTID複製 以前說的是基於 二進制日誌的文件號 + 二進制日誌position號 來實現的複製
叫作傳統複製結構classic
GTID 是新的複製結構
好處:簡化了複製的難度,主從切換的時候更有優點
5.6新特性 GTID(Global Transaction ID全局事務ID)是對於一個已提交事務的編號,而且是一個全局惟一的編號。 它的官方定義以下: GTID = source_id :transaction_id 7E11FA47-31CA-19E1-9E56-C43AA21293967:29 每一臺mysql實例中,都會有一個惟一的uuid(128位隨機數),標識實例的惟一性 auto.cnf,存放在數據目錄下 重要參數: gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 gtid-mode=on --啓用gtid類型,不然就是普通的複製架構 enforce-gtid-consistency=true --強制GTID的一致性 log-slave-updates=1 --slave更新是否記入日誌 -----------------
構建1主2從的GTID複製環境: 3臺虛擬機, db02 克隆兩臺虛擬機環境,分別命名爲db0一、db03,在生產中準備3臺真實的物理機,不用多實例 要求: 1、IP地址、主機名 db01:10.0.0.51/24 db03:10.0.0.53/24 2、清理全部以前3306的相關數據,只留軟件 db01: cd /application/mysql/data/ \rm -rf * cd /data/binlog/ \rm -rf * db02: cd /application/mysql/data/ \rm -rf * cd /data/binlog/ \rm -rf * db03: cd /application/mysql/data/ \rm -rf * cd /data/binlog/ \rm -rf * 3、準備配置文件 規劃: 主庫: 10.0.0.51/24 從庫1: 10.0.0.52/24 從庫2:10.0.0.53/24 主庫: 加入如下配置信息 db01:10.0.0.51/24 vim /etc/my.cnf [mysqld] basedir=/application/mysql datadir=/application/mysql/data socket=/tmp/mysql.sock log-error=/var/log/mysql.log log_bin=/data/binlog/mysql-bin binlog_format=row skip-name-resolve server-id=51 gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 [client] socket=/tmp/mysql.sock slave1: db02:10.0.0.52/24 vim /etc/my.cnf [mysqld] basedir=/application/mysql datadir=/application/mysql/data socket=/tmp/mysql.sock log-error=/var/log/mysql.log log_bin=/data/binlog/mysql-bin binlog_format=row skip-name-resolve server-id=52 gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 [client] socket=/tmp/mysql.sock slave2: db02:10.0.0.53/24 vim /etc/my.cnf [mysqld] basedir=/application/mysql datadir=/application/mysql/data socket=/tmp/mysql.sock log-error=/var/log/mysql.log log_bin=/data/binlog/mysql-bin binlog_format=row skip-name-resolve server-id=53 gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 [client] socket=/tmp/mysql.sock -----------------
三臺節點分別初始化數據: /application/mysql/scripts/mysql_install_db --user=mysql --basedir=/application/mysql --datadir=/application/mysql/data/ 分別啓動三個節點mysql: /etc/init.d/mysqld start 測試啓動狀況: mysql -e "show variables like 'server_id'" master:51 slave:52,53 51: grant replication slave on *.* to repl@'10.0.0.%' identified by '123'; 52\53: change master to master_host='10.0.0.51',master_user='repl',master_password='123' ,MASTER_AUTO_POSITION=1;
# 參數MASTER_AUTO_POSITION=1 自動判斷哪些事務有,哪些食物沒有,不用像以前那樣設置起點位置 start slave; -------------
show master status \G
show slave status \G 查看狀態
正常狀況Retrieved_Gtid_Set(記錄的事務數) 和 Executed_gtid_Set(已執行的事務數) 的事務數是同樣的
除了這兩個標識,其餘的變化不大
高可用---業務不間斷的工做---用戶的體驗
普通主從環境,存在的問題: 1、監控的問題:APP應用程序,並不具有監控數據庫的功能,沒有責任監控數據庫是否能鏈接。 2、選主的問題:選替代者,沒有選主的功能 3、failover:VIP漂移,將IP落到新的主上,對於應用透明 4、數據補償:數據不全
宕機後的架構形態的改變
普通主從複製架構思路主庫宕機場景(1)
普通主從複製架構思路主庫宕機場景(2)
普通主從複製架構思路主庫宕機場景(3)
企業高可用解決方案: MMM(過期) MHA(目前推薦) PXC、Galera Cluster(出現不少年,企業不多用) 5.7.17 MGR 、Innodb Cluster(將來的趨勢,儘早研究) MySQL NDB Cluster(出現不少年,仍然不完善) MyCAT 高可
MHA(Master High Availability),
由日本DeNA公司youshimaton(現就任於Facebook公司)開發。
MHA能作到在10~30秒以內自動完成數據庫的Failover,
Failover的過程當中,能最大程度上保證數據的一致性。 該軟件由兩部分組成:MHA Manager(管理節點)和MHA Node(數據節點)。 半同步複製,能夠大大下降數據丟失的風險。MHA能夠與半同步複製結合起來。 MHA高可用集羣,要求一個複製集羣中須要有三臺數據庫服務器,一主二從,不支持多實例。
出於機器成本的考慮,淘寶也在該基礎上進行了改造,淘寶TMHA支持一主一從。 注意:必須使用獨立的數據庫節點,不支持多實例。
masterha_check_ssh 檢查MHA的SSH配置情況
masterha_check_repl 檢查MySQL複製情況
masterha_manger 啓動MHA
masterha_check_status 檢測當前MHA運行狀態
masterha_master_monitor 檢測master是否宕機
masterha_conf_host 添加或刪除配置的server信息
masterha_master_switch 控制故障轉移(自動或者手動)
Node工具包(這些工具一般由MHA Manager的腳本觸發,無需人爲操做)主要包括如下幾個工具:
save_binary_logs
保存和複製master的二進制日誌
apply_diff_relay_logs
識別差別的中繼日誌事件並將其差別的事件應用於其餘的從節點
slave filter_mysqlbinlog
去除沒必要要的ROLLBACK事件(MHA已再也不使用這個工具)
purge_relay_logs
清除中繼日誌(不會阻塞SQL線程)
(1)Manager程序負責監控全部已知Node(1主2從全部節點) (2)當主庫發生意外宕機 (2.1)mysql實例故障(SSH可以鏈接到主機) 0、監控到主庫宕機,選擇一個新主(取消從庫角色,reset slave),選擇標準:數據較新的從庫會被選擇爲新主(show slave status\G) 1、從庫經過MHA自帶腳本程序,當即保存缺失部分的binlog 2、二號從庫會從新與新主構建主從關係,繼續提供服務 3、若是VIP機制,將vip從原主庫漂移到新主,讓應用程序無感知 (2.2)主節點服務器宕機(SSH已經鏈接不上了) 0、監控到主庫宕機,嘗試SSH鏈接,嘗試失敗 1、選擇一個數據較新的從庫成爲新主庫(取消從庫角色 reset slave),判斷細節:show slave status\G 2、計算從庫之間的relay-log的差別,補償到2號從庫 3、二號從庫會從新與新主構建主從關係,繼續提供服務 4、若是VIP機制,將vip從原主庫漂移到新主,讓應用程序無感知 5、若是有binlog server機制,會繼續講binlog server中的記錄的缺失部分的事務,補償到新的主庫
3.1、安裝mha node: 依賴包perl-DBD-MySQL ,並在三個節點都安裝node軟件 rpm包直接 rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm 3.2、主庫中建立mha管理用戶 grant all privileges on *.* to mha@'10.0.0.%' identified by 'mha'; 從庫中也要查看是否是有這個帳戶 3.3、配置軟鏈接 ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog ln -s /application/mysql/bin/mysql /usr/bin/mysql 3.4、部署manger節點(建議在從節點db03) wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes 3.5、安裝 manager軟件 rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm 3.6、建立Manager必須目錄與配置文件 mkdir -p /etc/mha mkdir -p /var/log/mha/app1 ----》能夠管理多套主從複製 建立配置文件 (不須要的配置不要留着,註釋沒用,切換後會重寫) vim /etc/mha/app1.cnf -----》serverdefault能夠獨立 [server default] manager_log=/var/log/mha/app1/manager manager_workdir=/var/log/mha/app1 master_binlog_dir=/data/binlog user=mha password=mha ping_interval=2 repl_password=123 repl_user=repl ssh_user=root [server1] hostname=10.0.0.51 port=3306 [server2] hostname=10.0.0.52 port=3306 [server3] hostname=10.0.0.53 port=3306 3.7、配置互信(全部節點) ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1 ssh-copy-id -i /root/.ssh/id_dsa.pub root@10.0.0.51 ssh-copy-id -i /root/.ssh/id_dsa.pub root@10.0.0.52 ssh-copy-id -i /root/.ssh/id_dsa.pub root@10.0.0.53
檢測是否成功
ssh 10.0.0.{51..53} date 3.8、檢測互信 masterha_check_ssh --conf=/etc/mha/app1.cnf 3.9、檢測主從 masterha_check_repl --conf=/etc/mha/app1.cnf 3.10、啓動MHA manager nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &
查看日誌,
cd /var/log/mha
cd app1/
tail -f manager
故障演練
1、宕掉db01主庫,停掉數據庫 2、tail -f /var/log/mha/app1/manager 觀察日誌變化 3、恢復主庫運行,從新將db01加入到主從複製關係中
mysql CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123'; start slave;
4、將配置文件中加入修稿的故障節點(由於立即後,系統會自動清理掉server1) 5、啓動MHA了manager程序 masterha_check_ssh --conf=/etc/mha/app1.cnf masterha_check_repl --conf=/etc/mha/app1.cnf nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &
檢測狀態
masterha_check_status --conf=/etc/mha/app1.cnf
使用MHA自帶腳本實現IP FailOver(vip 漂移,應用透明)
配置步驟 上傳準備好的/usr/local/bin/master_ip_failover
vim master_ip_failover
只修改腳本中如下內容
my $vip = '10.0.0.55/24';
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";
給腳本添加 執行權限
chown +x
轉換格式
dos2unix /usr/local/bin/master_ip_failover
修改配置文件 vim /etc/mha/app1.cnf 添加: master_ip_failover_script=/usr/local/bin/master_ip_failover 重啓mha masterha_stop --conf=/etc/mha/app1.cnf nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 & 手工在主庫上綁定vip,注意必定要和配置文件中的ethN一致,個人是eth0:1(1是key指定的值) ifconfig eth0:1 10.0.0.55/24 切換測試: 停主庫,看vip是否漂移
binlogserver配置:
思考:爲何不直接在從slave上左binlogserver?
找一臺額外的機器,必需要有5.6以上的版本,支持gtid並開啓,咱們直接用的第二個slave [binlog1] no_master=1 不參與主從 hostname=10.0.0.53 master_binlog_dir=/data/mysql/binlog 單獨的,不能和主庫的binlog同樣 提早建立好,這個目錄不能和原有的binlog一致 mkdir -p /data/mysql/binlog chown -R mysql.mysql /data/mysql/*
修改完成後,將主庫binlog拉過來(從000001開始拉,以後的binlog會自動按順序過來) cd /data/mysql/binlog -----》必須進入到本身建立好的目錄 mysqlbinlog -R --host=10.0.0.51 --user=mha --password=mha --raw --stop-never mysql-bin.000001 & 最好,先在主庫查看一下,是否是從000001開始的
重啓MHA,生效配置: 重啓mha masterha_stop --conf=/etc/mha/app1.cnf nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &
其餘參數說明
manager檢測節點存活的間隔時間,總共會探測4次。
ping_interval=2
#節點標籤下設置
設置爲候選master,若是設置該參數之後,發生主從切換之後將會將此從庫提高爲主庫,即便這個主庫不是集羣中事件最新的slave candidate_master=1
#默認狀況下若是一個slave落後master 100M的relay logs的話,MHA將不會選擇該slave做爲一個新的master, 由於對於這個slave的恢復須要花費很長時間,
經過設置check_repl_delay=0, MHA觸發切換在選擇一個新的master的時候將會忽略複製延時,這個參數對於設置了candidate_master=1的主機很是有用, 由於這個候選主在切換的過程當中必定是新的master check_repl_delay=0
MHA高可用架構的問題
咱們的業務基本都是讀多寫少,何不分離開來,增長架構的效率
增長中間層,任何的增刪改查都走中間層,來分配路由到後端
Mysql-proxy(oracle) 已再也不開發 Mysql-router(oracle) 重點關注 Atlas (Qihoo 360) 輕量級,簡單 Atlas-sharding (Qihoo 360) Cobar(是阿里巴巴(B2B)部門開發) 已再也不更新 Mycat(基於阿里開源的Cobar產品而研發) TDDL Smart Client的方式(淘寶) DRDS 阿里雲的產品 Oceanus(58同城數據庫中間件) OneProxy(原支付寶首席架構師樓方鑫開發) vitess(谷歌開發的數據庫中間件) Heisenberg(百度) TSharding(蘑菇街白輝) Xx-dbproxy(金山的Kingshard、噹噹網的sharding-jdbc )amoeba
Atlas 是由 Qihoo 360公司Web平臺部基礎架構團隊開發維護的一個基於MySQL協議的數據中間層項目。
它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基礎上,修改了大量bug,添加了不少功能特性。
目前該項目在360公司內部獲得了普遍應用,不少MySQL業務已經接入了Atlas平臺,天天承載的讀寫請求數達幾十億條。 源碼 Github: https://github.com/Qihoo360/Atlas
你理解的中間層應該能作些啥?
1、監控 2、對應用透明,有IP,port 3、分析語句 4、進行語句的路由 5、有負載均衡的功能 6、平滑上下線節點的能力 7、黑名單等
Atlas主要功能介紹
讀寫分離
從庫負載均衡
自動分表
IP過濾
SQL語句黑白名單
DBA可平滑上下線DB
自動摘除宕機的DB
Atlas應用場景介紹
Atlas是一個位於前端應用與後端MySQL數據庫之間的中間件,
它使得應用程序員無需再關心讀寫分離、分表等與MySQL相關的細節,能夠專一於編寫業務邏輯,
同時使得DBA的運維工做對前端應用透明,上下線DB前端應用無感知。
下載地址:https://github.com/Qihoo360/Atlas/releases 注意: 1、Atlas只能安裝運行在64位的系統上 2、Centos 5.X安裝 Atlas-XX.el5.x86_64.rpm,Centos 6.X安裝Atlas-XX.el6.x86_64.rpm。 3、後端mysql版本應大於5.1,建議使用Mysql 5.6以上
安裝在了10.0.0.53
安裝和配置
1、安裝軟件 rpm -ivh Atlas-2.2.1.el6.x86_64.rpm 2、修改配置 cd /usr/local/mysql-proxy/ vim /usr/local/mysql-proxy/conf/test.cnf # 本來的文件裏面有中文的註釋,解釋每一行的做用 [mysql-proxy] admin-username = user admin-password = pwd proxy-backend-addresses = 10.0.0.55:3306 主庫 寫操做 vip proxy-read-only-backend-addresses = 10.0.0.52:3306,10.0.0.53:3306 按照環境修改從庫地址 pwds = repl:3yb5jEku5h4=,mha:O2jBXONX098= 後端數據庫帳號和密碼,須要提早規劃好用戶和權限 daemon = true keepalive = true event-threads = 8 log-level = message log-path = /usr/local/mysql-proxy/log sql-log=ON proxy-address = 0.0.0.0:33060 容許全部地址,經過端口33060 連接atlas admin-address = 0.0.0.0:2345 管理atlas的地址 charset=utf8 /usr/local/mysql-proxy/bin/encrypt 123 ---->製做加密密碼的命令
3、啓動atlas /usr/local/mysql-proxy/bin/mysql-proxyd test start ps -ef |grep proxy ---------------------- netstat -lntup | grep proxy 看是否兩個端口號都生成了
ps -ef |grep proxy 看應用是否起來
4、測試 測試讀寫分離: 讀的測試 mysql -uroot -p123 -h10.0.0.53 -P33060 show variables like 'server_id';能夠看到在兩個從指間切換 寫操做測試: 設置兩個從節點只讀 set global read_only=1; 臨時設置爲只讀庫 鏈接測試 mysql -umha -pmha -h10.0.0.53 -P33060 create database db1;
Atlas配置文件說明
鏈接管理接口: mysql -uuser -ppwd -h127.0.0.1 -P2345 打印幫助: mysql> select * from help;查看到全部管理命令
動態添加刪除節點: REMOVE BACKEND 3;
添加節點: ADD SLAVE 10.0.0.53:3306;
在線改配置,使重啓後依然生效
SAVE CONFIG;
數據條數達到800萬後,索引的層次會很深,影響性能
school.stu 1000w id name 實現拆分 stu_0 stu_1 stu_2 stu_3 stu_4 以上分表方式,存數據很是均勻,取數據不均與,由於要考慮業務需求 若是業務查詢熱點數據集中在id是1-200w這些數據,那麼讀取就不均勻 取模分表 n/5 取餘數 (0,1,2,3,4) (1)若是是 0 則分到 stu_0 (2)若是是 1 則分到 stu_1 (3)若是是 2 則分到 stu_2 (4)若是是 3 則分到 stu_3 (5)若是是 4 則分到 stu_4 取餘數 -------------------------------------
配置文件 vim /usr/local/mysql-proxy/conf/test.cnf
加入 tables = school.stu.id.5 (主庫)手工建立,分表後的庫和表,分別爲定義的school 和 stu_0 stu_1 stu_2 stu_3 stu_4
mysql -umha -pmha h10.0.0.53 -P33060 create database school; use school create table stu_0 (id int,name varchar(20)); create table stu_1 (id int,name varchar(20)); create table stu_2 (id int,name varchar(20)); create table stu_3 (id int,name varchar(20)); create table stu_4 (id int,name varchar(20)); 重啓atlas
測試: insert into stu values (3,'wang5'); insert into stu values (2,'li4'); insert into stu values (1,'zhang3'); insert into stu values (4,'m6'); insert into stu values (5,'zou7'); commit;
查詢的時候,必須加上where條件,不能作範圍查詢,只能作等值查詢
讀寫分離 Atlas會透明的將事務語句和寫語句發送至主庫執行,讀語句發送至從庫執行。具體如下語句會在主庫執行 顯式事務中的語句 autocommit=0時的全部語句 含有select GET_LOCK()的語句 除SELECT、SET、USE、SHOW、DESC、EXPLAIN外的 從庫負載均衡 proxy-read-only-backend-addresses=ip1:port1@權重,ip2:port2@權重 自動分表(已詳細配置過) 使用Atlas的分表功能時,首先須要在配置文件test.cnf設置tables參數。 tables參數設置格式:數據庫名.表名.分表字段.子表數量, 好比: 你的數據庫名叫school,表名叫stu,分表字段叫id,總共分爲2張表, 那麼就寫爲school.stu.id.2,若是還有其餘的分表,以逗號分隔便可。 用戶須要手動創建2張子表(stu_0,stu_1,注意子表序號是從0開始的)。 全部的子表必須在DB的同一個database裏。 當經過Atlas執行(SELECT、DELETE、UPDATE、INSERT、REPLACE)操做時,
Atlas會根據分表結果(id%2=k),定位到相應的子表(stu_k)。例如,執行select * from stu where id=3;,
Atlas會自動從stu_1這張子表返回查詢結果。但若是執行SQL語句(select * from stu;)時不帶上id,則會提示執行stu 表不存在。 Atlas暫不支持自動建表和跨庫分表的功能。 Atlas目前支持分表的語句有SELECT、DELETE、UPDATE、INSERT、REPLACE。 IP過濾:client-ips 該參數用來實現IP過濾功能。 在傳統的開發模式中,應用程序直接鏈接DB,所以DB會對部署應用的機器(好比web服務器)的IP做訪問受權。 在引入中間層後,由於鏈接DB的是Atlas,因此DB改成對部署Atlas的機器的IP做訪問受權,
若是任意一臺客戶端均可以鏈接Atlas,就會帶來潛在的風險。 client-ips參數用來控制鏈接Atlas的客戶端的IP,能夠是精確IP,也能夠是IP段,以逗號分隔寫在一行上便可。 如: client-ips=192.168.1.2, 192.168.2,
這就表明192.168.1.2這個IP和192.168.2.*這個段的IP能夠鏈接Atlas,其餘IP均不能鏈接。 若是該參數不設置,則任意IP都可鏈接Atlas。 若是設置了client-ips參數,且Atlas前面掛有LVS,則必須設置lvs-ips參數,不然能夠不設置lvs-ips。 SQL語句黑白名單 Atlas會屏蔽不帶where條件的delete和update操做,以及sleep函數。
Sharding的基本思想就是把一個數據表中的數據切分紅多個部分, 存放到不一樣的主機上去(切分的策略有多種),
從而緩解單臺機器的性能跟容量的問題. sharding是一種水平切分, 適用於單表數據龐大的情景.
目前atlas支持靜態的sharding方案, 暫時不支持數據的自動遷移以及數據組的動態加入. Atlas以表爲單位sharding, 同一個數據庫內能夠同時共有sharding的表和不sharding的表,
不sharding的表數據存在未sharding的數據庫組中. 目前Atlas sharding支持insert, delete, select, update語句, 只支持不跨shard的事務.
全部的寫操做如insert, delete, update只能一次命中一個組,
不然會報"ERROR 1105 (HY000):write operation is only allow to one dbgroup!"錯誤. 因爲sharding取替了Atlas的分表功能, 因此在Sharding分支裏面, Atlas單機分表的功能已經移除, 配置tables將不會再有效.
Atlas-Sharding架構*
配置示例
Atlas支持非sharding跟sharding的表共存在同一個Atlas中, 2.2.1以前的配置能夠直接運行. 以前的配置如 proxy-backend-addresses = 192.168.0.12:3306 proxy-read-only-backend-addresses = 192.168.0.13:3306,192.168.0.14:3306 ...
這配置了一個master和兩個slave, 這屬於非sharding的組, 全部非sharding的表跟語句都會發往這個組內.
因此以前沒有Sharding的Atlas的表能夠無縫的在新版上使用, 注意: 非Sharding的組只能配置一個, 而sharding的組能夠配置多個. 下面的配置, 配置了Sharding的組, 注意與上面的配置區分 [shardrule-0] table = test.sharding_test #分表名,有數據庫+表名組成 type = range #sharding類型:range 或 hash shard-key = id #sharding 字段 groups = 0:0-999,1:1000-1999 #分片的group,若是是range類型的sharding,則groups的格式是:group_id:id範圍。
若是是hash類型的sharding,則groups的格式是:group_id。例如groups = 0, 1 [group-0] proxy-backend-addresses=192.168.0.15:3306 proxy-read-only-backend-addresses=192.168.0.16:3306 [group-1] proxy-backend-addresses=192.168.0.17:3306 proxy-read-only-backend-addresses=192.168.0.18:3306
Sharding測試案例*
建立測試表: DROP TABLE IF EXISTS `sharding_test`; CREATE TABLE `sharding_test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` char(50)
COLLATE utf8_bin NOT NULL, `age` int(11) DEFAULT NULL, `birthday` date DEFAULT NULL,
`nickname` char(50) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`id`) ) mysql -h127.0.0.1 –P33060 -uroot -pmysqltest –c mysql> use test; mysql> insert into sharding_test(id, name, age) values(1, 'test', 0); mysql> insert into sharding_test(id, name, age) values(50, 'test', 0), (999, 'test', 0); 注意: 以上幾條數據都插入到了dbgroup0, 請注意第二條多值插入的語句, 由於50和999都命中了dbgroup0, 因此其執行成功, 可是若是執行如下的語句: mysql> insert into sharding_test(id, name, age) values(100, 'test', 0), (1500, 'test', 0);
ERROR 1105 (HY000): Proxy Warning - write operation is only allow to one dbgroup! 在sharding的表中, 這是不容許的, 由於id爲100命中了dbgroup0, 而id爲1500 命中了dbgroup1,
因爲分佈式的多值插入可能致使部分紅功, 須要回滾, 這個Atlas暫不支持. update, delete, replace同理. 測試完成分別登錄兩個主庫進行查看數據。
sharding限制
關於支持的語句 Atlas sharding只對sql語句提供有限的支持, 目前支持基本的Select, insert/replace, delete, update語句,
支持所有的Where語法(SQL-92標準), 不支持DDL(create drop alter)以及一些管理語句,
DDL請直連MYSQL執行, 請只在Atlas上執行Select, insert, delete, update(CRUD)語句. 對於如下語句, 若是語句命中了多臺dbgroup, Atlas均未作支持(若是語句只命中了一個dbgroup,
如select count(*) from test where id < 1000, 其中dbgroup0範圍是0 - 1000, 那麼這些特性都是支持的) Limit Offset(支持Limit) Order by Group by Join ON Count, Max, Min等函數 增長節點 注意: 暫時只支持range方式的節點擴展, hash方式因爲須要數據遷移, 暫時未作支持. 擴展節點在保證原來節點的範圍不改變的狀況下, 如已有dbgroup0爲範圍0 - 999, dbgroup1爲範圍 1000 - 1999,
這個時候能夠增長範圍>2000的節點. 如增長一個節點爲2000 - 2999, 修改配置文件, 重啓Atlas便可.
誰參與優化
- 數據庫管理員
- 業務部門表明
- 應用程序架構師
- 應用程序設計人員
- 應用程序開發人員
- 硬件及系統管理員
- 存儲管理員
- 安全優化(業務持續性)
- 性能優化(業務高效性)
優化範圍
存儲、主機和操做系統: 主機架構穩定性 I/O規劃及配置 Swap OS內核參數和網絡問題 應用程序: 應用程序穩定性 SQL語句性能 串行訪問資源 性能欠佳會話管理 數據庫優化: 內存 數據庫結構(物理&邏輯) 實例配置
優化成本:由上往下依次增高
優化效果:由下往上依次增高
由以上圖示能夠看出,咱們若是想要深度優化MySQL數據庫,須要作的事情不是單方面的,而是要從成本及優化
效果選擇最適合當前企業需求的方案。因此本課程針對整個出發點,會從各個維度來讓MySQL在運行過程當中達到最優的
狀態。
操做系統 top,
iostat 、
vmstat、
nmon、
dstata 數據庫 基礎優化命令工具 mysql SHOW [SESSION | GLOBAL] STATUS SHOW ENGINE INNODB STATUS SHOW PROCESSLIST show index Information Schema mysqldumpslow explain msyqladmin mysqlshow 深度優化命令工具(擴展) mysqlslap sysbench mysql profiling Performance Schema
思路:
定位問題:
硬件
系統
應用
數據庫
架構(高可用、讀寫分離、分庫分表)
處理問題
明確優化目標
性能和安全的折中
防患未然
1、系統優化工具 1.1 top
[root@Dao ~]# top
top - 23:52:39 up 14:39, 1 user, load average: 0.00, 0.01, 0.05
Tasks: 67 total, 1 running, 66 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.3 us, 0.0 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0
KiB Mem : 1014892 total, 668044 free, 62020 used, 284828 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 800696 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3284 root 10 -10 125300 11640 9116 S 0.3 1.1 2:40.03 AliYunDun (1)簡介: 實時監控當前操做系統的負載狀況的,每秒刷新一次狀態,一般會關注三大指標(CPU、MEM、IO) (2)評判標準 (2.1) 總體的負載狀況,判斷標準,若是值很是高,只能告訴咱們操做系統很繁忙 load average: 0.00, 0.00, 0.00 (2.2)CPU使用狀況 Cpu(s): 0.2%us, 0.2%sy, 99.7%id, 0.0%wa %id: CPU空閒的百分比 問一個問題?你以爲在一個已投產的系統中ID值是高好仍是低好呢? 通常狀況下咱們建議,95%如下都算是正常的,可是呢,咱們去準備硬件的時候,通常都會預留一部分(3年)
硬件配置 %us:用戶程序,佔用的CPU時間片的百分比。咱們認爲us%高是好事,但要在cpu正常能力範圍內。 %sy:系統程序(和內核工做有關),資源調配,資源管理,內核其餘功能的管理(system call) 對於比較成熟的操做系統,對sy%應該是佔比不多的。咱們認爲越少越好。 若是飆升,可能說明兩件事情,1,系統bug;2,中病毒了 %wa 這個參數越少越好。若是wait高說明了, 1,IO很慢(速度慢,全表掃描) 2、內存滿了OOM(內存小,全表掃描) (2.3) Mem: 4040596k total, 1692536k used, 2348060k free, 152348k buffers Swap: 786428k total, 0k used, 786428k free, 620256k cached Mem: total:總的內存量 used:已經被使用的內存量 free:空閒的內存空間 buffer:專門負責操做系統當中,與文件修改類操做有關的內存緩衝區(專門負責寫操做的),
能夠被重複利用的內存區域 cached:專門負責操做系統當中,與文件讀取有關的緩存區域(專門負責文件讀取操做的), 對於操做系統可用內存量=free+buffer+cached used:used=RSS+anon+buffer+cached 補充: 1.Linux操做系統內存劃分的三大區域: RSS:常駐內存集,主要負責程序運行須要的內存區域 Page Cache:頁緩存,文件系統緩存(FS cache),主要負責文件有關的緩衝和緩存,buffer+cached anon page: 匿名頁,主要負責程序之間交互時使用到內存區域 2.連續的地址位,定義爲了page(頁),而且進行了量化。 (1)基於固定大小page分配模式,他的一些不足的地方? 在申請內存時,須要整個內存進行遍歷 會有大量的內存碎片,致使程序OOM(out of memory) (2)SLAB Allocator內存管理子系統 1、將內存邏輯化成chain+chunk模式,內存區域會有多條鏈。
每條chain下都「掛着」多個等同大小的chunk(2的冪) 2、在每條鏈的頭部,都會有一個專門的chunk位圖,來更快速的找到須要的空閒chunk,
而且記錄每一個chunk最後被訪問的時間戳。 (3)buddy system(夥伴系統) 1、提供了多種內存實現回收和整理內存碎片算法,最經典的就是LRU算法。 2、當內存free空間緊張時,會觸發進行整理或釋放,再也不使用buffer和cached 經過如下命令,手工釋放全部buffer和cached echo 3 > /proc/sys/vm/drop_caches SWAP:交換分區,當內存緊張的時候,會將內存區域當中的數據臨時置換到SWAP中。 默認:在內存使用量達到60% [root@db02 ~]# cat /proc/sys/vm/swappiness 控制參數 60
主要交換有哪些
buffer 中爲修改完成的,RSS,anon_page
對於MySQL環境,要儘可能避免swap使用 sysctl.conf swappiness=0 臨時修改: [root@db02 ~]# echo 0 >/proc/sys/vm/swappiness 2、iostat 測試當前環境IO水平
[root@Dao ~]# iostat 1 10 # 每1秒顯示一次,共顯示10次
[root@Dao ~]# iostat -dk 1 5 # 以KB爲單位,每1秒顯示一次,顯示5次
mount /dev/sdb /data iostat -dm 1 /dev/sdb # 以MB爲單位,每1s顯示一次sdb的狀況 ,不停 dd if=/dev/zero of=/data/bigfile 一直寫文件 在優化過程當中,咱們通常會結合CPU和內存的使用狀況看IO狀態 CPU很是繁忙(MYSQL): 1、user 很高 再看IO水平,正常狀況下IO也會很高 不正常的狀況,user很高,可是IO很低? 在作大量的計算(多表鏈接查詢、排序、分組、子查詢很複雜或者很頻繁) 2、wait 很高 IO不多 (1)頗有多是全表掃描 (2)IO有問題(RAID規劃或者磁盤IO自己問題) 3、vmstat 用法和iostat相似,是一個綜合判斷的命令
vmstat 1 10 [root@Dao ~]# vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 0 531816 45680 375384 0 0 1 2 90 105 0 0 100 0 0
0 0 0 531792 45680 375384 0 0 0 0 102 258 0 0 100 0 0
0 0 0 531792 45680 375384 0 0 0 0 97 250 0 0 100 0 0
0 0 0 531792 45680 375384 0 0 0 0 100 255 0 0 100 0 0
0 0 0 531792 45680 375384 0 0 0 0 101 253 0 1 99 0 4、dstat
須要單獨安裝 yum install dstat -y 也是一個綜合命令,直接使用,比較人性化,自動設置顯示的單位,仍是彩色的,換頁自動顯示錶頭,很cool
顯示了cpu、磁盤、網絡IO、swap(paging space)、系統相關 2、數據庫層面優化工具 基礎優化命令工具 (1)mysql 用法舉例: mysql -uroot -p123 -e "show status like '%lock%'" (2)SHOW ENGINE INNODB STATUS mysql> show engine innodb status\G 通常關注比較多的: 內存、線程、鎖相關 (3)show index from table 查看索引狀況 (4)Information Schema 能夠直接使用show命令查看裏面的內容 (5)mysql庫下的 innodb_table_stats innodb_index_stats
desc innodb_table_stats 看錶的使用狀況
select * from innodb_table_stats;
select * from innodb_index_stats; 索引的使用狀況和跟新狀態 (6) 用的最多的SHOW [SESSION | GLOBAL] STATUS (7) SHOW [FULL] PROCESSLIST(應急調優) (8) explain 查看執行計劃 (9) mysqldumpslow (pt-query-diagest) 分析慢日誌 深度優化命令工具(擴展) mysqlslap sysbench tpcc
以上三個都是壓力測試工具 Performance Schema(5.7默認開啓)-能夠重點關注,用於定位數據庫問題 -----------------------------------------
硬件優化: 主機: 根據數據庫類型,主機CPU選擇、內存容量選擇、磁盤選擇 平衡內存和磁盤資源 隨機的I/O和順序的I/O 主機 RAID卡的BBU(Battery Backup Unit)關閉 存儲: 根據存儲數據種類的不一樣,選擇不一樣的存儲設備 配置合理的RAID級別(raid五、raid十、熱備盤) 網絡設備: 使用流量支持更高的網絡設備(交換機、路由器、網線、網卡、HBA卡) 注意:這些規劃應該在初始設計系統時就應該 考慮
--------------------------------------------------------
詳細說明
主機:
根據數據庫類型
(1)主機CPU選擇 IO密集型:能夠處理多併發的CPU類型,特色是核心數量較多,主頻中等 Intel E系列 CPU密集型:能夠處理高性能計算的cpu類型,主頻很是高,核心數量中等 Intel I系列的 MySQL的線上業務,處理高併發訪問的業務。屬於IO密集型的業務,因此選擇志強系列的CPU更好一些。 MySQL非線上的業務,數據處理數據分析,算法計算,屬於CPU密集型業務,因此選擇I系列的CPU。 (2)內存容量選擇 通常是選擇cpu核心數量的2倍 (3)IO的選擇 1、磁盤選擇 SATAIII SAS FC SSD pci-e SSD Flash 主機 RAID卡的BBU(Battery Backup Unit)關閉 存儲(有條件的公司會選擇單獨存儲設備): 根據存儲數據種類的不一樣,選擇不一樣的存儲設備 配置合理的RAID級別(raid五、raid十、熱備盤) raid0 :性能高(條帶化),安全性和單盤同樣 raid1 :安全性高(條帶化功能),性能和單盤同樣 raid10 :讀寫性能都很高(0級別條帶化功能),安全性高(1級別,鏡像功能),企業若是有條件推薦的一種raid級別 raid5 :較好的安全性(校驗),較好的性能(條帶化功能,讀性能比較高,寫性能通常),
對於讀多寫少的業務能夠使用此級別 高端存儲:IBM EMC HDS,通常都是raid1(就是raid10) ,自帶條帶化功能,並且只支持4塊盤作一個raid 使用合適raid級別,避免過分條帶化 ,條帶化增長了IO次數(相同量的數據) IOPS峯值:對於每一塊硬件磁盤來說,都有一個固定參數IOPS,每秒最多可以進行的IO的次數。 網絡設備: 使用流量支持更高的網絡設備(交換機、路由器、網線、網卡、HBA卡) 網卡綁定:解決網絡傳輸的可靠性, bonding 0(負載均衡模式) 1(主備模式) 添加備用網卡,交換機,預防線路故障 交換機:堆疊 0模式的綁定,要進行交換機的之間的綁定(連接成相似一臺的狀態),若是不作,會發生丟包
系統優化
Cpu:
基本不須要調整,在硬件選擇方面下功夫便可。
內存:
基本不須要調整,在硬件選擇方面下功夫便可。
SWAP:
MySQL儘可能避免使用swap。
IO :
raid
no lvm
ext4或xfs
ssd
IO調度策略
--------------------------------------------------------
詳細說明
系統層面優化: 1、Swap調整 /proc/sys/vm/swappiness的內容改爲0(臨時) echo 0>/proc/sys/vm/swappiness /etc/sysctl.conf上添加vm.swappiness=0(永久) vim /etc/sysctl.conf vm.swappiness=0 sysctl -p 這個參數決定了Linux是傾向於使用swap,仍是傾向於釋放文件系統cache。
在內存緊張的狀況下,數值越低越傾向於釋放文件系統cache。 固然,這個參數只能減小使用swap的機率,並不能避免Linux使用swap。
注: 修改MySQL的的配置參數innodb_flush_method,並開啓O_DIRECT模式。
這種狀況下,IonnDB的buffer pool會直接繞過cache來訪問磁盤,
可是redo log依舊會使用文件系統的cache。
值得注意的是,Redo log是覆寫模式,即便使用了文件系統的cache,也不會佔用太多
2、IO調度策略 臨時修改: [root@db02 ~]# cat /sys/block/sda/queue/scheduler noop anticipatory deadline [cfq] 修改前是cfq(先進先出) [root@db02 ~]# cat /sys/block/sdb/queue/scheduler noop anticipatory deadline [cfq] [root@db02 ~]# echo deadline >/sys/block/sda/queue/scheduler [root@db02 ~]# echo deadline >/sys/block/sdb/queue/scheduler [root@db02 ~]# cat /sys/block/sdb/queue/scheduler noop anticipatory [deadline] cfq 修改後(mysql比較適合dedline) [root@db02 ~]# 永久修改:
vim /boot/grub.conf 在文件的下面內容中加入參數elevator=deadline,重啓後生效
kernel /vmlinuz-2.6.32-696.el6.x86_64 ro root=UUID=40c9133f-6007-485c-be19-4082c8361df3 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8
rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM elevator=deadline rhgb quiet 3、FS: NO LVM 儘可能不要使用LVM ext4或xfs 文件系統的選擇 ssd(binlog relay可能單獨存放在ssd上) 4、關閉無用服務 chkconfig --level 23456 acpid off chkconfig --level 23456 anacron off chkconfig --level 23456 autofs off chkconfig --level 23456 avahi-daemon off chkconfig --level 23456 bluetooth off chkconfig --level 23456 cups off chkconfig --level 23456 firstboot off chkconfig --level 23456 haldaemon off chkconfig --level 23456 hplip off chkconfig --level 23456 ip6tables off chkconfig --level 23456 iptables off chkconfig --level 23456 isdn off chkconfig --level 23456 pcscd off chkconfig --level 23456 sendmail off chkconfig --level 23456 yum-updatesd off
vm.swappiness=0 用戶限制參數 /etc/security/limits.conf
* soft nproc 65535
* hard nproc 65535
* soft nofile 65535
* hard nofile 65535
業務應用和數據庫應用獨立 防火牆:iptables selinux 其餘(關閉無用服務): chkconfig --level 23456 acpid off chkconfig --level 23456 anacron off chkconfig --level 23456 autofs off chkconfig --level 23456 avahi-daemon off chkconfig --level 23456 bluetooth off chkconfig --level 23456 cups off chkconfig --level 23456 firstboot off chkconfig --level 23456 haldaemon off chkconfig --level 23456 hplip off chkconfig --level 23456 ip6tables off chkconfig --level 23456 iptables off chkconfig --level 23456 isdn off chkconfig --level 23456 pcscd off chkconfig --level 23456 sendmail off chkconfig --level 23456 yum-updatesd off 另外,思考未來咱們的業務是否真的須要MySQL,仍是使用其餘種類的數據庫。 以上:硬件優化建議,操做系統優化建議,應該在業務架構搭建初始應該作好。
數據庫層面優化: 4.1 參數優化(見參數優化建議.txt) 4.2 數據庫索引優化(見索引管理章節) 4.3 鎖優化 4.4 數據庫架構優化(擴展)
參數調整: 實例總體(高級優化,擴展): thread_concurrency 併發線程數量個數 sort_buffer_size 排序緩存 read_buffer_size 順序讀取緩存 read_rnd_buffer_size 隨機讀取緩存 key_buffer_size 索引緩存 thread_cache_size (1G —> 8, 2G —> 16, 3G —> 32, >3G —> 64) 鏈接層(基礎優化) 設置合理的鏈接客戶和鏈接方式 max_connections 最大鏈接數 max_connect_errors 最大錯誤鏈接數 connect_timeout 鏈接超時 max_user_connections 最大用戶鏈接數 skip-name-resolve 跳過域名解析 wait_timeout 等待超時 back_log 能夠在堆棧中的鏈接數量 SQL層(基礎優化) query_cache_size 查詢緩存 存儲引擎層(innodb基礎優化參數) default-storage-engine innodb_buffer_pool_size innodb_file_per_table=(1,0) innodb_flush_log_at_trx_commit=(0,1,2) Innodb_flush_method=(O_DIRECT, fdatasync) innodb_log_buffer_size innodb_log_file_size innodb_log_files_in_group innodb_max_dirty_pages_pct log_bin max_binlog_cache_size max_binlog_size innodb_additional_mem_pool_size(於2G內存的機器,推薦值是20M。32G內存的 100M) transaction_isolation
SQL優化:
執行計劃(基礎優化)
索引(基礎優化)
SQL改寫(高級優化)
架構優化(高級優化擴展):
高可用架構
高性能架構
分庫分表
-----------------------------------------------
鎖優化 MyIASM: 表級鎖 優勢:申請和釋放時,須要更少系統資源,減小死鎖產生。 缺點:不利於併發處理,在某個事務在對錶進行修改操做時,會鎖定整個表,其餘事務只能等待完成以後,才能操做。 有很是嚴重的鎖等待。 InnoDB: 支持行級鎖,行級鎖在索引鎖。若是表中沒有任何索引,那麼咱們作表數據處理的時候,依然會表級鎖。 GAP鎖:主要針對範圍數據操做時 死鎖的處理過程: 1、show processlist 2、show engine innodb status\G; LOCK WAIT 2 lock struct(s), heap size 1184, 1 row lock(s) MySQL thread id 4, OS thread handle 0x7f37d66f0700, query id 44 localhost root Sending data select * from t1 where id=3 for update Trx read view will not see trx with id >= 2323, sees < 2323 ------- TRX HAS BEEN WAITING 3 SEC FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 14 page no 3 n bits 72 index `GEN_CLUST_INDEX` of table `test`.`t1` trx id 2322 lock_mode X waiting Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 3、kill 4; 避免死鎖的方法: (1)將index lock 轉換爲table lock set autocommit=0; lock table t1; insert to update delete commit unlock table t1; (2)將全部事務處理表數據的順序儘可能保證一致。
一、搭建MHA+Atlas高可用讀寫分離架構
要求: 畫出實驗拓撲圖,標準清楚IP/hostname/做用 (1)實現1主2從GTID主從複製環境 (2)構建MHA高可用環境 (3)模擬損壞主庫,並實現修復 (4)實現應用透明(VIP) (5)實現外部數據補償(binlog server) (6)基於MHA環境實現Atlas讀寫分離 (7)在線增長刪除節點管理Atlas