標簽(空格分隔): Linux 運維 MySQL
sql文件hellodb.sql
架構
MySQL被設計為一個單進程多線程架構的數據庫.其數據庫實例在系統上的表現就是一個進程.
這張圖大致將MySQL分為三層(模型)從上到下依次為:
? 視圖層: 即Connectors
? 邏輯層: Pluggable Storage Engines以上部分
? 物理層: Pluggable Storage Engines及以下部分即都是文件形式(插件式存儲引擎)
具體說明如下
? Connectors指的是不同語言中與SQL的交互
? Management Serveices & Utilities: 系統管理和控制工具
? Connection Pool: 連接池。
管理緩沖用戶連接,線程處理等需要緩存的需求
? SQL Interface: SQL接口。
接受用戶的SQL命令,并且返回用戶需要查詢的結果。比如select from就是調用SQL Interface
? Parser: 解析器。
SQL命令傳遞到解析器的時候會被解析器驗證和解析。解析器是由Lex和YACC實現的,是一個很長的腳本。
主要功能:
A. 將SQL語句分解成數據結構,并將這個結構傳遞到后續步驟,以后SQL語句的傳遞和處理就是基于這個結構的
B. 如果在分解構成中遇到錯誤,那么就說明這個sql語句是不合理的
? Optimizer: 查詢優化器。
SQL語句在查詢之前會使用查詢優化器對查詢進行優化。他使用的 是“選取-投影-聯接”策略進行查詢。
用一個例子就可以理解: select uid,name from user where gender = 1;
這個select 查詢先根據where 語句進行選取,而不是先將表全部查詢 出來以后再進行gender過濾
這個select查詢先根據uid和name進行屬性投影,而不是將屬性全部取 出以后再進行過濾
將這兩個查詢條件聯接起來生成最終查詢結果
? Cache和Buffer: 查詢緩存。
如果查詢緩存有命中的查詢結果,查詢語句就可以直接去查詢緩存中取數據。
這個緩存機制是由一系列小緩存組成的。比如表緩存,記錄緩存,key 緩存,權限緩存等
? Engine :存儲引擎。
存儲引擎是MySql中具體的與文件打交道的子系統。也是Mysql最具有特色的一個地方。
Mysql的存儲引擎是插件式的。它根據MySql AB公司提供的文件訪問層的一個抽象接口來定制一種文件訪問機制(這種訪問機制就叫存儲引擎)
現在有很多種存儲引擎,各個存儲引擎的優勢各不一樣,最常用的 MyISAM,InnoDB,BDB
默認下MySql是使用MyISAM引擎,它查詢速度快,有較好的索引優化和數據壓縮技術。但是它不支持事務。
InnoDB支持事務,并且提供行級的鎖定,應用也相當廣泛。 Mysql也支持自己定制存儲引擎,甚至一個庫中不同的表使用不同的存儲引擎,這些都是允許的。
執行流程
配置文件
安裝MySQL或MariaDB后執行# my_print_defaults
命令可以查看其配置文件加載順序,CentOS7中如下:
/etc/mysql/my.cnf /etc/my.cnf ~/.my.cnf
越靠后的文件的優先級越高
數據類型
整數
浮點數
日期時間
字符串
文本
二進制
ENUM類型
即枚舉類型.使用格式: FIELD_NAME enum('VALUE1', 'VALUE2', ...)
枚舉類型的取值范圍以列表的形式指定了,而且其值只能取列表中的一個元素,列表最多有65535個.同set一樣其數據都不是直接將數據存入數據庫,而是將其列表中的編號存入數據庫.
SET類型
在創建表時,set類型的取值范圍就以列表的形式指定了.使用格式:FIELD_NAME set('VALUE1','VALUE2',...);
set類型最多只能有64個元素
字符集
mysql> show character set;
事務
事務就是一組原子性的查詢語句,也即將多個查詢當作一個獨立的工作單元.
- A: 原子性
- C: 一致性
- I: 隔離性
- D: 持久性
事務常用的命令,需要關閉Innodb的autocommit功能
mysql> start transaction; # 啟動事務
mysql> savepoint IDENTIFIER; # 設置存檔
mysql> rollback | rollback to IDENTIFIER; # 回滾[到指定存檔]
mysql> commint # 提交事務
隔離級別
mysql> show global variables like 'tx_isolation';
查看事務級別
① 讀未提交: read uncommitted # 2個此事務,其中一個對同一數據的修改,對方即時能看到變化
② 讀提交: read committed # 2個此事務對同一數據的操作,只有一方提交后對方才能看到變化
③ 可重讀: repeatable read # mysql默認為此隔離級別,2個此事務對同一數據的操作,每個事務相當于有各自一份獨立的此數據的復本(快照),只有當2個此事務都commit時,2個事務對數據的操作會進行匯總
④ 串行化: serializable,一個事務對數據的操作時,任何別的事務都無法對些數據同時進行操作
存儲引擎
MySQL為插件式存儲引擎,執行
mysql> show engines;
可查看其支持的引擎類型
mysql> show variables like 'storage_engine'
# 查看默認的存儲引擎
mysql> show table status like 'TABNAME';
查看某張表的屬性,包括存儲引擎
MySQL存儲引擎為表類型的,即每個表都可選擇不同的存儲引擎.
InnoDB
InnoDB存儲引擎支持事務,其設計目標主要面向在線事務處理(OLTP)的應用.其特點是行鎖設計 支持外鍵,并支持類似于Oracle的非鎖定讀,即默認讀取操作不會產生鎖.MySQL5.5.8版本開始,InnoDB是默認的存儲引擎.
.frm 表結構
.ibd 表空間(數據與索引)
InnoDB特點
1.默認InnoDB表的數據和索引存儲于同一個表空間中.即datadir目錄中的ibdata1, ibdata2, ... 表結構文件也在此目錄中,名為tbl_name.frm
2.事務型,適合對事務要求較高的場景中,適用于處理大量短期事務
3.支持高并發,4個隔離級別(默認為可重讀),使用間隙鎖以防止幻讀
MyISAM
1.支持全文索引,占用空間小,處理速度快
2.不支持事務,不支持外鍵
3.鎖粒度為表級鎖
4.崩潰無法保證表安全恢復
5.其緩沖池只緩存索引文件,而不緩沖數據文件.
適用場景: 只讀或讀多寫少 較小的表
每個表有3個文件,存儲于數據庫目錄中
tbl_name.frm: 定義表結構
tbl_name.MYD: 數據文件
tbl_name.MYI: 索引文件
? MEMORY: 使用存儲在內在中的內容來創建表,所有數據放在內存中.一個表對應一個與表名相同類型為frm的文件.該文件只存儲表的結構而數據文件是存儲在內存中,這樣有利于對數據的快速處理.
設置MySQL默認存儲引擎:
set @@session.storage_engine='InnoDB' # 臨時修改
vim /etc/my.cnf # 配置文件修改重啟后永久生效
default-storage-engine= MyISAM|InnoDB|...
重啟mysql服務
范式
① 第一范式: 數據庫表中不能有重復字段
② 第二范式: 有主鍵,非主鍵字段依賴主鍵(唯一性,一個表只說明一個事物)
③ 第三范式: 非主鍵字段不能相互依賴
如果一個數據庫能夠滿足第三范式的要求,數據庫中基本上沒有冗余的內容了.但要記住滿足范式不是我們的目標,優化設計提高整個系統的性能才是我們的目標.
約束
? 主鍵約束: 主鍵是唯一且非空的,一張表只能有一個
? 惟一鍵約束: 可以為空,一張表可以存在多個
? 外鍵約束: 字段數據受另一張表主鍵約束
? 檢查性約束: 數據類型對數據進行的約束
源碼CMAKE安裝MySQL5.5.33
如何編譯
1、使用cmake編譯mysql-5.5
cmake指定編譯選項的方式不同于make,其實現方式對比如下:
./configure cmake .
./configure --help cmake . -LH or ccmake .
指定安裝文件的安裝路徑時常用的選項:
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql
-DMYSQL_DATADIR=/data/mysql
-DSYSCONFDIR=/etc
默認編譯的存儲引擎包括:csv、myisam、myisammrg和heap。若要安裝其它存儲引擎,可以使用類似如下編譯選項:
-DWITH_INNOBASE_STORAGE_ENGINE=1
-DWITH_ARCHIVE_STORAGE_ENGINE=1
-DWITH_BLACKHOLE_STORAGE_ENGINE=1
-DWITH_FEDERATED_STORAGE_ENGINE=1
若要明確指定不編譯某存儲引擎,可以使用類似如下的選項:
-DWITHOUT_<ENGINE>_STORAGE_ENGINE=1
比如:
-DWITHOUT_EXAMPLE_STORAGE_ENGINE=1
-DWITHOUT_FEDERATED_STORAGE_ENGINE=1
-DWITHOUT_PARTITION_STORAGE_ENGINE=1
如若要編譯進其它功能,如SSL等,則可使用類似如下選項來實現編譯時使用某庫或不使用某庫:
-DWITH_READLINE=1
-DWITH_SSL=system
-DWITH_ZLIB=system
-DWITH_LIBWRAP=0
其它常用的選項:
-DMYSQL_TCP_PORT=3306
-DMYSQL_UNIX_ADDR=/tmp/mysql.sock
-DENABLED_LOCAL_INFILE=1
-DEXTRA_CHARSETS=all
-DDEFAULT_CHARSET=utf8
-DDEFAULT_COLLATION=utf8_general_ci
-DWITH_DEBUG=0
-DENABLE_PROFILING=1
如果想清理此前的編譯所生成的文件,則需要使用如下命令:
make clean
rm CMakeCache.txt
編譯安裝
yum -y install cmake28 # 需要epel源base包中只提供2.6版本
yum -y install readline-devel zlib-devel openssl-devel
useradd -r -d /mydata/data -s /sbin/nologin mysql
tar xf mysql-5.5.33.tar.gz
cd mysql-5.5.33
cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql-5.5.33 \
-DMYSQL_DATADIR=/mydata/data \
-DSYSCONFDIR=/etc \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITH_READLINE=1 \
-DWITH_SSL=system \
-DWITH_ZLIB=system \
-DWITH_LIBWRAP=0 \
-DMYSQL_UNIX_ADDR=/tmp/mysql.sock \
-DMYSQL_TCP_PORT=3306 \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci
make && make install
cd /usr/local
ln -s mysql-5.5.33 mysql
chown -R mysql.mysql mysql;chown -R mysql.mysql mysql-5.5.33
mkdir -pv /mydata/data
chown -R mysql.mysql /mydata/data
cd mysql
scripts/mysql_install_db --user=mysql --datadir=/mydata/data 查看數據目錄下是否生成初始化數據 ls /mydata/data
cp support-files/mysql.server /etc/init.d/mysqld
chmod +x /etc/init.d/mysqld
chkconfig --add mysqld
cp support-files/my-large.cnf /etc/my.cnf; echo "datadir = /mydata/data" >> /etc/my.cnf
echo "export PATH=/usr/local/mysql/bin:$PATH" > /etc/profile.d/mysql.sh;
. /etc/profile.d/mysql.sh
安裝后初始化
mysql> select User,Host,Password from mysql.user; # 查看用戶
mysql> drop user ""@localhost; # 刪除匿名用戶,host部分可用% _通配符
mysql> update user set password = PASSWORD('magedu') where user='root'; # 給用戶添加密碼
或者
mysqladmin -u root password "xxxx" # 給用戶設置密碼的另一種方法
mysql> flush privileges;
優化設置
安裝并啟動后的初始化:mysql_secure_installation
運行前常修改的參數:
innodb_file_per_table=1
skip_name_resolve=1
InnoDB的所有表數據默認是放在一個文件里的/var/lib/mysql/ibdata1
工作模式
① mysql < /path/to/scripts.sql 腳本模式
② mysql 交互式shell
mysql命令
mysql
-u, --user
-h, --host
-p, --password
--port
--protocol
--database DATABASE, -D
MySQL服務器參數/變量(設定MySQL/MariaDB的運行參數)
mysql> show global[session] variables [like clause]; # 查看服務器參數變量
mysql> show global[session] status [like clause]; # 查看狀態參數變量
顯示單個服務器參數變量設定值的方法:
mysql> select @@[global.|session.]SYS_VAR_NAME;
如 select @@session.tx_isolation;
運行時修改參數/變量,其中global設定僅對修改后新建立的會話有效,而session僅對當前會話有效,且立即生效.
set [global|session] SYS_VAR_NAME = EXPR
或者
set @@[global.|session.]SYS_VAR_NAME = EXPR
設定系統參數sql_mode以提高數據的嚴格性,此參數默認為空(即不符合表定義類型的數據也會被插入到表中).常用的mode如下:
TRADITIONAL # 傳統
STRICT_TRANS_TABLES # 僅對事務型表嚴格限制,如InnoDB,不允許向其插入非法數據
STRICT_ALL_TABLES # 所有的非法數據都不允許
修改方式
set global sql_mode=MODE
set @@global.sql_mode=MODE
創建表
create table tb_name1(stu_id int primary key, stu_name varchar(20), stu_sex boolean) ;
create table tb_name2(s_id int, c_id int, grade float, primary key(stu_id,course_id)); # 多字段組合主鍵
create schema if not exists students character set 'gbk' collate
create table tab1 like tab2; # 復制表結構
創建tb_name2的子表(tb_name2是tb_name3的父表)
create table tb_name3(id int primary key,
stu_id int, course_id int,
constraint c_fk foreign key(stu_id,course_id)
references tb_name2(s_id, c_id));
# stu_id course_id為表tb_name3的外鍵,c_fk是外鍵的別名.子表的外鍵關聯的必須是父表的主鍵或組合主鍵中的一個且類型必須為一致
表數據的完整性約束
unsigned # 無符號的.對數字類型
primary key # 主鍵
foreigh key # 外鍵
not null # 非空
unique # 惟一
auto_increment # 自增
default # 默認
查看表結構、定義
mysql> describe tbl_name或者desc tbl_name # 查看表的基本定義
mysql> show create table tbl_name # 查看表的詳細定義
mysql> show table status [{from|in} db_name] [like 'pattern' | where expr]
修改表(結構屬性層面 alter&drop)
alter table OLDTABNAME rename [to] NEWTABNAME; # 修改表名
alter table TABNAME modify FIELDNAME TYPE; # 修改字段數據類型
alter table TABNAME change OLDFIELDNAME NEWFIELDNAME TYPE; # 修改字段名
alter table TABNAME add FIELD1 TYPE [約束條件] [first|after FIELD2]; # 添加字段
alter table TABNAME drop FIELDNAME; # 刪除字段
alter table TABNAME modify FIELD1 TYPE first|after FIELD2; # 修改字段的排列位置
alter table TABNAME engine=xxxx; # 修改表的存儲引擎
alter table TABNAME charset=utf8; # 修改表的數據字符集
alter table TABNAME drop foreign key 外鍵別名; # 刪除表的外鍵約束
drop table TABNAME; # 刪除表(沒有被其它表關聯)
如果與其它表有關聯的表,正確的方法應該是刪除子表的外鍵約束然后再刪除父表.這樣不會影響子表的其他數據,可以保證數據庫的安全.
假如example4表(外鍵為stu_id,別名為d_fk)是example1表的子表
alter table example4 drop foreign key d_fk;
drop table example1;
索引
索引是一種特殊的數據庫結構,可以有來快速查詢數據庫表中的特定記錄.索引同數據庫表中一列或多列組合而成,其作用提高對表中數據的查詢速度,是提高數據庫性能的重要方式.MySQL中所有的數據類型都可以被索引,其索引分類如下:
? 普通索引
在創建普通索引時,不附加任何限制條件.此類索引可以創建在任何數據類型中,其值是否唯一和非空由字段本身的完整性約束條件決定.
? 唯一性索引
使用unique參數可以設置索引為唯一性索引.限制該索引的值必須是唯一的.主鍵就是> 一種唯一性索引.其字段的每一個值都是唯一的.
? 全文索引
使用fulltext參數可以設置索引為全文索引.全文索引只能創建在char varchar或text類型的字段上.查詢數據量圈套的客串類型的字段時,使用全文索引可以提高查詢速度.(目前只有MyISAM支持)
? 單列索引
在表中的單個字段上創建索引.其可以是以上3種中的任意一種索引.
? 多列索引
多列索引是在表的多個字段上創建一個索引.該索引指向創建時對應的多個字段,可以通過這幾個字段進行查詢.但是只有查詢條件中使用了這些字段中第一個字段時,索引才會被使用.
? 空間索引
使用spatial參數可以設置索引為空間索引.空間索引只能建立在空間數據類型上,樣可以提高系統獲取空間數據的效率.MySQL中的空間數據類型包括geometry和point linestring polygon,目前只有MyISAM存儲引擎支持空間檢索,而且索引的字段不能為空值.
索引的缺點:
創建和維護索引需要耗費時間,耗費時間的數量隨著數據量的增加而增加.索引需要占用物理空間.索引可以提高查詢的速度,但是會影響插入記錄的速度.插入大量記錄的速度影響更加明顯.
索引的設計原則
- 選擇唯一性索引: 其值是唯一的,可以更快地通過該索引來確定某條記錄.
- 為經常需要排序、分組和聯合操作的字段建立索引
- 為常作為查詢條件的字段建立索引
- 限制索引的數目
- 盡量使用數據量少的索引
- 盡量使用前綴來索引
- 刪除不再使用或者很少使用的索引
創建索引
? 創建表的時候直接創建索引
create table TABNAME(屬性名 數據類型 [完整性約束條件],..,[unique|fulltext|spatial] index|key [別名] (屬性名 1 [(長度)] [asc|desc]));
屬性名 1: 前面定義好的某個字段的名稱.
長度: 可選參數,其指索引的長度,必須是客串類型才可以使用
asc|desc: 表示升序或降序排列
? 在已經存在的表上創建索引
create [unique|fulltext|spatial] index 索引名 on 表名 (屬性名 [(長度) [asc|desc]]);
? 在已經存在的表上通過alter table語句來創建索引
alter table 表名 add [unique|fulltext|spatial] index 索引名 (屬性名 [(長度) [asc|desc]]);
創建普通索引
create table index1(id int,
name varchar(20),
sex boolean,
index(id)
);
使用explain語句可以查看索引是否被使用
explain select * from index1 where id=1\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: index1
type: ref
possible_keys: id # 此行及以下一行說明索引起作用了
key: id
key_len: 5
ref: const
rows: 1
Extra:
1 row in set (0.01 sec)
創建唯一性索引
create table index2(
id int unique,
name varchar(20),
unique index index2_id(id asc)
);
創建全文索引
create table index3(
id int,
info varchar(20),
fulltext index index3_info(info)
)engine=MyISAM;
創建單列索引
create table index4(
id int,
subject varchar(30),
index index4_st(subject(10))
);
創建多列索引
create table index5(
id int,
name varchar(20),
sex char(4),
index index5_ns(name,sex)
);
創建空間索引
create table index6(
id int,
space geometry ont null,
spatial index index6_sp(space)
)engine=MyISAM;
創建唯一鍵索引 全文索引 多列索引示例:
create table user(
userid int(10) primary key not null unique auto_increment, username varchar(20) not null,
passwd varchar(20) not null,
info text,
unique index index_uid(userid desc),
index index_user(username,passwd),
fulltext index index_info(info)
)engine=MyISAM default charset=utf8;
索引何時不生效
① 像like "%xxx"
這樣%號為第一個字符時索引不會被使用.
② 如果是多列索引,但查詢條件并不是多列索引的第一個字段時,索引也不會起作用.示例如下:
mysql> create index index_birth_department on student(birth,department);
mysql> explain select * from student where birth=1991; # 多列索引生效
mysql> explain select * from student where deartment='CS'; # 多列索引不生效
③ 查詢語句只有or關鍵字時,如果or前后的兩個條件的列都是索引時,索引生效,否則索引不生效.
刪除索引
mysql> drop index 索引名 on 表名;
臨時禁用/開啟索引
mysql> alter table TABNAME disable|enable keys;
視圖(view)
視圖它是一個虛表,存儲下來的select語句.常見的操作如下
create view VIEW_NAME [(column_list)] as select_statement; # 創建
alter view VIEW_NAME [(column_list)] as select_statement; # 修改
drop view VIEW_NAME [if exists] VIEW_NAME [, VIEW_NAME] ...; # 刪除
觸發器
查詢語句
基本語法
select [distinct] FIELDS from TABNAME
where 條件
group by FIELDS having 條件
order by FIELDS [asc|desc]
limit 初始位置,記錄數
集合函數
count()
sum()
avg()
max()
min()
連接查詢
連接查詢是將兩個或多個表按某個條件連接起來,從中選取需要的數據.它包括?內連接查詢
與?外連接查詢
內連接查詢: 只查詢出指定字段取值相同的記錄.主鍵與外鍵交集
select num,name,employee.d_id,age,sex,d_name,function \ from employee, department \ where employee.d_id=department.d_id;
外連接查詢: 主外鍵字段值不相等的記錄也可以查詢出來.分為左外連接與右外連接(分別表示以哪此表為主)
select FIELD1,FIELD2,...
from TAB1 left|right join TAB2
on TAB1.FIELD=TAB2.FIELD;
子查詢(嵌套select,但效率不高)
子查詢的效率不高源自需要為內層的查詢結果建立臨時表,查詢完畢后還要撤銷這些臨時表.但連接查詢不需要,所以后者查詢效率更高.
in (select子語句): 在select子語句中出現過的值
比較運算符 (select子語句):
exists (select子語句): 判斷子語句為真時執行,否則不執行主select
比較符 any (select子語句): 與子語句查詢出的任意一個值比較
比較符 all (select子語句): 只有滿足內層子select子語句返回的所有結果才執行外層查詢語句.
合并查詢結果
取所有select語句的結果的交集部分.
select 語句1 union|union all
select 語句2 union|union all
select 語句3 union|union all
...
select 語句1 union select 語句2;
使用正則表達式查詢
select FIELD1,FIELD2,... from TAB where FIELD regexp|rlike "XX";
插入、更新、刪除數據(數據內容層面 insert update delete)
insert into TABNAME values(v1,v2,..);
insert into TABNAME(FIELD1,FIELD2,...) values(v1,v2,...),(x1,x2,...);
update TABNAME set FIELD1= ,FIELD2= where 條件;
delete from TABNAME where 條件;
# 不跟where子名會刪除整表內容
MySQL運算符
?算術運算符
?比較運算符
?邏輯運算符
?位運算符
MySQL函數
- 數學函數
-
字符串函數
字符串函數
忘記管理員密碼的解決辦法
- 啟動mysqld進程時,使用--skip-grant-tables和--skip-networking選項(systemctl管理的話要編輯mariadb.service,并執行systemctl daemon-reload;CentOS6的話需要更改/etc/init.d/mysqld文件)
- 通過update命令修改管理員密碼,flush privileges加載授權表.
- 改回1步驟以正常方式啟動mysqld進程
MySQL用戶帳號與權限管理
mysql -u USERNAME -h HOSTNAME -P PORT -p PASSWD -e "SQL語句"
登錄語句
創建用戶:
mysql> create user 'user'@'host' identified by [PASSWORD] 'password';
mysql> insert into mysql.user(User,Password) values('xx','xxx',PASSWORD('pwd'));
grant priv_type on DB.TAB to USER identified by [PASSWORD]"PWD";
刪除用戶:
mysql> drop user 'user'@'host' ...;
mysql> delete from mysql.user where Host='xxx' User='xx';
重命名用戶:
rename user OLD to NEW [OLD to NEW]...;
修改用戶密碼:
? set password [for 'user'@'host']=PASSWORD('xxxxx'); flush privileges;
? update mysql.user set Password=PASSWORD('xxxx') where User='USERNAME' and Host='HOST'
? mysqladmin -uUSERNAME -hHOST -p password 'NEW_PASS'
用戶權限
安裝MySQL時會自動安裝一個名為mysql的數據庫.mysql數據庫下面存儲的都是權限表(如user db host tables_priv columns_priv proc_priv).用戶登錄以后,MySQL數據庫系統會根據這些權限表的內容為每個用戶賦予相應的權限.
MySQL中權限分配是按照user表、db表、table_priv表和columns_priv表的順序依次判斷各表中的值是否為Y,是的話就不需要檢查后面的表了.
user表
Host: 主機名
User: 用戶名
Password: 密碼
xxx_priv: 以priv結尾的字段決定了用戶的權限.
ssl_type: #以下4個都與安全加密相關
ssl_cipher:
x509_issuer:
x509_subject
max_questions # 每小時可以允許多少次查詢,0表示不限制
max_updates # 更新
max_connections # 連接
max_user_connections# 單個用戶可以同時具有的連接數.
db表
db表存儲了某個用戶對一個數據庫的權限.
host表
較少使用
tables_priv表
可以對單個表進行權限設置
columns_priv表
此表可以對單個數據列進行權限設置
procs_priv表
此表可以對存儲過程和存儲函數進行權限設置.
用戶權限
MySQL權限說明(user表)
授權語句
語法:
GRANT
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
TO USER [, USER] ...
[REQUIRE {NONE | ssl_option [[AND] ssl_option] ...}]
[WITH with_option ...]
GRANT PROXY ON user_specification
TO user_specification [, user_specification] ...
[with GRANT OPTION]
with后跟的選項:
GRANT OPTION: 被授權的用戶可以將這些權限賦予給別的用戶
MAX_QUERIES_PER_HOUR count: 設置每小時可以允許執行count次查詢.
MAX_UPDATES_PER_HOUR count:
MAX_CONNECTIONS_PER_HOUR count:
MAX_USER_CONNECTIONS count
object_type:
TABLE
| FUNCTION
| PROCEDURE
priv_level:
*
| *.*
| db_name.*
| db_name.tbl_name
| tbl_name
| db_name.routine_name
user_specification:
user
[
IDENTIFIED BY [PASSWORD] 'password'
| IDENTIFIED WITH auth_plugin [AS 'auth_string']
]
ssl_option:
SSL
| X509
| CIPHER 'cipher'
| ISSUER 'issuer'
| SUBJECT 'subject'
with_option:
GRANT OPTION
| MAX_QUERIES_PER_HOUR count # 0表示不限次數
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONS count
mysql> grant all on db_name.tbl_name to 'user'@'host' ; # 授權
取消授權
mysql> revoke update on db_name.tbl_name from 'user'@'host';
# 收回授權
顯示用戶權限
mysql> show grants for 'user'@'host';
數據備份與還原
備份
? 備份:mysqldump命令(屬于邏輯備份,性能較差)
將數據庫中的數據備份成一個文本文件.其原理是查出需要備份的表的結構,分析出需要什么create語句與insert語句可以生成這張表,將這些個create與這個龐大的insert語句保存在文本文件中.應該在MySQL服務器壓力最小的時間段執行,并且需要考慮到備份需要影響到的時間有.當數據庫相當大時,不建議此種備份方式。
缺點: 會丟失數據精度,無法備份索引
備份類型
備份什么:
數據 配置文件 二進制日志 事務日志
備份策略:
完全+增量 完全+差異
按備份數據庫的內容
? 完全備份: 對數據庫進行一個完整的備份.
? 增量備份: 在上次完全備份的基礎上,對于更改的數據進行備份.
? 差異備份: 僅備份自上一次完全備份以來變量的那部分數據;
? 日志備份: 對MySQL數據庫二進制日志的備份.
物理備份、邏輯備份
? 物理備份:復制數據文件進行備份,也稱祼文件備份.恢復時間較短.不需要
? 邏輯備份:從數據庫導出數據另存在一個或多個文件中;恢復所需要的時間往往較長.但適用于任意存儲引擎.移植性較好,且方便使用文本處理工具直接對其處理
根據數據服務是否在線
? 熱備:讀寫操作均可進行的狀態下所做的備份.MySQL官方稱之為Online Backup.
? 溫備:可讀但不可寫狀態下進行的備份;
? 冷備:讀寫操作均不可進行的狀態下所做的備份;一般只需要復制相關的數據庫物理文件即可.MySQL官方稱之為Offline Backup
幾種備份工具
? mysqldump(邏輯備份|)
mysqldump命令用法:
# mysqldump -u USERNAME -h HOSTNAME -p DBNAME [tab1 tab2 ...] > backup.sql,如果只備份一個數據庫時,mysqldump不會自動生成數據庫,還原時需要手動創建數據庫,即下面2步操作
mysql> create database db;
# mysql db < backup.sql
# mysqldump -u USERNAME -h HOSTNAME -p --databases db1 db2 ... > backup.sql 備份多個指定數據庫
# mysqldump -u USERNAME -p -h HOSTNAME --all-databases > all.sql 備份所有數據庫
-p: 要求輸入密碼
USERNAME: 用戶名
DBNAME: 數據庫名
MyISAM存儲引擎:支持溫備 備份時要鎖定表
-x,--lock-all-tables:鎖定所有庫的所有表,讀鎖
-l,--lock-tables: 鎖定指定庫所有表
InnoDB存儲引擎: 支持熱備與溫備
--single-transaction: 創建一個事務,基于此快照執行備份.InnoDB務必加上,不要與--lock-all-tables一同使用
-R,--routines: 存儲過程和存儲函數
--triggers: 備份觸發器
-E,--events: 備份事件
--routines:
--triggers:
--master-data[=NUM]: 記錄備份文件時,binlog所處的時間 偏移量也會被記錄
0: 不記錄二進制日志及其位置
1: 記錄為chage master to語句,此語句不被注釋
2.: 記錄為chage master to語句,此語句被注釋
記錄的內容示例:
-- CHANGE MASTER TO MASTER_LOG_FILE='master-log.000001', MASTER_LOG_POS=245;
--flush-logs: 鎖定表完成后,即進行二進制日志滾動操作.
tab: 指定數據庫中的各表,沒有的話將備份整個數據庫.
backup.sql: 備份的文本文件(并非必須得以.sql結尾)
--lock-all-tables: 備份前鎖定所有庫所有表
mysqldump真實場景備份操作
備份所有數據庫: 每周完全備份+每日增量
# mysqldump -uroot -p --lock-all-tables --flush-logs --all-databases --master-data=2 > /root/all.sql
查看all.sql中(--master-data)記錄的二進制日志文件,在其之前的二進制日志文件可備份后都刪除.
mysql> prege binary logs to "mysql-bin.00000x"; # 備份后刪除舊的二進制日志文件
增量備份
mysql> flush logs;
# cd /mydata/data
# mysqlbinlog mysql-bin.0000011 > /root/mon-incremental.sql # 可以改名以便知道具體是哪個完全備份后的哪天的增量備份
# cd /usr/local/mysql
# scripts/mysql_install_db --user=mysql --data-dir=/mydata/data
# /etc/init.d/mysqld start
# mysql -uroot -p < /root/all.sql # 還原完全備份的數據
# mysql -uroot -p < /root/mon-incremental.sql # 還原增量備份的數據
# mysql -uroot -p < /root/tues-incremental.sql
# ...
? xtrabackup開源備份工具
支持對InnoDB做熱備,是一款開源的物理備份工具.下載percona-xtrabackup(CentOS7)
yum -y install ./percona-xtrabackup-2.3.2-1.el7.x86_64.rpm
xtrabackup --backup | --prepare [options]
--print-defaults: 打印程序參數列表
--no-defaults: 不從任何文件是讀取默認選項
--defaults-file= :
--target-dir= : 備份的目標目錄
--backup: 創建備份實例
--stats:
xtrabackup
? 備份:直接復制整個數據庫中目錄(InnoDB不適用)
最簡單的備份方法,就是將MySQL中的數據庫文件直接復制出來.使用這種方法前最好將數據庫服務停止以便數據不會發生變化.
? 備份:使用mysqlhotcopy工具快速備份(InnoDB不適用)
mysqlhotcopy(一個Perl腳本,需要安裝)可以在不停止MySQL服務器下進行備份,其速度快于mysqldump.其主要使用lock tables,flush tables,cp來進行快速備份.工作原理是,先將需要備份的數據庫加上一個讀操作鎖,然后用flush tables將內在中的數據寫回到硬盤上的數據庫中,最后用cp將需要備份的數據庫文件復制到目標目錄.
# mysqlhotcop [option] dbname1 dbname2 .. backDir/
--help: mysqlhotcopy幫助
--allowold: 如果備份目錄下存在相同的備份文件,則將舊的備份文件名加上_old
--keepold: 如果備份目錄下存在相同的備份文件,則將舊的備份更名而不是刪除.
--flushlog: 本次備份之后,將對數據庫的更新記錄到日志中.
--noindices: 只備份數據文件,不備份索引文件.
--user=用戶名: 用來指定用戶名,可以用-u替代
--password=密碼: 指定密碼,可以用-p替代但須與-p緊挨著
--port=端口號: 指定端口號,可以用-P替代
--socket=socket文件: 用來指定socket文件,可以用-S替代
備份策略:
1.完全+差異+binlog 或 完全+增量+binlog
- 多久一次完全備份
MySQL備份腳本
db_backup.sh
#!/bin/bash
. /etc/init.d/functions
# 要備份的數據庫名,多個數據庫用空格分開
databases=(db1 db2 db3)
# 備份文件要保存的目錄
basepath='/root/backup/b3log.org/mysql/'
if [ ! -d "$basepath" ]; then
mkdir -p "$basepath"
fi
# 循環databases數組
for db in ${databases[*]};do
# 備份數據庫生成SQL文件
/bin/nice -n 19 /usr/bin/mysqldump -uUSER -pPASSWORD --master-data=2 --database $db > $basepath$db-$(date +%Y%m%d).sql
# 將生成的SQL文件壓縮
/bin/nice -n 19 tar zPcf $basepath$db-$(date +%Y%m%d).sql.tar.gz $basepath$db-$(date +%Y%m%d).sql
done
# 刪除7天之前的備份數據
find $basepath -mtime +7 -name "*.sql.tar.gz" -exec rm -rf {} \;
# 刪除生成的SQL文件
rm -rf $basepath/*.sql
設置計劃任務來執行MySQL備份
crontab -e
# mysql backup
00 03 * * * /bin/bash /root/db_backup.sh
還原
? mysql命令還原
mysql -u root -p[dbname] < backup.sql
? 直接復制數據庫文件到數據庫目錄
必須保證兩個MySQL數據庫的主版本號是相同的.
數據庫遷移
? 相同版本的MySQL數據庫之間
mysqldump -h host1 -u root --password=password1 --all-databases | mysql -h host2 -u root --password=password2
? 不同版本的MySQL數據庫之間
高版本的MySQL數據庫通常都會兼容低版本.
日志
MySQL日志是記錄數據庫日常操作和錯誤信息的文件.當數據庫遭到意外的損害時,可以通過日志文件來查詢出錯原因,并且可以通過日志文件進行數據恢復.MySQL中日志可分為:
? 二進制日志: 以二進制文件的形式記錄數據庫中的操作,但不記錄查詢語句
? 錯誤日志: 記錄MySQL服務器的啟動、關閉、 運行錯誤信息(文本)
? 通用查詢日志: 記錄用戶登錄和記錄查詢的信息(文本)
? 慢查詢日志: 記錄執行時間超過指定時間的操作(文本)
? 中繼日志: 在當前從服務器上要求執行一遍的日志(格式同二進制日志一樣)
? 事務日志: 將隨機IO轉化
二進制日志
也叫做變更日志,主要用于記錄數據庫的變化情況以及還原數據.任何可能引起數據變化的操作都會記錄.通過其可以查詢MySQL數據庫中進行了哪些改變.MySQL的每一次重啟都會生成一個相應的二進制日志文件.
二進制日志的格式的兩種:1基于語句 2基于行 3前兩種的混合模式(binlog_format=mixed)
二進制日志文件最好不要與數據文件放在同一塊硬盤上,應該放置在有冗余能力的磁盤上
mysql-bin.index文本文件記錄了所有的二進制日志文件數量
啟動與設置
vim /etc/my.cnf
log-bin=mysql-bin # 名稱示例:mysql-bin.000001
/etc/init.d/mysqld restart 或修改MySQL服務器參數"log_bin":
set session log_bin = 1;
查看并輸出指定二進制日志內容
mysqlbinlog 二進制日志文件
選項
--start-datetime
--stop-datetime
--start-position
--stop-position
示例
msyqlbinlog --start-datetime "2015-03-26 15:14:39" mysql-bin.000003 > /root/a.sql
查看所有二進制日志文件名與大小
mysq> show binary logs;
查看當前正在使用的二進制日志文件
mysql> show master status;
查看二進制日志事件
mysql> show binlog events in 'mysql-bin.000005';
mysql> show binlog events in 'mysql-bin.000005' from 107;
# 從指定位置查看
刪除二進制日志
mysql> reset master; # 刪除所有二進制日志
mysql> purge master logs to "mysql-bin.000007"; # 刪除小于此編號的所有二進制日劇
mysql> purge master logs to "yyyy-mm-dd hh:MM:ss;" # 刪除指定時間之前創建的二進制日志
或設置expire_logs_days
用二進制日志還原數據庫
如果數據庫遭到意外損壞,首先應該使用最近的備份文件加上二進制日志來還原.備份文件時間之前的二進制日志可以刪除.備份文件的恢復上面提到.
二進制日志還原
mysqlbinlog filename.number | mysql -u root -p
使用mysqlbinlog命令進行還原操作時,必須是編號小的先還原
暫時停止二進制日志功能
在配置文件中設置log-bin選項后MySQL服務器將會一直開啟二進制日志功能.但有命令可以臨時暫停二進制日志功能(不希望某些sql語句記錄在二進制日志中).
mysql> set sql_log_bin=0;
# 暫停二進制日志功能
mysql> set sql_log_bin=1;
# 開啟二進制日志功能
截取掉部分二進制日志內容
mysqlbinlog --stop-position=695 /var/lib/mysql/master-log.000001 > new.sql
手動滾動二進制日志
mysql> flush logs;
# 會滾動生成一個新的二進制日志文件,在從服務器上會滾動中繼日志
二進制日志的同步參數
sync_binlog=#
設定多久同步一次二進制近幾年至磁盤文件中,0表示不同步,任何正數值都表示對二進制日志每多少次寫操作之后同步一次.當autocommit的值為1時,每條語句的執行都會日志同步,否則,每個事務的提交會引起二進制近幾年同步.
錯誤日志
錯誤日志記錄著開啟與關閉MySQL服務的時間,以及服務運行過程中出現哪些異常等信息.配置文件里若沒有配置的話,一般名為hostname.err
設置錯誤日志
vim /etc/my.cnf
log-error=/PATH/TO/FILE #
log-warning={1|0}
/etc/init.d/mysqld restart
刪除錯誤日志
# mysqladmin -u root -p flush-logs
# 會將舊日志文件更名為filename.err-old
開啟的錯誤日志
mysql> flush logs;
通用查詢日志
默認情況下,通用查詢日志功能是關閉的.開啟后如果沒有指定日志文件名的話則默認名為HOSTNAME.log
開啟通用查詢日志
vim /etc/my.cnf
[mysqld]
log = [/PATH/TO/FILE]
/etc/init.d/mysqld restart
刪除通用查詢日志
mysqladmin -u root -p flush-logs
或手工刪除
慢查詢日志
默認情況下,慢查詢日志功能是關閉的.在配置文件開啟后如果沒有指定文件名,則名為HOSTNAME-slow.log
開啟慢查詢日志
vim /etc/my.cnf
[mysqld]
log-slow-queries[=/PATH/TO/FILE]
long_query_time=SECOND # 如果查詢超過這個時間,這個查詢語句將被記錄到慢查詢日志.
刪除慢查詢日志
mysqladmin -u root -p flush-logs
或手工刪除
中繼日志
從主服務器的二進制日志文件中復制而來的事件,并保存為日志文件.
事務日志
就像一個快照,同時記錄了新舊數據.事務性存儲引擎用于保證原子性 一致性 隔離性和持久性.即主要用于保證事務的可靠性.
innodb_flush_log_at_trx_commit
0: 每秒同步,并執行磁盤flush操作
1: 每事務同步,并執行磁盤flush操作
2: 每事務同步,但不執行磁盤flush
性能優化
優化查詢
分析查詢語句
explain select 語句
id: select語句的編號
select_type: select語句的類型
simple:簡單查詢
primary:主查詢或最外層的查詢語句
union: 連接查詢的第二個或后面的查詢語句
table: 查詢的表
type: 表示連接類型
system:表中只有一條記錄
const: 表中有多條記錄
all: 表示對表進行了完整的掃描
eq_ref: 表示多表連接時,后面的表使用了unique或者primary key;
ref:表示多表查詢時,后面的表使用了普通索引
unique_subquery: 表示子查詢中使用了unique或者primary key
index_subquery:表示子查詢中使用了普通索引
range: 表示查詢語句中給出了查詢范圍
index: 表示對表中的索引進行了完整的掃描
possible_keys: 表示查詢中可能使用的索引
key: 表示查詢使用到的索引
key_len: 表示索引字段的長度
ref: 表示使用哪個列或常數與索引一起來查詢記錄
rows: 表示查詢的行數
Extra: 表示查詢過程的附件信息
describe select 語句也可簡寫成desc
索引對查詢速度的影響
相當于新華字典的目錄可以大大加快你查找一個字的速度一樣,索引對于MySQL的功能也是類似,可以提高數據庫查詢的速度
使用索引查詢記錄時,一定要注意索引的使用情況.例如,like關鍵字配置的字符串不能以"%"開頭;使用多列索引時,查詢條件必須要使用這相索引的第一個字段;使用or關鍵字時,or關鍵字連接的所有條件都必須使用索引.
優化子查詢
盡量用連接查詢代替子查詢
優化數據庫結構
① 將字段很多的表分解成多個表**
② 增加中間表
③ 增加冗余字段.雖然有背三范式,但可以提高查詢速度.(因為不需要常連接多張表來查詢,一張表就可搞定)
④ 優化插入記錄的速度
1.臨時禁用\開啟索引
mysql> alter table TABNAME disable|enable keys;
2.禁用唯一性檢查
mysql> set unique_checks=[0|1] # 0為關閉,1為開啟
3.優化insert語句: 將多條對同一表進行操作的insert語句匯合成單條,可以減少與數據庫之間的連接等操作.
⑤ 分析表、檢查表和優化表
1.分析表
mysql> analyze table TAB1 [,TAB2 ...];
2.檢查表: 執行過程會給表加上只讀鎖
mysql> check table TAB1 [,TAB2 ..] [OPTION];
OPTION: 按執行效率從高到低(只對MyISAM類型表有效)
QUICK
FAST
CHANGED
MEDIUM
EXTENDED
3.優化表: 可以消除刪除和更新造成的磁盤碎片,執行過程中也會給表加上只讀鎖
mysql> optimize table TAB1 [,TAB2...];
服務器優化
- 增大MySQL服務器內存,并選擇my-innodb-heavy-4G.ini作為MySQL數據庫的配置文件.
- 添加多塊磁盤來存儲數據
- 優化MySQL參數
vim /etc/my.cnf
[mysqld]
key_buffer_size:
table_cache:
query_cache_size=0:
query_cahce_type:
max_connections=100: 最大連接數
sort_buffer_size:
read_buffer_size:
read_rnd_buffer_size:
innodb_buffer_pool_size:
innodb_flush_log_at_trx_commit: