數據庫的目標是爲了數據的集中管理和共享。但是數據庫中的數據針對不同的人本就應該有不同的訪問權限,以下就是對數據訪問管理的概況。
9.1 用戶管理
MySQL的用戶分兩類:
- 超級管理員用戶root(在安裝時已默認建立,密碼爲空,擁有數據庫中的所有權限如數據庫的備份與還原),
- 普通用戶(由管理員創建,只擁有創建時管理員賦予的權限)
MySQL的用戶信息是存放在數據庫mysql的user表中的。
因此,在MySQL中,對用戶的管理,既可以使用MySQL特定的語句,也可以使用標準的SQL語句,當然前提是擁有相關權限。
用戶信息存放在數據庫mysql中的user表中。
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sakila |
| sys |
| world |
+--------------------+
10 rows in set (0.01 sec)
mysql> use mysql;
Database changed
mysql> show tables;
+---------------------------+
| Tables_in_mysql |
+---------------------------+
| columns_priv |
| .... |
| user |
+---------------------------+
33 rows in set (0.03 sec)
mysql> desc user;
// 查看user表結構
// 這裏重點關注三個字段:
// host:可以登錄數據庫的主機地址
// user:用戶名
// authentication_string:加密過的登陸密碼
// _priv 結尾的字段:表明用戶的權限
基本語法:
create user 用戶名@主機名
//用戶名區分大小寫,主機名連接來自的主機;百分符表示一組主機,localhost表示本地主機
[ identified by [password] ‘密碼’]
//密碼區分大小寫;password省略則自動用密碼函數進行加密,不省略則用加密函數後的明文作爲密碼
[ , 用戶名@主機名[identified by [password][‘密碼’]] [ ,... ]
//可以同時創建多個數據庫用戶,中間用逗號分隔。
實踐:
mysql> create user cat@localhost identified by 'cat123';
Query OK, 0 rows affected (0.02 sec)
mysql> select host,user,authentication_string from user;
+-----------+------------------+------------------------------------------------------------------------+
| host | user | authentication_string |
+-----------+------------------+------------------------------------------------------------------------+
| localhost | cat | $A$005$I3X*!v/Uf2+Ef^pBk08rUDb.7YBIitg3KJ622TocHgkbzQCHzfLTLy117 |
+-----------+------------------+------------------------------------------------------------------------+
mysql> exit
GRANT語句給用戶分配權限
基本語法:
grant 權限類別//權限類別表示各類權限,用逗號隔開;
on 數據庫名.表名
to 用戶名@主機名
[,用戶名@主機名] [,...]
實踐證明貌似Grant語句在8.0.18版本里不能添加用戶,只能附加權限。
修改用戶名
rename user 舊用戶名@主機名 to 新用戶名@主機名;
mysql> rename user cat@localhost to mouse@localhost;
Query OK, 0 rows affected (0.02 sec)
//要爲現有帳戶分配或更改密碼,請將該 ALTER USER語句與以下IDENTIFIED BY子句一起使用 :
ALTER USER 'jeffrey'@'localhost' IDENTIFIED BY 'password';
//如果您不是以匿名用戶身份連接的,則可以更改自己的密碼,而無需直接命名自己的帳戶:
ALTER USER USER() IDENTIFIED BY 'password';
刪除用戶
drop user 用戶名[,..]
drop user mouse@localhost;
9.2 權限管理
9.2.1 權限管理概述
MySql中權限表:
表 | 介紹 |
---|---|
user | 最重要的權限表,存儲允許連接到服務器的賬號。 |
db | 存儲用戶對某個數據庫的操作權限。 |
host | 存儲某個主機對數據庫的操作權限。 |
tables_priv | 對單個表進行權限設置。 |
columns_priv | 對單個數據列進行權限設置。 |
proc_priv | 對存儲過程和存儲函數進行權限設置。 |
重點補充:
- 表示對錶進行操作的權限。包括Select /Insert /Update /Delete/ Create/ Drop / Grant / References / Index 和Alter
MySQL的訪問控制的兩個階段
- 連接覈實階段
用戶試圖連接MySQL服務器時,服務器基於用戶提供的信息來驗證用戶身份。使用MySQL的user表進行身份覈實 - 請求覈實階段
對當前用戶的每個操作都進行權限檢查,判斷用戶是否有足夠的權限來執行它。
權限的遞進:先檢查user表、然後db、host,再…直到conlumns_priv中都沒有,就拒絕請求。
MySQL權限等級:
- 全局層級:適用於一個給定服務器中所有的數據庫,權限存儲於
user
。 - 數據庫層級:適用於一個給定數據庫中的所有目標,權限在
db
與host
。 - 表層級:適用於一個給定表中的所有列,權限在
tables_priv
。 - 列層級:適用於一個給定表中的單一列,權限在
columns_priv
。 - 子程序層級:適用於存儲的子程序 ,可以被授權爲全局層級和數據庫層級,權限在
proc_priv
。
MySQL權限類型
權限 | 含義 |
---|---|
all[privileges] | 設置除grant option之外的所有簡單權限 |
alter | 允許使用alter table |
alter routine | 更改或取消已存儲的子過程 |
create | 允許使用create table |
create routine | 創建已存儲的子過程 |
create temporary table | 允許使用create temporary table |
create user | 允許使用create user, drop user, rename,user 和 revoke all privileges |
create view | 允許使用create view |
delete | 允許使用delete |
drop | 允許使用drop table |
execute | 允許用戶運行已存儲的子程序 |
file | 允許使用select…into outfile 和 load data infile |
index | 允許使用create index 和 drop index |
insert | 允許使用insert |
lock tables | 允許對用戶擁有select權限的表使用lock tables |
process | 允許使用show full processlist |
references | 未被實施 |
reload | 允許使用flush |
replication client | 允許用戶詢問從屬服務器或主服務器的地址 |
replication slave | 用於複製性從屬服務器(從主服務器中讀取二進制日誌文件) |
select | 允許使用select |
show databases | 允許顯示所有數據庫 |
show view | 允許使用show create view |
shutdown | show view MySQLadmin shutdown |
super | 允許使用change master,kill,purge masterlogs 和set global 語句;MySQLadmin debug命令;允許用戶連接(一次),即使已達到max_connections; |
update | 允許使用update |
usage | “無權限”的同義詞 |
9.2.2 權限管理語法
grant獲取權限:
grant priv_type [(column_list)] //要設置的權限項;
[,priv_type[(column_list)]][,.....n] on
{tbl_name|*|*.*|db_name.*|db_name.tbl_name} //對象類型;
to user[,user][,....n]
[with grant_option] //可以將該用戶的權限轉移給其他用戶;
在MySQL8以上,grant已經沒辦法創建新用戶了
實例:
mysql> grant select on *.* to aa@localhost identified by '123' with grant option;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'identified by '123' with grant option' at line 1
mysql> grant select on *.* to mat@localhost with grant option;
Query OK, 0 rows affected (0.01 sec)
————————————————————————
用revoke收回權限
revoke priv_type [(column_list)][,priv_type[(column_list)]][,.....n] on
{tbl_name|*|*.*|db_name.*|db_name.tbl_name}
from ‘username’@’hostname’[,‘username’@’hostname’][,...n]
實例:收回mat所有權限
mysql> revoke all privileges,grant option from mat@localhost;
Query OK, 0 rows affected (0.01 sec)
————————————————————————————————
查看用戶權限
show grants for username@hostname
實踐:查看mat的權限
mysql> show grants for mat@localhost;
+-----------------------------------------+
| Grants for mat@localhost |
+-----------------------------------------+
| GRANT USAGE ON *.* TO `mat`@`localhost` |
+-----------------------------------------+
1 row in set (0.00 sec)
————————————————————————
限制權限
max_queries_per_hour count:表示每小時可以查詢數據庫的次數
max_connections_per_hour count:表示每小時可以連接數據庫的次數
max_updates_per_hour count:表示每小時可以修改數據庫的次數
實例:
grant all on *.* to test1@localhost
with max_queries_per_hour 50
with max_connections_per_hour 10
with max_updates_per_hour 5;
————————————————————————————————————————
既然權限是存放在對應的表中,那麼如果我們手動更新了權限表,是否MySQL服務器會自動立刻生效呢?如果不能,那使用什麼方法可以讓手動修改的權限生效呢?
9.3 備份與恢復
MySQL保證數據安全的三種方法:
- 數據庫備份:通過導出數據或表文件的拷貝來保護數據
- 二進制日誌文件:保存更新數據的所有語句
- 數據庫複製:使用MySQL內部複製功能,建立在兩個或兩個以上的數據庫之間的,通過設定它們的主次關係而實現的。
備份:將數據庫中的結構、對象和數據導出,生成副本。
備份的分類:
- 按照備份時服務器是否在線:
熱備份:是指數據庫在線服務正常的情況下進行數據備份。
溫備份:是指備份時數據庫在線正常運行,但數據只能讀不能寫。
冷備份:是指數據庫已經正常關閉的情況下進行備份。 - 按照備份的內容:
邏輯備份:該文件格式與原數據庫文件格式不同,通常備份的是SQL語句(也就是DDL和insert 語句)。
物理備份:直接複製數據庫文件進行備份,與邏輯備份相比,其速度快,但佔用的存儲空間比較大。 - 按備份涉及的數據範圍:
完整備份:備份整個數據庫。增量備份與差異備份依賴於完整備份。
增量備份:備份數據庫從上一次完全備份或者最近一次增量備份以來改變的內容。
差異備份:將從最近一次完整數據庫備份以後發生改變的數據進行備份。
備份的時機:
- 創建數據庫或爲數據庫填充數據後 備份數據庫
- 創建索引後 備份數據庫
- 清理事務日誌後備份數據庫,清理事務日誌後 備份數據庫
- 執行了無日誌操作後備份數據庫 備份數據庫
9.3.1 備份方法
mysqldump命令的語法格式
mysqldump -u user -h host -ppassword
[--databases]databasename[,databasename2] //可以指定多個數據庫;
[all-databases]//可以指定所有數據庫;
[tablename=,[tablename=...]] //可以指定特定表;
> filename.sql //輸出文件名,可以指定路徑;
實例:
備份所有表:使用mysqldump備份數據庫Course中所有的表。
mysqldump -u root -p Course > d:/backup/Course.sql
備份指定表:使用mysqldump備份數據庫Course中的student表和teacher表。
mysqldump -u root -p Course student,teacher >d:/backup/Course_teacher_student.sql
備份多個指定數據庫:使用mysqldump備份數據庫Course 和mysql。
mysqldump -u root -p --databases Course,mysql >d:/backup/Course_mysql.sql
9.3.2 備份恢復
恢復數據庫,就是讓數據庫根據備份的數據回到備份時的狀態。主要的方法:
使用mysql命令恢復
mysql -u user -h host -ppassword databasename < filename.sql //注意箭頭方向
使用mysql將備份文件Course.sql恢復到數據庫Course2中。
mysql -u root -p Course2 < d:\backup\Course.sql
使用souce語句恢復
source filename.sql //需要進入到數據庫後運行。
使用source命令將備份文件Course.sql恢復到數據庫Course3中。
create course3;
use course3;
source d:\backup\Course.sql;
9.4 日誌管理
日誌是記錄數據庫日常操作和錯誤信息的文件,當數據遭遇意外發生丟失時可以通過日誌文件來查詢原因,並且通過日誌文件進行數據恢復。
日誌文件種類
- 錯誤日誌
記錄MySQL數據庫的啓動,運行和停止時出現的問題,文本文件格式,默認開啓。 - 二進制日誌
記錄了數據庫中所有更改數據的語句,可用於修復數據庫,二進制文件的格式,默認關閉。 - 通用查詢日誌
記錄用戶登陸和記錄查詢的信息,文本文件格式,默認關閉。 - 慢查詢日誌
記錄所有執行時間超過long_query_time秒的查詢或不使用索引的查詢,文本文件格式,默認關閉。
詳情
1、錯誤日誌:
默認是開啓的,並且無法被禁止。
默認存儲在MySQL數據庫的數據庫文件夾下。
通常錯誤日誌的文件名爲“主機名.err”。
可以通過修改配置選項log-err來更改。
通過修改配置選項log-error來更改路徑和日誌名:
[mysqld]
log-error[ =path/filename] #修改錯誤日誌存放位置及文件名
查詢錯誤日誌位置
mysql> show variables like 'log_error';
+---------------+--------------------+
| Variable_name | Value |
+---------------+--------------------+
| log_error | .\HEARTFORLING.err |
+---------------+--------------------+
1 row in set, 1 warning (0.03 sec)
刪除錯誤日誌
mysqladmin -u root -p flush -logs
本質上是更新錯誤日誌,創建出一個新的錯誤日誌,舊的錯誤日誌改名爲:'原文件名.err-old'
2、二進制日誌:
默認是關閉的,通過修改my.ini配置文件的log-bin選項開啓。
[mysqld]
log-bin[ =path/[filename]] #開啓二進制日誌
Expire_logs_days=10 #定義自動清除日誌的時間(天數)
max_binlog_size=100M #定義單個二進制文件的大小限制
如何查看二進制日誌?
mysqlbinlog XXXX-bin.0001
mysqlbinlog命令恢復數據庫:
mysqlbinlog [option] filename mysql -u user -ppassword
option:可選參數,常見的參數有
--start-date (--stop-date) :用於指定數據庫恢復的起始時間和結束時間點。
--start-position (--stop-position): 可以指定恢復數據庫的開始位置和結束位置。
刪除所有二進制日誌
reset master
刪除指定的日誌文件
可以根據編號或者創建的時間來刪除,語法格式是:
purge {binary|master} logs to ‘log_name’
purge {binary|master} logs before ‘data’
3、通用查詢日誌:
默認是關閉的,通過修改my.ini配置文件的log選項開啓。
[mysqld]
log[ =path/filename] #開啓通用查詢日誌
4、慢查詢日誌:
默認是關閉的,通過修改my.ini配置文件的log-slow- queries選項開啓。
[mysqld]
log-slow-queries[ =path/filename] #開啓慢查詢日誌
long_query_time = n #最慢的查詢時間,單位是秒,默認值是10
9.5 事務處理
一個事務由一條或者多條SQL語句組成,這些SQL語句相互依賴不可分割,如果其中的某一條SQL語句沒能完成,前面已經執行的SQL語句就會撤銷,回滾到事務開始前的狀態。
事務的四個特性(ACID):
原子性(Atomicity):事務作爲一個整體被執行,包含在其中的對數據庫的操作要麼全部被執行,要麼都不執行。
一致性(Consistency):事務應確保數據庫的狀態從一個一致狀態轉變爲另一個一致狀態。
隔離性(Isolation):多個事務併發執行時,一個事務的執行不應影響其他事務的執行。
持久性(Durability):已被提交的事務對數據庫的修改應該永久保存在數據庫中。
9.5.1 MySQL事務類型
系統定義事務:
默認情況下,每條單獨的語句都是一個事務。語句執行完後,MySQL會自動提交,也就是立刻將結果存儲到磁盤中。如要顯式關閉自動提交:使用的語句set @@autocommit=0;
用戶定義事務:
用戶自定義開始,結束,回滾和提交等事務的狀態,用到的語句爲:
start transaction |begin work:開啓事務。
commit[ work] [and [no] chain] [[no] release]:提交事務
Rollback [work][and [no] chain] [[no] release]:回滾事務
會隱式地執行一個commit命令的語句:
drop database / drop table / create index /
drop index / alter table / rename table /
lock tables / unlock tables / set @@autocommit=1
rollback to 語句使事務回滾到某點,需要事先設置一個保存點:
設置保存點使用的語句
savepoint identifier
Rollback [work] to identifier
9.5.2 MySQL設置隔離級別
MySQL四種隔離級別:
序列化(SERIALIZABLE):用戶之間通過一個接一個順序地執行當前事務,這種方式提供了事務之間最大限度的隔離。
可重複讀(REPEATABLE READ):MySQL默認隔離級,適用於大多數應用程序。它確保同一事務內相同的查詢語句執行結果一致。
提交讀(READ COMMITTED):滿足了隔離的簡單定義,一個事務只能看見已提交事務所做的改變。
未提交讀(READ UNCOMMITTED):提供了事務之間最小程度的隔離。這個級別下,所有事務都可以看到其他未提交事務的執行結果。
!隔離級別強度(從左到右減弱):序列化、可重複讀、提交讀、未提交讀。
使用SET TRANSACTION 語句定義隔離級:
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL
SERIALIZABLE |
REPEATABLE READ |
READ COMMITTED |
READ COMMITTED
9.5.3 MySQL事務併發
事務的併發,鎖定的機制:
表級鎖:一種特殊類型的訪問,整個表被客戶鎖定。
頁級鎖:鎖定表中的某幾行(稱作頁)
行級鎖:只有線程使用的行被鎖定,其他行對於其他線程是可用的。
MySQL提供LOCK 語句來鎖定當前線程的表,語法格式是:
LOCK TABLES table_name [as alias ] {
read [local] | # 用戶可以讀取表,但是不能修改表
[low_priority] write #只有鎖定該表的用戶可以修改表,其他的用戶無法訪問該表。
}
解除鎖定:
UNLOCK Table;//不需要指定表,會解鎖所有表