1. 程式人生 > >許可權管理,資料備份、pymysql模組

許可權管理,資料備份、pymysql模組

許可權管理

許可權管理重點

MySQL 預設有個root使用者,但是這個使用者許可權太大,一般只在管理資料庫時候才用。如果在專案中要連線 MySQL 資料庫,則建議新建一個許可權較小的使用者來連線。

在 MySQL 命令列模式下輸入如下命令可以為 MySQL 建立一個新使用者:

create user "賬戶名"@"主機名" identified by 密碼
create user "tom"@"localhost" identified by "123";

新使用者建立完成,但是此刻如果以此使用者登陸的話,會報錯,因為我們還沒有為這個使用者分配相應許可權,分配許可權的命令如下:

授予所有資料庫所有表的所有許可權給jerry這個使用者  並允許jerry在任意一臺電腦登入
如果使用者不存在會自動建立
grant all on *.* to "jerry"@"%" identified by  "123" with grant option;

with grant option這個使用者可以將擁有的許可權授予別人

授予username使用者在所有資料庫上的所有許可權。

如果此時發現剛剛給的許可權太大了,如果我們只是想授予它在某個資料庫上的許可權,那麼需要切換到root 使用者撤銷剛才的許可權,重新授權:

授予day45資料庫所有表的所有許可權給jack這個使用者 並允許jerry在任意一臺電腦登入

grant all on  day45.* to "jack"@"%" identified by  "123";

授予day45資料庫的emp表的所有許可權給rose這個使用者 並允許jerry在任意一臺電腦登入

grant all on day45.emp to "rose"@"%" identified by "123";

授予day45資料庫的emp表的name欄位的查詢許可權給maria這個使用者 並允許jerry在任意一臺電腦登入

grant select(name) on day45.emp to "maria"@"%" identified by "123";

另外每當調整許可權後,通常需要執行以下語句重新整理許可權:

flush privileges;

收回許可權

REVOKE all privileges [column] on db.table from [email protected]"host";

如何授權就如何收回 因為不同許可權資訊存到不同的表中

REVOKE all privileges on day45.emp from [email protected]"%"; 

當你在雲伺服器部署了 mysql環境時 你的程式無法直接連線到伺服器 需要授予在任意一臺電腦登入的許可權

grant all on *.* to "jerry"@"%" identified by "123" with grant option;

刪除剛才建立的使用者:

DROP USER 使用者名稱@localhost;

仔細上面幾個命令,可以發現不管是授權,還是撤銷授權,都要指定響應的host(即 @ 符號後面的內容),因為以上及格命令實際上都是在操作mysql 資料庫中的user表,可以用如下命令檢視相應使用者及對應的host:

SELECT User, Host FROM user;

許可權表

MySQL伺服器通過MySQL許可權表來控制使用者對資料庫的訪問,MySQL許可權表存放在mysql資料庫裡,由mysql_install_db指令碼初始化。這些MySQL許可權表分別user,db,table_priv,columns_priv和host。下面分別介紹一下這些表的結構和內容:
user許可權表:記錄允許連線到伺服器的使用者帳號資訊,裡面的許可權是全域性級的。
db許可權表:記錄各個帳號在各個資料庫上的操作許可權。
table_priv許可權表:記錄資料表級的操作許可權。
columns_priv許可權表:記錄資料列級的操作許可權。
host許可權表:配合db許可權表對給定主機上資料庫級操作許可權作更細緻的控制。這個許可權表不受GRANT和REVOKE語句的影響。

許可權列表

ALTER: 修改表和索引。
CREATE: 建立資料庫和表。
DELETE: 刪除表中已有的記錄。
DROP: 拋棄(刪除)資料庫和表。
INDEX: 建立或拋棄索引。
INSERT: 向表中插入新行。
REFERENCE: 未用。
SELECT: 檢索表中的記錄。
UPDATE: 修改現存表記錄。
FILE: 讀或寫伺服器上的檔案。
PROCESS: 檢視伺服器中執行的執行緒資訊或殺死執行緒。
RELOAD: 過載授權表或清空日誌、主機快取或表快取。
SHUTDOWN: 關閉伺服器。
ALL: 所有許可權,ALL PRIVILEGES同義詞。
USAGE: 特殊的 "無許可權" 許可權。
用 戶賬戶包括 "username" 和 "host" 兩部分,後者表示該使用者被允許從何地接入。[email protected]'%' 表示任何地址,預設可以省略。還可以是 "[email protected]%"、"[email protected]%.abc.com" 等。資料庫格式為 [email protected],可以是 "test.*" 或 "*.*",前者表示 test 資料庫的所有表,後者表示所有資料庫的所有表。
子句 "WITH GRANT OPTION" 表示該使用者可以為其他使用者分配許可權。 

補充知識

grant和revoke可以在幾個層次上控制訪問許可權
1,整個伺服器,使用 grant ALL 和revoke ALL
2,整個資料庫,使用on database.*
3,特點表,使用on database.table
4,特定的列
5,特定的儲存過程

user表中host列的值的意義
% 匹配所有主機
localhost localhost不會被解析成IP地址,直接通過UNIXsocket連線
127.0.0.1 會通過TCP/IP協議連線,並且只能在本機訪問;
::1 ::1就是相容支援ipv6的,表示同ipv4的127.0.0.1

grant 普通資料使用者,查詢、插入、更新、刪除 資料庫中所有表資料的權利。
grant select on testdb.* to [email protected]’%’
grant insert on testdb.* to [email protected]’%’
grant update on testdb.* to [email protected]’%’
grant delete on testdb.* to [email protected]’%’
或者,用一條 MySQL 命令來替代:
grant select, insert, update, delete on testdb.* to [email protected]’%’
grant 資料庫開發人員,建立表、索引、檢視、儲存過程、函式。。。等許可權。
grant 建立、修改、刪除 MySQL 資料表結構許可權。
grant create on testdb.* to [email protected]’192.168.0.%’;
grant alter on testdb.* to [email protected]’192.168.0.%’;
grant drop on testdb.* to [email protected]’192.168.0.%’;
grant 操作 MySQL 外來鍵許可權。
grant references on testdb.* to [email protected]’192.168.0.%’;
grant 操作 MySQL 臨時表許可權。
grant create temporary tables on testdb.* to [email protected]’192.168.0.%’;
grant 操作 MySQL 索引許可權。
grant index on testdb.* to [email protected]’192.168.0.%’;
grant 操作 MySQL 檢視、檢視檢視原始碼 許可權。
grant create view on testdb.* to [email protected]’192.168.0.%’;
grant show view on testdb.* to [email protected]’192.168.0.%’;
grant 操作 MySQL 儲存過程、函式 許可權。
grant create routine on testdb.* to [email protected]’192.168.0.%’; -- now, can show procedure status
grant alter routine on testdb.* to [email protected]’192.168.0.%’; -- now, you can drop a procedure
grant execute on testdb.* to [email protected]’192.168.0.%’;
grant 普通 DBA 管理某個 MySQL 資料庫的許可權。
grant all privileges on testdb to [email protected]’localhost’
其中,關鍵字 “privileges” 可以省略。
grant 高階 DBA 管理 MySQL 中所有資料庫的許可權。
grant all on *.* to [email protected]’localhost’

MySQL grant 許可權,分別可以作用在多個層次上。
1. grant 作用在整個 MySQL 伺服器上:
grant select on *.* to [email protected]; -- dba 可以查詢 MySQL 中所有資料庫中的表。
grant all on *.* to [email protected]; -- dba 可以管理 MySQL 中的所有資料庫
2. grant 作用在單個數據庫上:
grant select on testdb.* to [email protected]; -- dba 可以查詢 testdb 中的表。
3. grant 作用在單個數據表上:
grant select, insert, update, delete on testdb.orders to [email protected];
4. grant 作用在表中的列上:
grant select(id, se, rank) on testdb.apache_log to [email protected];
5. grant 作用在儲存過程、函式上:
grant execute on procedure testdb.pr_add to ’dba’@’localhost’
grant execute on function testdb.fn_add to ’dba’@’localhost’

注意:修改完許可權以後 一定要重新整理服務,或者重啟服務,重新整理服務用:FLUSH PRIVILEGES。

IDE工具介紹

生產環境還是推薦使用mysql命令列,但為了方便我們測試,可以使用IDE工具,不能依賴這種ide

掌握:
1. 測試+連結資料庫
2. 新建庫
3. 新建表,新增欄位+型別+約束
4. 設計表:外來鍵
5. 新建查詢
6. 備份庫/表

注意:
批量加註釋:ctrl+?鍵
批量去註釋:ctrl+shift+?鍵

MySQL資料備份

1. 物理備份: 直接複製資料庫檔案,適用於大型資料庫環境。但不能恢復到異構系統中如Windows。
2. 邏輯備份: 備份的是建表、建庫、插入等操作所執行SQL語句,適用於中小型資料庫,效率相對較低。
3. 匯出表: 將表匯入到文字檔案中。

使用mysqldump實現邏輯備份

語法:
 mysqldump -h 伺服器 -u使用者名稱 -p密碼 資料庫名 > 備份檔案.sql

示例:
單庫備份
mysqldump -uroot -p123 db1 > db1.sql
mysqldump -uroot -p123 db1 table1 table2 > db1-table1-table2.sql

多庫備份
mysqldump -uroot -p123 --databases db1 db2 mysql db3 > db1_db2_mysql_db3.sql

備份所有庫
mysqldump -uroot -p123 --all-databases > all.sql 

恢復邏輯備份

方法一:
[[email protected] backup]# mysql -uroot -p123 < /backup/all.sql

方法二:
mysql> use db1;
mysql> SET SQL_LOG_BIN=0;
mysql> source /root/db1.sql

注:如果備份/恢復單個庫時,可以修改sql檔案
DROP database if exists school;
create database school;
use school;

備份/恢復案例

#資料庫備份/恢復實驗一:資料庫損壞
備份:
1. # mysqldump -uroot -p123 --all-databases > /backup/`date +%F`_all.sql
2. # mysql -uroot -p123 -e 'flush logs' //截斷併產生新的binlog
3. 插入資料 //模擬伺服器正常執行
4. mysql> set sql_log_bin=0; //模擬伺服器損壞
mysql> drop database db;

恢復:
1. # mysqlbinlog 最後一個binlog > /backup/last_bin.log
2. mysql> set sql_log_bin=0; 
mysql> source /backup/2014-02-13_all.sql //恢復最近一次完全備份 
mysql> source /backup/last_bin.log //恢復最後個binlog檔案


#資料庫備份/恢復實驗二:如果有誤刪除
備份:
1. mysqldump -uroot -p123 --all-databases > /backup/`date +%F`_all.sql
2. mysql -uroot -p123 -e 'flush logs' //截斷併產生新的binlog
3. 插入資料 //模擬伺服器正常執行
4. drop table db1.t1 //模擬誤刪除
5. 插入資料 //模擬伺服器正常執行

恢復:
1. # mysqlbinlog 最後一個binlog --stop-position=260 > /tmp/1.sql 
# mysqlbinlog 最後一個binlog --start-position=900 > /tmp/2.sql 
2. mysql> set sql_log_bin=0; 
mysql> source /backup/2014-02-13_all.sql //恢復最近一次完全備份
mysql> source /tmp/1.log //恢復最後個binlog檔案
mysql> source /tmp/2.log //恢復最後個binlog檔案

注意事項:
1. 完全恢復到一個乾淨的環境(例如新的資料庫或刪除原有的資料庫)
2. 恢復期間所有SQL語句不應該記錄到binlog中
View Code

實現自動化備份

備份計劃:
1. 什麼時間 2:00
2. 對哪些資料庫備份
3. 備份檔案放的位置

備份指令碼:
[[email protected] ~]# vim /mysql_back.sql
#!/bin/bash
back_dir=/backup
back_file=`date +%F`_all.sql
user=root
pass=123

if [ ! -d /backup ];then
mkdir -p /backup
fi

# 備份並截斷日誌
mysqldump -u${user} -p${pass} --events --all-databases > ${back_dir}/${back_file}
mysql -u${user} -p${pass} -e 'flush logs'

# 只保留最近一週的備份
cd $back_dir
find . -mtime +7 -exec rm -rf {} \;

手動測試:
[[email protected] ~]# chmod a+x /mysql_back.sql 
[[email protected] ~]# chattr +i /mysql_back.sql
[[email protected] ~]# /mysql_back.sql

配置cron:
[[email protected] ~]# crontab -l
2 * * * /mysql_back.sql
View Code

表的匯出和匯入

SELECT... INTO OUTFILE 匯出文字檔案
示例:
mysql> SELECT * FROM school.student1
INTO OUTFILE 'student1.txt'
FIELDS TERMINATED BY ',' //定義欄位分隔符
OPTIONALLY ENCLOSED BY '”' //定義字串使用什麼符號括起來
LINES TERMINATED BY '\n' ; //定義換行符


mysql 命令匯出文字檔案
示例:
# mysql -u root -p123 -e 'select * from student1.school' > /tmp/student1.txt
# mysql -u root -p123 --xml -e 'select * from student1.school' > /tmp/student1.xml
# mysql -u root -p123 --html -e 'select * from student1.school' > /tmp/student1.html

LOAD DATA INFILE 匯入文字檔案
mysql> DELETE FROM student1;
mysql> LOAD DATA INFILE '/tmp/student1.txt'
INTO TABLE school.student1
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '”'
LINES TERMINATED BY '\n';

  

#可能會報錯
mysql> select * from db1.emp into outfile 'C:\\db1.emp.txt' fields terminated by ',' lines terminated by '\r\n';
ERROR 1238 (HY000): Variable 'secure_file_priv' is a read only variable


#資料庫最關鍵的是資料,一旦資料庫許可權洩露,那麼通過上述語句就可以輕鬆將資料匯出到檔案中然後下載拿走,因而mysql對此作了限制,只能將檔案匯出到指定目錄
在配置檔案中
[mysqld]
secure_file_priv='C:\\' #只能將資料匯出到C:\\下

重啟mysql
重新執行上述語句
View Code

資料庫遷移

務必保證在相同版本之間遷移
mysqldump -h 源IP -uroot -p123 --databases db1 | mysql -h 目標IP -uroot -p456

pymysql模組

dos命令安裝
pip3 install pymysql

準備工作

create database userinfo;
use userinfo;
create table regis(name char(10) unique not null,password int(10) not null);
insert into regis values('xuxu',123456);

建立連結、執行sql、關閉(遊標)

import pymysql
user=input('使用者名稱: ').strip()
pwd=input('密碼: ').strip()

#連結
conn=pymysql.connect(host='localhost',user='root',password='1234',database='userinfo',charset='utf8')
#遊標
cursor=conn.cursor() #執行完畢返回的結果集預設以元組顯示
#cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)  #這種以字典的形式輸出的可以很直觀的看到欄位和記錄


#執行sql語句
sql='select * from regis where name="%s" and password="%s"' %(user,pwd) #注意%s需要加引號
print(sql)
res=cursor.execute(sql) #執行sql語句,返回sql查詢成功的記錄數目
print(res)

cursor.close()
conn.close()

if res:
    print('登入成功')
else:
    print('登入失敗')

執行結果:
使用者名稱: xuxu
密碼: 123456
select * from regis where name="xuxu" and password="123456"
1
登入成功

execute()之sql注入

注意:符號--會註釋掉它之後的sql,正確的語法:--後至少有一個任意字元

根本原理:就根據程式的字串拼接name='%s',我們輸入一個xxx' -- haha,用我們輸入的xxx加'在程式中拼接成一個判斷條件name='xxx' -- haha'

最後那一個空格,在一條sql語句中如果遇到select * from t1 where id > 3 -- and name='xuxu';則--之後的條件被註釋掉了

1、sql注入之:使用者存在,繞過密碼
xuxu' -- 任意字元

2、sql注入之:使用者不存在,繞過使用者與密碼
xxx' or 1=1 -- 任意字元

 

出現了一點bug,未完待續

 

解決辦法

原來是我們對sql進行字串拼接
 sql="select * from userinfo where name='%s' and password='%s'" %(user,pwd)
 print(sql)
 res=cursor.execute(sql)

改寫為(execute幫我們做字串拼接,我們無需且一定不能再為%s加引號了)
sql="select * from userinfo where name=%s and password=%s" #!!!注意%s需要去掉引號,因為pymysql會自動為我們加上
res=cursor.execute(sql,[user,pwd]) #pymysql模組自動幫我們解決sql注入的問題,只要我們按照pymysql的規矩來。

增、刪、改:conn.commit()

import pymysql
#連結
conn=pymysql.connect(host='localhost',user='root',password='123',database='egon')
#遊標
cursor=conn.cursor()

#執行sql語句
#part1
# sql='insert into userinfo(name,password) values("root","123456");'
# res=cursor.execute(sql) #執行sql語句,返回sql影響成功的行數
# print(res)

#part2
# sql='insert into userinfo(name,password) values(%s,%s);'
# res=cursor.execute(sql,("root","123456")) #執行sql語句,返回sql影響成功的行數
# print(res)

#part3
sql='insert into userinfo(name,password) values(%s,%s);'
res=cursor.executemany(sql,[("root","123456"),("lhf","12356"),("eee","156")]) #執行sql語句,返回sql影響成功的行數
print(res)

conn.commit() #提交後才發現表中插入記錄成功
cursor.close()
conn.close()

查:fetchone,fetchmany,fetchall

import pymysql
#連結
conn=pymysql.connect(host='localhost',user='root',password='123',database='egon')
#遊標
cursor=conn.cursor()

#執行sql語句
sql='select * from userinfo;'
rows=cursor.execute(sql) #執行sql語句,返回sql影響成功的行數rows,將結果放入一個集合,等待被查詢

# cursor.scroll(3,mode='absolute') # 相對絕對位置移動
# cursor.scroll(3,mode='relative') # 相對當前位置移動
res1=cursor.fetchone()
res2=cursor.fetchone()
res3=cursor.fetchone()
res4=cursor.fetchmany(2)
res5=cursor.fetchall()
print(res1)
print(res2)
print(res3)
print(res4)
print(res5)
print('%s rows in set (0.00 sec)' %rows)



conn.commit() #提交後才發現表中插入記錄成功
cursor.close()
conn.close()

'''
(1, 'root', '123456')
(2, 'root', '123456')
(3, 'root', '123456')
((4, 'root', '123456'), (5, 'root', '123456'))
((6, 'root', '123456'), (7, 'lhf', '12356'), (8, 'eee', '156'))
rows in set (0.00 sec)
'''

獲取插入的最後一條資料的自增ID

import pymysql
conn=pymysql.connect(host='localhost',user='root',password='123',database='egon')
cursor=conn.cursor()

sql='insert into userinfo(name,password) values("xxx","123");'
rows=cursor.execute(sql)
print(cursor.lastrowid) #在插入語句後檢視

conn.commit()

cursor.close()
conn.close()