一 IDE工具介紹
生產環境還是推薦使用mysql命令行,但為了方便測試,可以使用IDE工具
下載鏈接:https://pan.baidu.com/s/1bpo5mqj
掌握: #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
二、恢復邏輯備份
#方法一: [root@egon 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中
四、實現自動化備份
備份計划: 1. 什么時間 2:00 2. 對哪些數據庫備份 3. 備份文件放的位置 備份腳本: [root@egon ~]# 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 {} \; 手動測試: [root@egon ~]# chmod a+x /mysql_back.sql [root@egon ~]# chattr +i /mysql_back.sql [root@egon ~]# /mysql_back.sql 配置cron: [root@egon ~]# crontab -l 0 2 * * * /mysql_back.sql
五、表的導出和導入
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';
六、數據庫遷移
務必保證在相同版本之間遷移 # mysqldump -h 源IP -uroot -p123 --databases db1 | mysql -h 目標IP -uroot -p456
七 pymysql模塊
#安裝 pip3 install pymysql
一 鏈接、執行sql、關閉(游標)
#!/usr/bin/python import pymysql conn=pymysql.connect(host='localhost',user='root',password='',database='db8') cursor=conn.cursor() sql='select * from user where id=1' print(sql) rows=cursor.execute(sql) print('%s row in set(0.00 sec)'%rows) #conn.commit() cursor.close() #關閉光標連接 conn.close() #關閉連接 ''' 執行結果: [root@localhost pythonfile]# python3 s1.py select * from user where id=1 1 row in set(0.00 sec) #顯示1條記錄 '''
驗證登陸
#!/usr/bin/python import pymysql name=input('用戶名>>: ').strip() pwd=input('密碼:>>: ').strip() conn=pymysql.connect(host='localhost',user='root',password='',database='db8') #建立連接 cursor=conn.cursor() #連接游標 mysql> sql='select * from user where user="%s" and password="%s";' %(name,pwd) print(sql) rows=cursor.execute(sql) #print('%s row in set(0.00 sec)'%rows) #conn.commit() cursor.close() #關閉游標 conn.close() #關閉連接 if rows: print('登陸成功') else: print('登陸失敗') ''' 驗證結果: [root@localhost pythonfile]# python3 sql.py 用戶名>>: egon 密碼:>>: 221a select * from user where user="egon" and password="221a"; 登陸成功 '''
二 execute()之sql注入
注意:符號--會注釋掉它之后的sql,正確的語法:--后至少有一個任意字符
根本原理:就根據程序的字符串拼接name='%s',我們輸入一個xxx' -- haha,用我們輸入的xxx加'在程序中拼接成一個判斷條件name='xxx' -- haha'
最后那一個空格,在一條sql語句中如果遇到select * from t1 where id > 3 -- and name='egon';則--之后的條件被注釋掉了 #1、sql注入之:用戶存在,繞過密碼 egon' -- 任意字符 #2、sql注入之:用戶不存在,繞過用戶與密碼 xxx' or 1=1 -- 任意字符
[root@localhost pythonfile]# python3 sql.py 用戶名>>: egon" -- xxxxx 密碼:>>: select * from user where user="egon" -- xxxxx" and password=""; #--之后的的sql均被注釋掉了 登陸成功 #繞過密碼直接登錄成功
缺點:如果不能知道用戶名就不能進行
繞過用戶名登錄:
[root@localhost pythonfile]# python3 sql.py 用戶名>>: xxx" or 1=1 -- sssss 密碼:>>: select * from user where user="xxx" or 1=1 -- sssss" and password=""; 登陸成功
解決sql注入的方法
# 原來是我們對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()
#!/usr/bin/python import pymysql conn=pymysql.connect(host='localhost',user='root',password='',database='db8',charset='utf8' ) cursor=conn.cursor() sql='insert into user(name,password) values(%s,%s);' rows=cursor.execute(sql,('alex','123')) #單條插入 rows=cursor.executemany(sql,[('ss','121'),('laowu','111')]) #多條插入 print('%s row in set (0.00 sec)' %rows) conn.commit() cursor.close() conn.close() ''' mysql> select * from user; +----+-------+----------+ | id | name | password | +----+-------+----------+ | 1 | egon | 123 | | 2 | egon1 | 123 | | 3 | alex | 123 | | 4 | egon1 | 123 | +----+-------+----------+ 4 rows in set (0.00 sec) mysql> select * from user; +----+-------+----------+ | id | name | password | +----+-------+----------+ | 1 | egon | 123 | | 2 | egon1 | 123 | | 3 | alex | 123 | | 4 | egon1 | 123 | +----+-------+----------+ 4 rows in set (0.00 sec) mysql> select * from user; +----+-------+----------+ | id | name | password | +----+-------+----------+ | 1 | egon | 123 | | 2 | egon1 | 123 | | 3 | alex | 123 | | 4 | egon1 | 123 | | 5 | alex | 123 | | 6 | ss | 121 | | 7 | laowu | 111 | +----+-------+----------+ 7 rows in set (0.00 sec) '''
四、查:fetchone,fetchmany,fetchall
[root@localhost pythonfile]# cat examine.py #!/usr/bin/python #單條查詢 import pymysql conn=pymysql.connect(host='localhost',user='root',password='',database='db8') cursor=conn.cursor() #游標 sql='select * from user;' rows=cursor.execute(sql) res1=cursor.fetchone() #查單條 print(res1) #多條查詢 [root@localhost pythonfile]# cat examine.py #!/usr/bin/python import pymysql conn=pymysql.connect(host='localhost',user='root',password='',database='db8') cursor=conn.cursor() #游標 sql='select * from user;' rows=cursor.execute(sql) res1=cursor.fetchone() print(res1) print(cursor.fetchmany(3)) #多條查詢 ''' 查詢結果: [root@localhost pythonfile]# python3 examine.py (1, 'egon', '123') ((2, 'egon1', '123'), (3, 'alex', '123'), (4, 'egon1', '123')) #以一個大元組的形式返回 ''' #查所有 [root@localhost pythonfile]# cat examine.py #!/usr/bin/python import pymysql conn=pymysql.connect(host='localhost',user='root',password='',database='db8') cursor=conn.cursor() #游標 sql='select * from user;' rows=cursor.execute(sql) print(cursor.fetchall()) #查表的所有 ''' 查詢結果: [root@localhost pythonfile]# python3 examine.py ((1, 'egon', '123'), (2, 'egon1', '123'), (3, 'alex', '123'), (4, 'egon1', '123'), (5, 'alex', '123'), (6, 'ss', '121'), (7, 'laowu', '111')) ''' #光標移動查詢 [root@localhost pythonfile]# cat examine.py #!/usr/bin/python import pymysql conn=pymysql.connect(host='localhost',user='root',password='',database='db8') cursor=conn.cursor() #游標 sql='select * from user;' rows=cursor.execute(sql) print(cursor.fetchall()) cursor.scroll(1,mode='absolute') #絕對路徑 print(cursor.fetchone()) ''' 結果: [root@localhost pythonfile]# python3 examine.py ((1, 'egon', '123'), (2, 'egon1', '123'), (3, 'alex', '123'), (4, 'egon1', '123'), (5, 'alex', '123'), (6, 'ss', '121'), (7, 'laowu', '111')) (2, 'egon1', '123') #光標跳到第一條后面,后面查詢直接是第二條了 ''' #相對路徑 [root@localhost pythonfile]# cat examine.py #!/usr/bin/python import pymysql conn=pymysql.connect(host='localhost',user='root',password='',database='db8') cursor=conn.cursor() #游標 sql='select * from user;' rows=cursor.execute(sql) print(cursor.fetchone()) cursor.scroll(1,mode='relative') #相對路徑,在原有的基礎上開始移動光標 print(cursor.fetchone()) ''' 輸出結果: [root@localhost pythonfile]# python3 examine.py (1, 'egon', '123') (3, 'alex', '123') '''