許可權管理,資料備份、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.sqlView 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()