带你了解什么是MySQL数据库(五)数据库备份、PyMySQL模块、SQL注入问题

前言:

相信了解到这里,对MySQL数据库也有了一定的了解,那么我们再来学习一下较为重要的内容,数据备份,使用备份的目的也很简单, 防止数据遗忘或者丢失等等,通过备份文件就可以恢复备份时的数据内容,通常备份需要定期来执行。以及在Python内如果操作数据,让我们来了解一下这些内容吧。


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

恢复逻辑备份

恢复备份的两种两种方式

方式一:

# 针对单库备份的恢复,将备份文件里面的表,全部恢复到某个库下面
mysql -uroot -p密码(可省略,密文输入) 库名 < 备份文件.sql

# 针对多库备份的恢复,将备份文件里面的多个库及表的结构记录,全部创建出来
mysql -uroot -p密码(可省略,密文输入) < 备份文件.sql
# 不需要输入库名

方式二:

# 当备份文件内是单个库时,我们需要将它恢复到某个库下面,这里就创建一个库
create database lll;
use lll;
source /xxx/xxx/备份文件.sql

# 当备份文件内是多个库时,我们不需要将它恢复到某张表下面,可以直接执行
source /xxx/xxx/备份文件.sql

这里补充一个删除库或者表的特殊语句,就是当库存在时则正常删除,如果不存在时,则发出警告信息,不会报错

drop table if exists 表名;

在这里插入图片描述
sdf这个库是不存在的,但是这条SQL语句还是成功执行了,没有报错,但是抛出了警告。


PyMySQL模块的使用


PyMySQL是Python3.x版本的一个模块,其主要作用就是用于连接MySQL数据库,本文将介绍使用PyMySQL连接数据库,并实现增删改查等功能。

在使用之前我们要确保PyMySQL的安装,如果还未安装可以使用:

pip3 install PyMySQL

当然也可以在pycharm内安装
在这里插入图片描述


环境准备

在使用PyMySQL开始本次练习前,需要先建立实验表

create database pymysql_test; # 创建实验所需库

CREATE TABLE student (
  id int not null auto_increment primary key,
  name varchar(30),
  age int,
)

INSERT INTO `student` VALUES (1, 'jack', 18);
INSERT INTO `student` VALUES (2, 'tom', 19);
INSERT INTO `student` VALUES (3, 'jams', 23);
INSERT INTO `student` VALUES (4, 'rouse', 21);
INSERT INTO `student` VALUES (5, 'mark', 25);

实例

import pymysql

conn = pymysql.connect( # 连接MySQL数据库
	host='127.0.0.1',
	port=3306,
	database='student',
	user='登录MySQL的用户',
	password='用户密码'
)

# 创建游标对象,用于操作数据库
cursor = conn.cursor() # 以元组的方式显示我们接收到的内容
# cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 改变显示方式为字典

cursor.execute("select * from student;")

data = cursor.fetchall() # 获取查询到的所有数据

print(data)

执行结果

# 元组显示
((1, 'jack', 18), (2, 'tom', 19), (3, 'jams', 23), (4, 'rouse', 21), (5, 'mark', 25))

# 如果改变显示为字段方式,则会显示出每个数据对应的字段
[{'id': 1, 'name': 'jack', 'age': 18}, {'id': 2, 'name': 'tom', 'age': 19}, {'id': 3, 'name': 'jams', 'age': 23}, {'id': 4, 'name': 'rouse', 'age': 21}, {'id': 5, 'name': 'mark', 'age': 25}]

插入数据

以下实例通过SQL语句向student表插入数据

mport pymysql

conn = pymysql.connect(
	host='127.0.0.1',
	port=3306,
	database='pymysql_test',
	user='root',
	password='password'
)

# 创建游标对象,用于操作数据库
cursor = conn.cursor()

sql = '''
	insert into student values(null,'张三',26),(null,'李四',29);
'''

try:
	cursor.execute(sql) # 执行SQL语句
	conn.commit() # 如果要对数据库进行操作,需要操作完以后进行commit提交
except:
	conn.rollback() # 如果发生错误进行回滚,回到操作之前的状态

至于为啥要执行完操作要进行commit提交,后续我们会在事务里提到

我们再通过select语句查看是否插入数据成功

...省略连接
# 创建游标对象,用于操作数据库
cursor = conn.cursor()

cursor.execute('select * from student;')

data = cursor.fetchall()

print(data)

执行结果

((1, 'jack', 18), (2, 'tom', 19), (3, 'jams', 23), (4, 'rouse', 21), (5, 'mark', 25), (6, '张三', 26), (7, '李四', 29))

删除记录操作

通过SQL语句删除name为"张三"所在行的记录

# 创建游标对象,用于操作数据库
cursor = conn.cursor()

try: # 执行数据相关操作,最好放在try..except内执行,避免出现错误,导致数据出现问题
	cursor.execute('delete from student where name = "张三";')
	conn.commit()
except:
	conn.rollback()

cursor.execute('select * from student;')

data = cursor.fetchall()

print(data)

执行结果

((1, 'jack', 18), (2, 'tom', 19), (3, 'jams', 23), (4, 'rouse', 21), (5, 'mark', 25), (7, '李四', 29))

更新数据操作

我们将通过update语句更新,将name字段为"李四"的年龄改成一个外部输入的内容

age = input('输入新的年龄:')

# 创建游标对象,用于操作数据库
cursor = conn.cursor()
sql = 'update student set age = %s where name = "李四";' % (age)
try: # 执行数据相关操作,最好放在try..except内执行,避免出现错误,导致数据出现问题
	cursor.execute(sql)
	conn.commit()
except:
	conn.rollback()

cursor.execute('select * from student;')

data = cursor.fetchall()

print(data)

执行结果

输入新的年龄:35
((1, 'jack', 18), (2, 'tom', 19), (3, 'jams', 23), (4, 'rouse', 21), (5, 'mark', 25), (7, '李四', 35))

查询记录操作

PyMySQL提供给我们不同呈现记录的方式,元组、字典等。

此外它还提供给了我们3种不同形式的显示记录形式,因为PyMySQL查询是一种惰性机制,它会帮助我们节省内存空间,就是说内容不会立马返回给我们,而是存放在迭代器内,我们需要再进行返回,

  • cursor.fetchall():显示迭代器内放置的所有记录
  • cursor.fetchone():一次从迭代器内取出一条记录(相当于next)
  • cursor.fetchmany(size):指定从迭代器内取出的记录数量,如果指定数量超过迭代器已存在的所有记录数量,则取所有的记录。

实例演示:cursor.fetchone()

# 创建游标对象,用于操作数据库
cursor = conn.cursor()

cursor.execute('select * from student;')

print(cursor.fetchone()) # 取出第一条记录
print(cursor.fetchone()) # 取出第二条记录
print(cursor.fetchone()) # 取出第三条记录

执行结果

(1, 'jack', 18)
(2, 'tom', 19)
(3, 'jams', 23)

实例演示:cursor.fetchmany(size)

# 创建游标对象,用于操作数据库
cursor = conn.cursor()

cursor.execute('select * from student;')

print(cursor.fetchmany(3))

执行结果

((1, 'jack', 18), (2, 'tom', 19), (3, 'jams', 23))

注意:将记录从迭代器内取出来以后,该记录就不会在存在于迭代器内。

# 创建游标对象,用于操作数据库
cursor = conn.cursor()

cursor.execute('select * from student;')

print(cursor.fetchmany(3))
print(cursor.fetchone()) # 取的是第四条记录,因为已经从迭代器内取走三条记录

执行结果

((1, 'jack', 18), (2, 'tom', 19), (3, 'jams', 23))
(4, 'rouse', 21)

简单说明SQL注入问题

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

下面简单演示SQL注入的产生

创建一个新的实验表:

create table login(
	id int not null auto_increment primary key,
	username varchar(30) not null,
	password varchar(30) not null
);

insert login values(null,'admin','Admin0.0');
insert login values(null,'jack','101001');
insert login values(null,'tom','00000');
insert login values(null,'jams','111222..');

实验开始:

import pymysql

conn = pymysql.connect(
	host='127.0.0.1',
	port=3306,
	database='pymysql_test',
	user='root',
	password='password'
)

account = input('请输入账号:').strip()

password = input('请输入密码:').strip()

sql = 'select * from login where username = "%s" and password = "%s"' % (account,password)

cursor = conn.cursor()

cursor.execute(sql)

data = cursor.fetchall()

print(data)

接下来的关键点是:我们怎么添加额外的SQL语句,在提示我们输入account 或 password 时。在提示我们输入账号时,输入一下SQL语句

请输入账号:abc" or 1=1 -- a
请输入密码:直接回车

此时就会达到了SQL注入的效果,直接将整张表的内容给我们现实出来了

((1, 'admin', 'Admin0.0'), (2, 'jack', '101001'), (3, 'tom', '00000'), (4, 'jams', '111222..'))

在这里,如果我们要解决这个问题,有两种方案:

  1. 不让用户输入一些非法符号(通常网页就是这么操作的)
  2. 需要修改执行SQL语句的方式
account = input('请输入账号:').strip()

password = input('请输入密码:').strip()

sql = 'select * from login where username = "%s" and password = "%s"'

cursor = conn.cursor()

cursor.execute(sql,(account,password)) # 添加进入这里,PyMySQL会帮助我们判断处理

data = cursor.fetchall()
print(data)

执行结果

请输入账号:abc" or 1=1 -- a
请输入密码:
()

结果就是什么也没有显示出来,因为PyMySQL在这里帮助我们避开了这个问题,但是有些时候SQL注入的问题无法避免,其原因有一下:

  1. 广泛性
    任何一个基于SQL语言的数据库都可能被攻击,很多开发人员在编写Web应用程序时未对从输入参数、Web表单、cookie等接受到的值进行规范性验证和检测,通常会出现SQL注入漏洞。
  2. 隐蔽性
    SQL注入语句一般都嵌入在普通的HTTP请求中,很难与正常语句区分开,所以当前许多防火墙都无法识别予以警告,而且SQL注入变种极多,攻击者可以调整攻击的参数,所以使用传统的方法防御SQL注入效果非常不理想。
  3. 危害大
    攻击者通过SQL注入获取到服务器的库名、表名、字段名,从而获取到整个服务器中的数据,对网站用户的数据安全有极大的威胁。攻击者也可以通过获取到的数据,得到后台管理员的密码,然后对网页页面进行恶意篡改。这样不仅对数据库信息安全造成严重威胁,对整个数据库系统安全也影响重大。
  4. 操作方便
    互联网上有很多SQL注入工具,简单易学,攻击过程简单,不需要专业知识也能自如运用。

以上就是本文所表述的所有内容,希望本文能帮助到您对MySQL数据库理解。


技术小白记录学习过程,有错误或不解的地方请指出,如果这篇文章对你有所帮助请点赞 收藏+关注 子夜期待您的关注,谢谢支持!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值