常用工具
- window : mysql workbench、 navicat、sqlyog、heidisql、mysql front
- linux : mysql workbeanch 、navicat
- linux : mysql workbeanch 、navicat
架构演变
- 架构1.0 - 单机单库
- 数据量太大、超过一台服务器承受范围
- 读写操作量大,超出一台 服务器承受
- 一台服务器挂了,应用也会挂掉(可用性差
- 架构 2.0 - 主从架构
- 读写分离
- 保证服务的可用
- 数据量太大超过一台服务器
- 写操作太大超出一台服务器的性能
- 架构 3.0 - 分库分表
- 写操作太大超出一台服务器的性能
- 数据如何路由是一个关键问题,一般采用范围拆分,list拆分,hash拆分
- 如何保持数据一致性是一个难题
- 架构 4.0 - 云数据库
- 使用Saas服务,服务提供商负责解决可配置性,可扩展性,多用户存储 接哦古涉及 等难点问题
SQL基本使用
SQL约束
约束 | 约束表达式 | 备注 |
---|---|---|
主键 | primary key | |
非空 | not null | |
唯一 | unique | |
默认 | default | |
外键 | foreign key |
常用关键字
关键字 | 含义 | 备注 |
---|---|---|
distinct | 去除重复项 | |
like | 模糊查询(% 任意多个字符 , _ 一个任意字符) | |
in | 非连续范围内 | |
between … and … | 一个连续的范围内 | |
count(*) | 统计总行数 | |
max() | 求最大值 | |
min() | 求最小值 | |
sum(列) | 求和 | |
avg(列) | 求平均数 | |
group by | 将查询结果按照1个或者多个字段进行分组,字段值相同的一组 | |
group by + having | 分组后查询指定条件输出的查询结果 | |
having | 只能用于group by | |
order by | 排序 (asc升序 desc降序) |
SQL 增删改查
# 连接数据库
mysql -u"用户名" -p
$pwd
# 数据库退出
quit
# 查看数据库
show databases;
# 查看数据库版本
select version()
# 显示时间
select now();
# 创建数据
create database `python01` charset="utf-8";
# 展示数据库创建语句
show create database "database03"
# 查看当前使用数据库
select database();
# 使用数据库
use "数据库名称";
# 删除数据库
drop database "数据库名称";
# **数据库表的操作**
# 查看当前数据库中所有表
show tables;
# 创建表
# auto_increment表示自动增长
# not null 表示不能为空
# primary key 表示主键
# create table 数据库名称(字段 类型 约束 [字段 类型 约束]);
create table demo(id int,name varchar(20));
# 查看表结构
desc "表名";
# 创建 students 表(id、name、age、high、gender、cls_id)
create table students(
id int not null primary key auto_increment,
name varchar(30),
age tinyint unsigned default 0,
high decimal(5,2),
gender enum('男','女','中性','保密') default '保密',
cls_id int unsigned
);
# 表中插入数据
insert into student values(0,"老王",18,175.88,"男",1);
select * from student;
# 查看表的创建语句
show create table students
# 修改表 - 添加字段
# alter table 表名 add 列名 类型;
alter table students add birthday datetime;
# 修改表- 修改字段 : 不重名命名 - 修改字段类型 + 约束
# alter table 表名 modify 列名 类型及约束
alter table students modify birthday date dafault '1997-01-01'
# 修改表- 修改字段 : 重名命名 - 改变字段的名称
# alter table 表名 change 原名 新名 类型及约束;
alter table students change birthday birth date dafault '1997-01-01'
# 修改表 - 删除字段
# alter table 表名 drop 列名;
alter table students drop high;
# 删除表
drop table "表名";
drop database "数据库";
drop table "数据表";
**# 新增**
# 全列插入 insert [into] 表名 values(...)
# 主键字段 - 可以用 0 null default 来占位
# 向 classes 表中插入一个班级
insert into class values(0,"python") # 0 是 id位置 用 0 表示自增
# 枚举类型的插入 1-男 2-女
insert into students values(0,'tony',18,1,1,'1997/01/01');
# 部分插入
# insert into 表名(列1,...) values(值1,...)
insert into students(name,gender) values("小乔",2);
# 多行插入
insert into students(name,gender) values("小乔",2)("周瑜",1)("孙策",1);
**#修改**
# update 表名 set 列1=值1,列2=值2...where 条件;
update students set age=18; # 全表修改
update students set age=28 where name = "tony"; # 条件筛选修改
# 物理删除
# delete from 表名 where 条件
delete from students where name = 'tony';
# 逻辑删除 - 用一个字段表示此条数据已经不能在再用 例如 :is_delete字段
alter table students add is_delete int default 0 ;
updata students set is_delete = 1 where id = 6;
**# 基本查询**
# select 去重选项 字段列表[as 字段名] from 数据表 where [group by 子句] [having 子句] [order by 子句 ] [order by 子句] [limit子句];
# 查询全部
select * from students;
# 去除重复字段查询
select distinct name from students;
# 查询指定列
select id,name from students;
# 可以使用 as 为列或表指定别名
select id, cls_id as "班级" from students;
select student.name as "姓名" from students;
#数据库数据查询
# 从 第10行开始获取20行数据,
# 分页(从start开始,获取count条数据)
select * from students limit 10,20;
# join查询连接查询
select * from table1 inner join table2 on table1.firstid = table2.secondid;
select * from table1 left join table2 on table1.firstid = table2.secondid;
select * from table1 right join table2 on table1.firstid = table2.secondid;
# 子查询
select * from students where height = (select max(height) from students);
# 创建数据表
create table student(sid int(4) not null primary key,sname varchar(36),gid int(4) not null);
# 添加外键
alter table tablesname add constraint prinaryname foreign key(id) references table2(idname)
# 删除外键
alter table tablename1 drop foreign key prinaryname1;
**# 比较运算符**
> # 大于
< # 小于
>= #大于等于
<= #小于等于
!= / <> # 不等于
**# 逻辑运算符**
and # 和
or # 或者
not # 非/取反
**# 模糊查询**
# like
# % 替换1个或者多个
# _ 替换1个
# 查询姓名中 以 "李" 开始的名字
select * from students where name like '李%';
# 查询姓名中 带有 "李" 开始的名字
select * from students where name like '%李%';
# 查询有2个字的名字
select * from students where name like '__';
# 查询至少有2个字的名字
select * from students where name like '__%';
# where 子句(条件)范围查询
# in 表示在一个非连续的范围内
select * from students where id in(1,3,8);
select * from students where id not in(1,3,8);
# between...and... 表示在一个连续的范围内
select * from students where id between 3 and 8;
# id 3-8 男生
select * from students where id between 3 and 8 and gender=1;
select * from students where id not between 3 and 8 and gender=1;
# 判断为空 is null
# 非空 is not null
# 查询 cls_id 为空的数据
select * from students where cls_is is null;
**# 聚合函数**
# 总数 count()
# 查询学生总数
select cout(*) from students;
# 查询男性有多少人
select cout(*) as "男性人数" from students where gender = 1;
# 最大值/最小值 max / min
select max(age) from students;
# 查询男性 ID的最大值
select max(id) from students where gender=1;
# 查询女性的最高身高
select max(height) from students where gender = 2;
# 求和 sum()
# 查询男生的年龄和
select sum(age) from students where gender =1;
# 平均值 avg() 默认保留4位
# 查询未删除女生的ID的平均值
select avg(id) from students where gender=2 and is_delete=0;
# 四舍五入 round(123.23,1) 保留 1 位小数
# 计算所以人的平均年龄,保留2位小数
select round(ave(age),2) from students;
# 分组 group by
# 按照性别分组,查询所有的性别
select gender from students group by gender;
# 计算男生和女生的人数
select gender as "性别",count(*) from students where gender = 1;
select gender as "性别",count(*) from students where gender = 2;
select gender as "性别",count(*) from students group by gender;
# 男女同学最大年龄
select gender as "性别",max(age) from students group by gender;
# group_concat() 查看组内信息 ( 把所有内容写在同一个格子里)
# 查询同种性别中的姓名
select gender as "性别",max(age),group_concat(name) from students group by gender;
# 查询组内年龄,姓名(name + age) 写在同一框格中
select gender as "性别",group_concat(name,age) as "组内姓名" from students group by gender;
# having 分组之后的筛选
# 查询男生女生总数大于2s
select gender as "性别",count(*) from students group by gender having count(*) > 2;
# 查询男生 女生 总数大于 2 的姓名
select count(*),group_concat(name) from students group by gender having count(*) > 2;
# 查询平均年龄超过18岁的性别,以及姓名 having age(age) > 18
select gender,group_concat(name),avg(age) from studernt group by gender having avg(age) > 18;
# 数据库排序 order by / asc 从小到大排列,即升序,默认 / desc 降序
# 查询年龄在 18-26 岁之间的男同学 ,按照年龄从小到大排序
select * from students where age between 18 and 26 group by gender having gender =1 order by age;
select * from students where age between 18 and 26 and gender =1 order by age;
# 查询年龄在 18-34 岁之间的女同学,身高从高到矮排序
select * from students where age bewteen 18 and 34 and gender =2 order by height desc;
# order by 多个字段
# 查询年龄在18-28之间,女性,身高从高到矮,如果身高相同 按年龄从小到大排列
select * from students where age bewteen 18 and 28 and gender = 2 order by height descc,age asc;
# 按年龄从小到大,身高从高到矮
select * from students order by age asc,height desc;
# 分页 limint start count
# 限制查询出来的结果
select * from students limit 2; # 查询前两条数据
select * from students limit(3,5); # 从3位置开始 查询5条数据
# 数据库的连接查询
inner join ...on # 内连接
select * from students inner join classes on students.cls_id = class.id;
# 按照要求显示姓名、班级
select students.name,classed.name from students inner join classes on students.cls_id = class.od;
left join ...on # 左连接
light join ...on # 右连接
**# 子查询**
# 查询最高的男生的信息
select * from students where height = (select max(height) from students where gender =1 );
# 查询高于平均身高的信息
select * from students where height > (selecct avg(height) from students);
# 自关联 - 省市区三级联动
select * from provinces as p inner join cities as c on p.'provinceid' = c.'provineid' having p.province ="吉林省"
视图 增删改查
# 视图创建
create view v_stu_score as (select * from table1);
# 视图查看(查看表时会显示所有视图)
show tables;
# 使用视图((v_stu_score 视图名))
select * from v_stu_score;
# 删除视图
drop view v_stu_sco;
SQL 索引
- 定义 : 索引是一种特殊的文件(InnoDB 数据表上的索引是表空间的一个组成部分),包含着对数据表里所有记录的引用指针
- 效率 :300 万左右数据量,可以提高一倍的查询效率
- 索引建立 :
- 主键自动建立索引
- 频繁作为查询条件的字段因该建立索引
- 查询中与 其他表关联的字段,外键关系建立索引
- 在高并发的情况下创建复合索引
- 查询中排序的字段、排序字段若通过索引去访问大大提升排序速度(建立索引的顺序跟排序的顺序保持一致)
# 查看索引
show index from "表名";
# 创建索引
create [unique] index "索引名称" on "表名(字段名称(长度))"
create index idx_name on students(name(30)); # 单值索引
# 删除索引
drop index "索引名称" on "表名";
SQL 事务
事务:就是一系列的操作,一旦出现问题则进行回滚
#事务开启
begin "或" start transaction
# 事务提交
commit;
# 回滚事务
rollback;
SQL 权限控制
# 查看user表结构
desc user;
# 查看所有用户
select host,user,authentication_string from user;
# 创建账号& 授权
grant 权限列表 on 数据库 to '用户名'@'访问主机' identified by '密码';
# 退出root登陆
quit
存储引擎
-
存储引擎 Innodb : 最大程度的支持并发
使用表空间进行数据存储 (on/off)
系统表空间会产生I/O瓶颈,刷新数据的时候是顺序进行的,所以会产生 I/O 瓶颈,独立空间可以同时向多个文件刷新数据
支持外键、支持事务、行级锁最大程度支持并发,缓存索引、缓存真实数据、表空间大
# 查看存储引擎 show engines; show variables like 'innodb_file_per_table' # 查看是否独立表空间 set global innodb_file_per_table = off # 关闭独立表空间
-
存储引擎 MyISAM : 适合非事务应用,只读类应用
支持表数据压缩(linux),压缩后只能读,不能写
不支持外键,不支持事务
表级锁,不适合高并发
只缓存索引,不缓存真实数据
表空间较小
myisampack -b -f myIsam.MYI # 表损坏修复 reapir table "表名";
-
存储引擎 CSV : 文本存储表的内容
.CSM 文件存储表的元数据,如表的状态、数据量等
.frm 文件存储表结构信息
适合做数据交换的中间表
不支持主键,不支持自增长,所有列不能为空
-
存储引擎 Memory : 内存型
支持 hash(用于等值查找)、btree索引(范围查找)
所有字段长度固定
不支持 BLOB 和 text 等大字段
使用表级锁
重启后数据会小时
服务架构说明
- 网络链路层
- 能够与mysql服务器建立链接的客户端(java、C、python、.net)
- 服务层(msyql server)
- 包含系统管理和控制工具、链接池、SQL接口、解析器、查询优化器、缓存
- 链接池 : 负责存储和管理客户端的数据路链接,一个线程负责管理链接
- 系统管理和控制工具 :备份恢复、安全管理、集群管理
- SQL接口 :接口客户端发送过来的sql命令,并返回查询结果。
- 解析器 :负责将请求的 SQL 解析生成一个 解析树,然后根据mysql规则进行检查树是否合法。
- 查询优化器 :当解析树 通过解析器语法检查后,交给优化器及逆行转化成执行计划,然后与存储引擎交互
- 缓存 : 小缓存组成(表缓存、记录缓存、权限缓存、引擎缓存)、如果查询缓存名中,则执行查询缓存
- 引擎层
- 存储引擎层 :负责数据的存储和提取
- 系统文件层
- 负责数据库的数据和日志存储在文件系统中,并完成与存储引擎的交互
- 日志文件、数据文件、配置文件、pid文件、socket文件
- 日志文件
- error log 日志 : 错误日志 ( show variables like %log_err%)
- 慢查询日志 :记录一般查询语句 ( show variables like %general% )
- 二进制日志 (binary log):记录对数据库的执行更改记录语句发生时间,执行时长,用于数据库恢复 和主从复制。( show binary logs )
- 慢查询日志 (Slow query log)
- 配置文件
- 用于存放 mysql所有配置信息文件、比如my.cnf、my.ini等
- 数据文件
- db.opt 文件 : 记录这个库默认使用的字符集和校验规则
- frm 文件 :存储 与相关的元数据信息,包括表结构的定义信息,每一张表都会有 一个frm文件
- MYD文件 :MySAM存储引擎专用,存放MySAM表的 数据,每一张表都会有一个 .myd文件
- MYI文件 :MySAM存储引擎专用,存放MySAM表 的索引相关的信息,每一张表都会有一个 .myi文件
- ibd 文件和IBDATA文件 : 存放InnoDB的数据文件(包括引擎)。InnoDB存储引擎有两种表空间方式 :独立表空间,共享表空间 独享表空间使用.ibd文件夹存放数据,且每一张InnoDB表对应一个.ibd表对应一个 .ibd文件。共享表空间 使用.ibdata文件,所有表共享使用一个(或 多个、自行设置).ibdata文件
- ibdata1 文件 :系统表空间数据文件,存储表 元数据,Undo日志等
- ib_logfile0、ib_logfile1文件、Redo log日志文件
- pid文件 :进程文件,存放自己的进程id
- socket文件 :客户端可用不 通过TCP/IP 网络而 直接使用socket链接数据库
日志说明
undo log
数据库事务开始前,将要需修改的记录存放在Undo日志里,当事务回滚时,数据崩溃时,可以利用Undo日志,撤销未提交事务 对数据库产生影响
Undo Log 产生和销毁 : Undo Log在事务开始前产生,事务在提交时,并不会立刻删除undo log , innodb会将该事务对那个的undo log放入到 删除列表中,后面会通过后台线程 purge thread进行回收处理。Undo Log 属于逻辑日志,记录一个变化 过程,发生一个动作会记录一个相反的 updata
Undo Log 存储 :采用段的方式进行管理和记录
Redo Log
以恢复操作为目的,在数据库发生意外时重新操作
在事务中修改任何数据,将最新的数据 备份存储的位置
随着事务操作执行,就 会生成,在事务提交时 会产生写入Log Buffer,而 不是将事务 提交立刻写入磁盘文件
随着事务的提交就立刻写入磁盘文件
Redo log工作原理
- 实现事物的持久性而出现的产物。防止发生故障时,尚有脏页没有写入到 IBD文件中,重启mysql服务时,根据Redo log 进行重做,从而达到事物未吸入磁盘数据的持久化特性
- 写入机制 :以顺序循环的方式写入文件,写满是则回溯到第一个文件,进行覆盖写
- redo log 相关配置参数 :show variables like ‘%innodb_log%’;
Bin log 日志
redo log 属于 innodb引擎所特有的日志,而 mysql server也有自己的日志,叫做binary log(二进制文件) 简称 bin log
记录数据表结构变更及表数据修改的二进制日志
以事件形式记录,包含语句所执行的消耗时间
应用场景 : 主从同步(开启 bin log,传递给从库)、数据恢复
文件记录模式 row模式(对每一行进行记录,批量操作是日志量巨大)
statment 模式(每条记录的sql都会就在master的 binlog中,在sql中含有变量时,比如last inset id 等时,不可靠)
mixed 模式(正常用sql,识别用 row模式)
# binlog 状态查询(开启状态)
show variables like 'log_bin';
# 开启bin log 文件 需要修改 my.cnf 或my.ini配置文件,在增加 log_bin = mysql_bin_log,重启mysql服务
# log-bin = ON
# log-bin-basename=mysqlbinlog
binlog-format=ROW
log-bin = mysqlbinlog
# 使用show binlog events命令
show binary logs; // 展示 bin log 文件
show master status; // 现在使用的 bin log文件
show binlog events; // 包含哪些事件
show binlog events in ‘mysqlbinlog.000001’;
# 系统cmd下查看 binlog文件
mysqlbinlog “文件名”
mysqlbinlog “文件名” > 'test.sql'
# 使用 binlog恢复数据
# 按指定时间恢复
mysqlbinlog -- start -datetime = -- stop-datetime=“2020-11-10 18:00:00” mysqlbinlog.00002 | mysql -uroot -p1234
# 按事件位置号恢复
mysqlbinlog -- start -position=154 stop-position=957 mysqlbinlog.00002 | mysql -uroot -p1234
# 删除binlog文件
purge binary logs to 'mysqlbinlog.00001'; // 删除指定文件
purge binary logs before '2020-11-10 18:00:00'; //删除指定时间之前的文件
reset master; // 清除所有文件
MYSQL主从配置
master 将改变记录到二进制日志。这些记录过程叫做二进制日志事件,binary log events.
slave 将 master 的binary log events 拷贝到它的中继日志
slave 重做中继器日志中的事件,将改变应用到自己的数据库中,mysql复制是异步的且串行
# 主机配置文件 - my.ini
# 开启二进制日志
# log-bin = 自己本地的路径/mydqlbin
log-bin = mysql-bin
# 指定主服务器ID
server-id =1
# 需要从新启动服务
# 从机配置文件 - mysqld.cnf
server-id = 2 # 不要和主服务器ID重复
log-bin = /自己本地的路径/mysql-bin.log
service mysql restart # 重启服务
# MySQL8.0主从配置 对从机进行授权
# 192.168.0.183 为从机IP
# 用户名 repl 密码 : 123
CREATE USER 'repl'@'192.168.0.183' IDENTIFIED WITH mysql_native_password BY '123';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.0.183';
show master status;
# 展示 :( file:mysql-bin.000004 Position : 680 )
# 对从机进行配置
# 主机IP地址
change master to master_host = '192.168.0.161',
# 主机用户名
master_user = 'juran',
# 密码
master_password = '123',
master_log_file = 'binlog.000004',
master_log_pos= 908;
数据库的分区
定义 :根据某个区间值,特定值 或 hash函数执行数据的聚合,让那个数据根据规则分布在不同的分区中
类型 :Range分区、List分区、Hash分区
注意事项 :避免跨分区查询、最好在where从句中包含分区值,具有唯一索引的表,主键或唯一索引必须是分区键的一部分
partition # 分区
# 查看数据库支持项
show plugins;
# 数据库分区特点
# 逻辑上为一个表,在物理上存储在多个文件中
create table `login_log`(
login_id int(10) unsigned not null comment '登录用户id',
login_time timestamp not null default current_timestamp,
login_ip int(10) unsigned not null comment '登录ip'
)engine=innodb default charset=utf8
partition by hash(login_id) partitions 4; # 将这个表划分4个分区
# 删除分区(表中的数据也会删除)
alter table login_log_list drop partition p0;
# 分区的数据迁移(p1分区数据迁移到table arch_login_log_list )
alter table login_log_list exchange partition p1 with table arch_login_log_list;
Range分区
根据键值的范围,将数据存储到表的不同分区中
分区需要连续,但是不能重叠,分区不包含上限值,包含下限值
常用分区 日期,时间,可以定期按分区记性清理历史数据
# 建立Range分区
create table `login_log_range`(
login_id int(10) unsigned not null comment '登录用户ID',
login_time timestamp not null default CURRENT_TIMESTAMP,
login_ip int(10) unsigned not null comment '登录ip'
)engine=innodb
partition by range(login_id)(
partition p0 values less than(10000), # 实际范围0-9999
partition p1 values less than(20000), # 实际范围10000-19999
partition p2 values less than(30000),
partition p3 values less than maxvalue # 存储大于30000的数据
);
Hash 分区
根据 mod (分区键、分区值)把数据行存储到表的而不同分区内
数据可以平均分布在各个分区
Hash分区的键值必须是 INT 类型的值,或者通过函数可以转化为 INT类型
# 建立Hash分区表
create table `login_log`(
login_id int(10) unsigned not null comment '登录用户ID',
login_time timestamp not null default CURRENT_TIMESTAMP,
login_ip int(10) unsigned not null comment '登录ip'
)engine=innodb default charset=utf8
partition by hash(login_id) partitions 4;
# 时间类型用函数转化为整数
create table `login_log`(
login_id int(10) unsigned not null comment '登录用户ID',
login_time timestamp not null default CURRENT_TIMESTAMP,
login_ip int(10) unsigned not null comment '登录ip'
)engine=innodb default charset=utf8
partition by hash(UNIX_TIMESTAMP(login_time))partitions 4;
List 分区
按分区键值取值的列表进行分区
同范围分区一样,各分区的列表值不能重复
每一行数据必须能找到对应的分区列表,否则数据插入失败
create table `login_log_list`(
login_id int(10) unsigned not null comment '登录用户ID',
login_time timestamp not null default CURRENT_TIMESTAMP,
login_ip int(10) unsigned not null comment '登录ip',
login_type int(10) not null
)engine=innodb
partition by list(login_type)(
partition p0 values in(1,3,5,7,9),
partition p1 values in(2,4,6,8)
);
交互框架
Pymysql
import pymysql
# pymysql.connect() 此对象为pymysql连接数据库的类
# 创建Connection连接对象实例
conn = pymysql.connect(host='localhost', port=3306, user='root', password='mysql', database='python1', charset='utf8')
# 创建游标
cursor = conn.cursor()
# 数据查询
sql = "select id,name from students where id = 7"
# 数据更新
sql = 'update students set name="刘邦" where id=6'
# 数据删除
sql = 'delete from students where id=6'
# 载入查询语句, 返回的是执行成功的条数,可以用于判断是否执行成功
cursor.execute(sql)
# 接收查询结果、就要一条
result = cursor.fetchone()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
# 数据更新/或数据新增时
conn.commit() # 提交
# 事务的回滚
conn.rollback()
# 查看所有数据
cursor.fetchall()
cursor.fetchone()
cursor.fetchmany(2)
SQLAlchemy
框架定义 : 一个数据库 ORM框架
原生开发模式
from sqlalchemy import create_engine # 引擎
# 连接数据库
HOSTNAME = '127.0.0.1' # IP
PORT = '3306' # 端口
DATABASE = 'demo0417' # 数据库名称
USERNAME = 'root' # 用户名
PASSWORD = 'root' # 密码
# 驱动 方式 1 — 用 pymysql 连接
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)
# 驱动 方式 2 — 用 mysqlconnector 连接
pip install mysqlconnector
DB_URI = 'mysql+mysqlconnector://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)
# 创建数据库引擎
engine = create_engine(DB_URI)
# 创建连接
with engine.connect() as conn:
# 执行SQL语句,原生的SQL写法
result = conn.execute("select * from users")
print(result.fetchone()) # 一条数据,返回一个元组
print(result.fetchall()) # 多条数据
SQLAlchemy 常用数据类型
Integer # 整形。
Float # 浮点类型。
Boolean # 传递True/False进去。
DECIMAL # 定点类型。
enum # 枚举类型。
Date # 传递datetime.date()进去。
DateTime # 传递datetime.datetime()进去。
Time # 传递datetime.time()进去。
String # 字符类型,使⽤时需要指定⻓度,区别于Text类型。
Text # ⽂本类型。
LONGTEXT # ⻓⽂本类型。
Column常⽤参数
default # 默认值。
nullable # 是否可空。
primary_key # 是否为主键。
unique # 是否唯⼀。
autoincrement # 是否⾃动增⻓。
sqlalchemy # 常⽤数据类型
Column # 常⽤参数
onupdate # 更新的时候执⾏的函数。
name # 该属性在数据库中的字段映射
ORM 框架使用
通过类的方式进行操作数据库,底层转化为 select 原生语句
"""
class Users(object):
name = "lcl"
pass
user = Users(1,"lcl")
user.add()
类 :class 一张表
属性 :name 表字段
对象 : 一条记录
"""
from sqlalchemy import create_engine
# 导入ORM的类
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String
HOSTNAME = '127.0.0.1' # IP
PORT = '3306' # 端口
DATABASE = 'demo0417' # 数据库名称
USERNAME = 'root' # 用户名
PASSWORD = 'root' # 密码
DB_URI = 'mysql+mysqlconnector://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)
engine = create_engine(DB_URI)
# 实例化ORM的类 所有模型 继承自 declarative_base
Base = declarative_base(engine)
# 使用 ORM 操作数据库, 继承 Base = declarative_base(engine) 的基类
class Students(Base):
# 定义表的名字
__tablename = "students"
# 创建一些字段 通过 Column 进行创建
id = Column(Interger, primary_key = True,autoincrement = True) # 数据类型、主键、自增
name = Column(String(50),nullable = False ) # 字符串类型、不能为空
gender = Column(Interger,default = 1 ,comment = "1 为 男,2为女")
# 模型映射到数据库中
Base.metadata.create_all()
ORM 增删改查
from sqlalchemy import create_engine
from sqlalchemy.declarative import declarative_base
from sqlalchemy import Column,Integer,String
from sqlalchemy.orm import sessionmaker
HOSTNAME = '127.0.0.1' # IP
PORT = '3306' # 端口
DATABASE = 'demo0417' # 数据库名称
USERNAME = 'root' # 用户名
PASSWORD = 'root' # 密码
DB_URI = 'mysql+mysqlconnector://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)
engine = create_engine(DB_URI)
Base = declarative_base(engine)
class Article(Base):
# 定义表的名字
__tablename = "article"
# 创建一些字段 通过 Column 进行创建
id = Column(Interger, primary_key = True,autoincrement = True) # 数据类型、主键、自增
name = Column(String(50),nullable = False ) # 字符串类型、不能为空
# 模型映射到数据库中
Base.metadata.create_all()
# 数据在内存中
article = Article(name = 'lcl')
# 将数据保存到数据库中
# 实例化 sessionmaker 类
# 类的实例化 __call__ 将类变成方法 去 调用
Session = sessionmaker( bind = engine )
session = Session()
# 数据添加 - 数据尚未提交
session.add(article)
# 数据提交
session.commit()
print(article.name)
print(article.id)
# 一次添加多条数据
session.add_all([article,article1])
session.commit()
ORM 增删改查-方法封装
from sqlalchemy import create_engine
from sqlalchemy.declarative import declarative_base
from sqlalchemy import Column,Integer,String
from sqlalchemy.orm import sessionmaker
HOSTNAME = '127.0.0.1' # IP
PORT = '3306' # 端口
DATABASE = 'demo0417' # 数据库名称
USERNAME = 'root' # 用户名
PASSWORD = 'root' # 密码
DB_URI = 'mysql+mysqlconnector://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)
engine = create_engine(DB_URI)
Base = declarative_base(engine)
class Article(Base):
__tablename__ = 'art'
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(50), nullable=False)
content = Column(String(50))
author = Column(String(50))
def __str__(self):
return "Article(title:{},content:{},author:{})".format(self.title, self.content, self.author)
# 模型映射到数据库中
Base.metadata.create_all()
# 写入数据
def add_data():
article = Article(title='Python', content='人生苦短,我用Python', author='龟叔')
session.add(article)
session.commit()
# 数据的查询
def search_data():
data = session.query(Article).all() # all 查询所有
for item in data:
print(item)
print(item.title)
print(item.content)
# print(data)
# 条件 filter 方法 1 返回的是列表
data = session.query(Article).filter(Article.title=='Python').all()
for item in data:
print(item)
# filter_by 方法 返回的是列表
data = session.query(Article).filter_by(title='JAVA').all()
for item in data:
print(item)
print(data)
# 查询第一条
data = session.query(Article).first()
print(data)
# get 方法 传的ID 不存在 返回None
data = session.query(Article).get(1) # 查询 ID 为 1
data = session.query(Article).get(2) # 查询 ID 为 2
print(data)
# ORM 修改
def update_data():
# 查询出要修改的这条记录
article = session.query(Article).first()
article.title = 'lgcoder'
print(article.title)
# session.rollback() 回滚
# print(article.title)
session.commit()
# ORM 删除
def delete_data():
# 查询出要修改的这条记录
article = session.query(Article).first()
# 误操作
# is_delete 1 未删除 0 删除
# 修改操作 is_delete 1=>0
session.delete(article)
session.commit()
query 可用参数
"""
1. 模型对象。指定查找这个模型中所有的对象。
2. 模型中的属性。可以指定只查找某个模型的其中⼏个属性。
3. 聚合函数。
func.count:统计⾏的数量。
func.avg:求平均值。
func.max:求最⼤值。
func.min:求最⼩值。
func.sum:求和
"""
from sqlalchemy import function
# 总条数
result = session.query(func.count(Article.id)).first()
# 求平均值
result = session.query(func.avg(Article.price)).first()
过滤条件
# 这些过滤条件都是只能通过filter⽅法实现的
# 等于 equals
query.filter(User.name == 'ed').all()
# 不等于 not equals
query.filter(User.name != 'ed')
# 模糊查询 like
query.filter(User.name.like('%ed%'))
# 在...中 in
query.filter(User.name.in_(['ed','wendy','jack']))
# 同时,in也可以作⽤于⼀个Query
query.filter(User.name.in_(session.query(User.name).filter(User.name.like ('%ed%'))))
# 不在...中 not in
query.filter(~User.name.in_(['ed','wendy','jack']))
# is null 为空
query.filter(User.name==None)
query.filter(User.name.is_(None))
# 不为空 is not null
query.filter(User.name != None)
query.filter(User.name.isnot(None))
# 条件并列 and
from sqlalchemy import and_
query.filter(and_(User.name=='ed',User.fullname=='Ed Jones'))
# 或者是传递多个参数
query.filter(User.name=='ed',User.fullname=='Ed Jones')
# 或者是通过多次filter操作
query.filter(User.name=='ed').filter(User.fullname=='Ed Jones')
from sqlalchemy import or_ query.filter(or_(User.name=='ed',User.name=='wendy'))
外键&外键约束
# 通过 ForeignKey类来实现,并且可以指定表的外键约束
class Article(Base):
__tablename__ = 'article'
id = Column(Integer,primary_key=True,autoincrement=True)
title = Column(String(50),nullable=False)
content = Column(Text,nullable=False)
# 外键 user.id user 表 中的 id 字段
uid = Column(Integer,ForeignKey('user.id'))
def __repr__(self):
return "<Article(title:%s)>" % self.title
class User(Base):
__tablename__ = 'user'
id = Column(Integer,primary_key=True,autoincrement=True)
username = Column(String(50),nullable=False)
# 外键查询(原理)
article = session.query(Article).first()
uid = article.uid
user = session.query(User).get(uid)
print(user)
# 外键查询
user = session.query(User).filter(User.id == Article.uid).first()
# 外键约束
RESTRICT:⽗表数据被删除,会阻⽌删除。默认就是这⼀项。
NO ACTION:在MySQL中,同RESTRICT。
CASCADE:级联删除。
SET NULL:⽗表数据被删除,⼦表数据会设置为NULL
# 通过 ForeignKey类来实现,并且可以指定表的外键约束
class Article(Base):
__tablename__ = 'article'
id = Column(Integer,primary_key=True,autoincrement=True)
title = Column(String(50),nullable=False)
content = Column(Text,nullable=False)
# 指定外键关系、执行外键约束删除关系
uid = Column(Integer,ForeignKey('user.id',ondelete='CASCADE'))
数据表对应关系
# 1对 n 的关系
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
class Article(Base):
__tablename__ = 'article'
id = Column(Integer,primary_key=True)
email_address = Column(String,nullable=False)
user_id = Column(Integer,ForeignKey('users.id'))
# 一对多的关系,backref 反向访问属性
author = relationship('Author',backref="article")
def __repr__(self):
return "<Address(email_address='%s')>" % self.email_address
class Author(Base):
__tablename__ = 'author'
id = Column(Integer,primary_key=True)
name = Column(String(50))
fullname = Column(String(50))
password = Column(String(100))
# 一对多的关系 relationship, backref(反向查询)
article = relationship("Article",backref="author")
# 查询 (文章,作者)
article = session.query(article).first()
print(article.author)
# 添加单条数据
user = Article(username = "lcl")
article = Article(title = "python",context ="xxxxx")
article.author = user
session.add(article)
session.commit()
# 添加多条文章记录
user = User(username = "lcl")
article1 = Article(title="python1",context="xxxx1")
article2 = Article(title="python2",context="xxxx2")
article1.author = user
article2.author = user
session.add(article1)
session.add(article2)
session.commit()
# 1对1 的关系
class User(Base):
__tablename__ = "user"
id = Column(Integet,primary_key = True, autoincrement= True)
username = Column(String(50),nullable = False)
**# uselist= False 指定关系为 1 vs 1**
extend = relationship("UserExtend",uselist= False)
class UserExtend(Base):
__tablename__ = "user_extend"
id = Column(Integet,primary_key = True, autoincrement= True)
school = Column(String(50))
# 外键
uid = Column(Integer,Foreignkey("user.id"))
user = relationship("User",backref = "extend")
# n 对 n 的关系
# 多对多,班级对老师,老师对班级
# 班级表 —— 中间表(班级表ID + 老师表 ID) —— 老师表
from sqlalchemy import Table
# 中间表定义
techer_class = Table(
"techer_classes", # 中间表名
Base.metadata,
Column("techer_id",Interger,ForeignKey("techer.id")) # 中间表字段
Column("classes_id",Interger,ForeignKey("classes.id")) # 中间表字段
)
class Teacher(Base):
__tablename__ = "teacher"
id = Column(Integet,primary_key = True, autoincrement= True)
name = Column(String(50))
# 外键关系、指定中间表
classes = relationship("Classes",backref = "teachers",secondary= teacher_classes)
class Classes(Base):
__tablename__ = "classes"
id = Column(Integet,primary_key = True, autoincrement= True)
name = Column(String(50))
# 多对多数据的添加
teacher1 = Teacher(name= "lcl")
teacher2 = Teacher(name ="wzh")
classes1 = Classes(name = "初级班")
classes2 = Classes(name = "进阶班")
teacher1.classes.append(classes1)
teacher1.classes.append(classes2)
teacher2.classes.append(classes1)
teacher2.classes.append(classes2)
session.add(teacher1)
session.add(teacher2)
session.commit()
# 查询老师对应的班级
teacher = session.query(Teacher).first()
print(teacher)
for i in teacher.classes:
print(i)
# 班级对应的老师
classes = session.query(Classes).first()
for i in classes.techers:
print(i)
数据库高级查询
# 排序
articles = session.query(Article).order_by(Article.id).all() # 升序
articles = session.query(Article).order_by(Article.id.desc()).all() # 降序
articles = session.query(Article).order_by(-Article.id).all() # 降序
for article in articles:
print(articles)
# 默认排序方法 - __mapper_args__ 魔术方法
class Article(Base):
__tablename__ = 'article'
id = Column(Integer,primary_key=True,autoincrement=True)
title = Column(String(50),nullable=False)
__mapper_args__ = {
"order_by" : id
}
# 定义魔术方法后,查询你中无需 order_by
articles = session.query(Article).all()
for article in articles:
print(articles)
"""
limit : 可以限制每条查询的时候,只查询几条数据
offset : 可以限制查询数据的时候过滤掉前面多少条
切片 : 可以对Query 对象使用切片操作,来获取想要的数据
"""
# limit 限制 —— 前三条数据
articles = session.query(Article).limit(3).all()
for article in articles:
print(articles)
# offset偏移量 查询 3-5条数据
articles = session.query(Article).offset(3).limit(3).all()
for article in articles:
print(articles)
# 切片 取 2-4 条
articles = session.query(Article).all()[2,5]
for article in articles:
print(articles)
# 分组、having、join方法
# group_by 分组、一般和聚合 函数连用
results = session.query(User.gender).group_by(User.gender).all()
results = session.query(User.gender,func.count(User.id)).group_by(User.gender).all()
for result in results
print(result)
# having ,分组后过滤
results = session.query(User.age,func.count(User.id)).group_by(User.age).having(User.age<18).all()
print(results)
# 子查询
# 查询和 李 相同的城市 和年龄的人
user = session.query(User).filter(User.username =="李").first()
print(user.city)
print(user.age)
result = session.query(User).filter(User.city == user.city,User.age == user.age).all()
for data in result:
print(data)
sub = session.query(User.city.label("city"),User.age.label("age")).filter(User.username =="李").subquery()
result = session.query(User).filter(User.city == sub.c.city,User.age == sub.c.age).all()
Flask - SQLAlchemy插件
# 插件安装
pip install flask-sqlalchemy
from flask import Flask
from flask sqlachemy import SQLAlchemy
# localhost
HOSTNAME = '127.0.0.1' # IP
PORT = '3306' # 端口
DATABASE = 'demo0417' # 数据库名称
USERNAME = 'root' # 用户名
PASSWORD = 'root' # 密码
DB_URI = 'mysql+mysqlconnector://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)
app = Flask(__name__)
# 创建引擎,加载配置文件 SQLALCHEMY_DATABASE_URL
# engine = create_engine(DB_URL)
app.config['SQLALCHEMY_DATABASE_URL'] = DB_URL
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 操作数据库,通过db 操作数据库
db = SQLAlchemy(app)
# 创建模型(继承自 db.Model)
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer,primary_key = True,autoincrement= True)
name = db.Column(db.String(50))
class Article(db.Model):
__tablename__ = 'article'
id = db.Column(db.Integer,primary_key = True,autoincrement= True)
title = db.Column(db.String(50))
# 定义外键
uid = db.Colunm(db.Integer,db.Foreignkey('users.id'))
# 表关联
author = db.relationship('User',back='articles')
# 将Model 映射到数据库中
db.create_all()
# 数据添加
user = User(name = 'lcl')
article = Artcile(title = 'python')
article.author = user
db.session.add(article)
db.session.commit()
# 查询数据
user = User.query.all()
print(user)
# 排序
users = User.query.order_by(User.id.desc()).all()
print(users)
@app.route("/")
def index():
return "首页"
if __name__ == '__main__':
app.run(debug = True)
性能优化
基准测试定义 :测量和评估软件性能指标的活动,用于建立某时刻的性能基准,便于当系统发生软硬件变化时,评估变更带来的影响
对系统设置压力测试,用于评估服务器的处理能力
建立mysql服务性能基线
基准测试工具
- 工具 : mysqlslap
# 参数命名
mysqlslap --auto-generate-sql # 由系统自动生成SQL脚本进行测试
mysqlslap --auto-generate-sql-add-autoincrement # 在生成的表中增加自增ID
mysqlslap --auto-generate-sql-load-type # 指定测试中使用的查询类型
mysqlslap --auto-generate-sql-write-number # 指定初始化数据时生成的数据量
mysqlslap --concurrency # 指定并发线程的数量
mysqlslap --engine # 指定要测试表的存储引擎,可以用逗号分割多个存储引擎
mysqlslap --no-drop # 指定不清理测试数据
mysqlslap --iterations # 指定测试运行的次数
mysqlslap --number-of-queries # 指定每一个线程执行的查询数量
mysqlslap --debug-info # 指定输出额外的内存及CPU统计信息
mysqlslap --number-int-cols # 指定测试表中包含的INT类型列的数量
mysqlslap --number-char-cols # 指定测试表中包含的varchar类型的数量
mysqlslap --create-schema # 指定了用于执行测试的数据库的名字
mysqlslap --query # 用于指定自定义SQL的脚本
mysqlslap --only-print # 并不运行测试脚本,而是把生成的脚本打印出来
# 测试案例
mysqlslap --concurrency=1,50,100,200 --iterations=3 --number-int-cols=5 --number-char-
cols=5 --auto-generate-sql --auto-generate-sql-add-autoincrement --engine=myisam,innodb
--number-of-queries=10 --create-schema=test
explain 解析语句
定义 :模拟优化器执行 sql 查询语句,分析查询语句的表结构性能瓶颈
解析内容 :
- 表的读取顺序
- 数据读取操作的操作类型
- 哪些索引可以被使用
- 哪些索引实际被使用
- 表之间的引用
- 每张表有多好啊行被优化器查询
explain select * from t1,t2,t3 where t1.id=t2.id and t1.id = t3.id and t1.other_column='';
explian语句解析
- id— 表的读取加载顺序 (id相同、执行顺序由上而下,id不同、id值越大优先级越高、越先被执行)
- select_type — 数据读取操作的操作类型(simple 简单的查询、primary 查询中若包含任何负责的子部分、最外层查询则被标记,subquery 在select 或where列表中包含了子查询,union 若第二个select出现在union之后,则被标记为union,union result 从union表获取结果的select)
Sqlmap探测工具
功能定义 : 一种安全探测测试工具,用于发现SQL注入的安全漏洞,长用来进行安全扫描
基本操作
# 程序开启(在文件程序对应目录下)
python sqlmap.py
# 查看当前数据库版本信息
"""
0:只显示python 的tracebacks 信息、错误信息、关键信息
1:显示普通信息,和警告信息
2:显示调试信息 [debug]
3:显示注入使用的攻击载荷[payload]
4:显示HTTP请求头
5:显示http响应头
6:显示HTTP响应体
"""
python sqlmap.py --version
# sqlmap直连数据库(用户名、密码、端口地址、数据库名字)
python3 sqlmap.py -d "mysql://用户名:密码@地址:端口/数据库名字" -f --banner --dbs --users
# sqlmap 探测定向的url地址
"""
探测分7级(0-6),参数用V标识,级别越高,探测的东西越多,时间越长,默认为V1
- u : 指定单一url地址
- m : 探测多个目标(text文件保存在sqlmap文件中,可以保存多行目标, 目标地址需要和数据库有交互的地址)
- r : 指定httl交互文件,文件中保存请求头信息(request header(view parsed))
- c :从配置文件sqlmap.conf 中读取目标文件(需要先修改target url 地址)
--method :http请求方法(get、post、cookie、user-agent)
"""
python sqlmap.py -u "地址" --banner -v2
python sqlmap.py -u "地址" -2 --banner
sqlmap -m "文件路径" --banner
# 针对post方法提交参数的地址通过提交参数来进行测试
sqlmap -u "url" --data="uname=admin&passwd=amdin&submit=Submit" --banner
# sqlmap中设置cookie参数
#对登陆界面进行探测的时候需要携带 cookie信息 对登陆之后网站进行探测 也需要携带cookie 信息
--cookie "cookie值" # 指定cookie值
--cookie-del # 删除cookie值
--load-cookies # 在文件中加载cookie
--drop-set-ookie # 设置set-cookie的值
#sqlmap中设置 user-agent
sqlmap -u "url" --data="uname=admin&passwd=amdin&submit=Submit" --user-agent
# 随机设置请求user-agent
sqlmap -u "url" --data="uname=admin&passwd=amdin&submit=Submit" -- random -agent
# sqlmap 设置代理(ip代理)
sqlmap -u "url" --data="uname=admin&passwd=amdin&submit=Submit" --proxy "http:// $haproxy ip:prot"
sqlmap -u "url" --data="uname=admin&passwd=amdin&submit=Submit" --proxy-file
#设置http代理服务器认证信息
sqlmap -u "url" --data="uname=admin&passwd=amdin&submit=Submit" --proxy-cred user:pwd
--ignore-proxy # 忽略系统范围内的代理服务器
# qlmap 设置探测延迟
-- delay 0.5 # 设置延迟0.5秒
# sqlmap 中设置超时
--timeout 10.5 # (超过一段时间请求没有响应,此测试跳过)
# sqlmap 设置超时连接次数
--retries count # 默认为3次
# sqlmap 中设置随机参数(每次请求期间随机更改其参数名称(长度和类型根据原始值保持一直))
--randomize "参数名称"
# sqlmap 忽略 错误站点提示 401
--ignore -401 # 继续探测
# 指定网站请求的参数分隔符
--param-del = "分隔符"
常用检索参数
# 获取后端数据库的版本信息
-- banner
-b
# 获取DBMS当前用户
--current -user
# 获取当前数据库名称
--current -db
# 获取当前主机名
-- hostname
# 探测当前用户是否是数据库管理员
--is -dba
# 会先列举用户,在列举用户密码的hash值
--passwords
# 枚举 DBMS用户 所有用户
--users
# 列举数据库名
--dbs
# 枚举数据库表
--tables # 数据库名字
# 指定具体数据库
-D
# 枚举数据表列
--columns
-T # 指定数据库表
# 枚举数据值
-- dump
# 枚举schema 信息
--schema # (列举数据库管理系统模式,模式列表包括数据库、表、列、触发器、和他们各自的类型。同样的 可以通过参数 --exclude-sysdbs 排除系统数据库)
-sysbds # 除去数据库系统表
# 检索数据表数量
--count #(如果用户只想知道表数据条数)
# 获取数据信息
--start --stop (--start1 --stop3) # 返回前三条数据
# 设置条件获取信息
--where
# 暴力破解表名
--common -table
# 暴力破解列名
# 1、版本小于5.0的无法查询
# 2、数据库 用户的权限过低 无法读取表名
--common-columns
# 读取文件
--file-read # 路径 读取对应文件内容(此路径为绝对路径)
# 检索所有信息 参数
-a
--all # 返回所有的检索信息
性能优化
# 查询参数
python sqlmap -hh
# 设置持久化http连接(长连接)
--keep-alive
python sqlmap.py -u "地址" --keep-alive --banner -v2
# 设置不接收http body(不接收消息体)
--null -connection
python sqlmap.py -u "地址" --keep-alive --null-connection --banner
# 设置多线程
--thread = 3
python sqlmap.py -u "地址" --thread=3 --banner
# 一键优化(同时添加多个参数)
-o (--keep-alive --null-connection --threads = 3)
python sqlmap.py -u "地址" -o --banner
#**sqlmap自定义检测级别**
# 设置探测等级 (1-5)
# 大于2时、会对cookie等参数进行测试、大于3时,会使用user-agent 和 referer(跳转) 进行测试
--level = 2
python sqlmap.py -u "地址" -o --banner --level = 2
# 设置风险等级
--risk = 2
# 指定探测参数
python sqlmap.py -u "地址" -p "id,user-agent" --banner
# 跳过某些注入参数
python sqlmap.py -u "地址" -skip "参数名称"
# 对注入点存在uri中的,在参数后面加 # 进行指定探测参数
python sqlmap.py -u "127.0.0.1/id#/user/"
# sqlmap检索DBMS(指定探测数据库)
sqlmap -u "url" --data="uname=admin&passwd=amdin&submit=Submit" --dbms "数据类型"
# 执行操作系统
sqlmap -u "url" --data="uname=admin&passwd=amdin&submit=Submit" --os
# 无效值参数的替换(替换原有的、执行替换的部分)
--invalid-bignum
--invalid-logical
sqlmap -u "url" --data="uname=admin&passwd=amdin&submit=Submit and 恶意sql语句" "
# 自定义注入负载位置
--prefix "设置sql注入payload前缀"
sqlmap -u "127.0.0.1/lesson/id=1" --prefix
--suffix "设置sql注入payload后缀"
# 设置Tamper参数
sqlmap -u "127.0.0.1/lesson/id=1" --tamper "脚本名称"
# 设置DBMS认证
--dbms-cred = username
指定注入参数
# 参数 --technique
# 默认情况下所有的方式全部使用一遍
B:Boolean-based blind # (布尔型注入)
E:Error-based # (报错型注入)
U:Union query-based # (可联合查询注入)
S:Stacked queries # (可多语句查询注入)
T:Time-based blind # (基于时间延迟注入)
Q:Inline queries # (嵌套查询注入)
# 设置时间盲注延迟时间(默认5s)
--time-sec
# 设置union联合字段数
--union-cols 12-18
# sqlmap设置union字符
-union-char
# 设置联合查询表
--union-from "表名" # 指定联合查询的表名
# 探测目标指纹信息
-f
--fingerprint