线程与MySQL回归
线程相关知识
线程理论
进程
进程是资源单位
线程
线程是执行单位
一个进程内至少有一个线程
1.一个进程内可以开设多个线程
2.同一个进程下的多个线程是数据共享的
3.创建线程的消耗低于进程
因为创建进程要占用内存资源,而线程则不需要
创建的线程的两种方式
方式一:
from threading import Thread
def task(name):
print(f'{name} is running')
t = Thread(target=task, args=('jason',))
t.start()
方式2:
class MyThread(Thread):
def run(self):
print('is running')
obj = MyThread()
obj.start()
"""
需要注意的是子进程创建运行也是异步的,但是子进程的创建速度是很快的,所以执行顺序会直接会开始执行函数体代码
"""
线程的诸多特性
jion方法 主线程等待子线程结束才开始执行
同个进程内的多个线程数据共享
current_thread()
active_ciount()
python多线程是否有用
需要分情况:
情况1: 多个CPU 单个CPU
情况2: IO密集型(代码有IO操作) 计算密集型
1.单个CPU
IO密集型
多线程有优势
计算密集型
多进程有优势
2.多个CPU
IO密集型
多线程有优势
计算密集型
多进程有优势
GIL全局解释器锁
1.在python解释器中存在全局解释器锁
2.GIL本身也是一把互斥锁,用来阻止同一个进程内多个线程同时执行
3.GIL的存在是因为python进程中有垃圾回收机制的线程,内存管理不是线程安全的
通俗点:在python进程中垃圾回收机制是必须存在的,如果没有GIL全局解释器锁,那么多个线程可以同时运行,垃圾回收机制很容易清除掉还没有绑定的数据,造成数据的丢失
信号量
在python中并发编程信号量相当于多把互斥锁
from threading import Thread, Semaphore
import time
import random
sp = Semaphore(5) # 一次性产生5把锁
class MyThread(Thread):
def run(self):
sp.acquire() # 加锁
print(self.name)
time.sleep(random.randint(1, 3))
sp.release() # 释放锁
for i in range(20):
t = MyThread()
t.start()
"""
这样一次就可以有5个线程抢到锁,同时执行5个线程
"""
event事件
from threading import Thread,Event
import time
event = Event()
def light():
print('红灯亮着 所有人不能动')
time.sleep(3)
print('绿灯亮了 油门踩到底!冲冲冲!!!')
event.set()
def car(name):
print(f'{name}正在等红灯')
event.wait() # event事件表示,会在这里等待执行到event.set()执行结束才会执行
print(f'{name}飙车了')
t = Thread(target=light) # 创建线程执行Light函数
t.start()
for i in range(10):
t = Thread(target=car,args=('熊猫PRO%s' % i,))
t.start()
"""
event事件其实就是等待执行到event.set之后才会执行event.wait
"""
进程池与线程池
进程和线程是不可以无限制的创建
硬件的发展是赶不上软件的,有物理极限,如果我们在写代码的过程中无限制的创建进程或者线程会造成计算机的崩溃
池
降低程序的执行效率,提高了计算机的安全性
进程池
提高创建好固定需要的进程供给后续程序的调用
线程池
体检创建好固定数量的线程供给后续程序的调用
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time
import random
from threading import current_thread
# 1.产生固定数量的进程池和线程池
pool = ProcessPoolExecutor(5) # 创建固定5个进程的进程池
pool1 = ThreadPoolExecutor(10) # 创建固定10个线程的线程池
def task(n):
print('task is running')
time.sleep(random.randint(1, 3))
print('task is over', n, current_thread().name)
return '我是task函数的返回值'
def func(*args, **kwargs):
print('from func')
if __name__ == '__main__':
# 直接将任务提交给线程池久远可以了
for i in range(20):
pool.submit(task, 123).add_done_callback(func)
# 这句话表示将函数task函数提交给线程池,然后获取的返回值直接作为参数传入func函数,执行,这样必须一个进程或者线程执行完毕task函数之后才可以执行func
携程
进程:资源单位
线程:执行单位
携程:单线程下实现并发,在代码层面欺骗CPU,让CPU认为代码没有没有IO操作,实际上IO操作被我们写的代码检测,一旦有,立刻让代码执行别的,自己写的代码完成切换+保存状态
数据库初识
读取数据的演变史
1.文本文档
存放位置不统一,存放格式不统一
2.软件开发目录
存放位置统一但是格式不统一
3.数据库服务
统一龙江,统一操作方式
数据库软件应用史
1.本地存储
2.网络存储
网络集中存储让所有数据存储到一起,为了保证数据的安全性所以会有数据库集群
数据库的本质
站在底层原理
数据库就是一堆代码
站在实际应用
数据库指的是可视化操作界面(一些软件)
数据库软件本身也是CS架构
数据库的分类
1.关系型数据库
特征1:有固定的表结构(字段名、字段类型)
特征2:数据之前可以建立数据库层面的关系
有:MySQL,Orcale,MariaDB,PostgreSQL,sql servser,sqlite,acces
2.非关系型数据库
有:redis,mongoDB
MySQL简介
1.版本问题
8.0版本 目前最新
5.7版本 使用率最高
5.6版本 学习推荐使用
系统服务的制作
1.把bin目录添加系统环境变量
2.将mysql添加到系统服务中
以管理员身份打开cmd窗口
mysql --install
移除系统服务
mysql --remove
3.启动mysql进程
net start mysql
4.停止mysql
net stop mysql
SQL与NoSQL
SQL:
操作关系型数据库的语言
NoSQL:
操作非关系型数据库的语言
数据库重要概念
库 文件夹
表 文件
记录 文件内的数据
基本的SQL语句
1.sql语句必须以分好结尾
2.sql语句编写错误直接执行报错即可
基于库的增删改查
show databases 查看所有的库
create database 库名 创建库
show create databass 库名 查看具体某个库
alter database 库名 charset = 'utf8' 编辑库
drop database 库名 删除库
基于表的增删改查
先切换到库里面 use 库名
show tables 查看所有的表
create table 表名 创建表
show create table 表名 查看具体某个表
desc 表名 查看表结构
alter table 表名 rename 新表名 编辑表
drop table 表名 删除表
基于记录的增删改查
select * from 表名 查看表内的所有记录
insert into 表名 values(数据) 表内添加数据
update 表名 set 字段名=新数据 修改表内的数据
delete from 表名 删除表内的全部数据
delete from 表名 where 条件 删除表内符合条件的数据
数据库的基本数据类型
数据库引擎
存储引擎
数据库针对数据采取的多种存取方式
查看常见存储引擎的方式:
show engiens
需要了解的4个引擎;
MyIASM mysql5.5及之前默认的引擎
InnoDB mysql5.6及之后默认的引擎
Memory 基于内存存取数据,临时数据存储
Blackhole 任何存取进去的数据都会立刻丢失
不同存储引擎底层文件的个数
InnoDB
.frm 表结构
.idb 表数据
MyIASM
.frm 表结构
.MYD 表数据
.MYI 表索引
memory
.frm 表结构
blackhole
.frm 表结构
创建表的完整语法
create table 表名(字段名 字段类型 约束条件)
字段类型之整型
tinyint 1bytes
smallint 2bytes
int 4bytes
bignit 8bytes
取消正负号
unsigned
字段类型之浮点型
float()
double()
decimal()
括号内第一个是多少位的数字,第二个数字是表示小数点后多少位,所以第一个数字肯定是大于第二个数字的以防写错
三者的区别主要是精确度的不同
字符类型之字符类型
char()
定长
最多存储括号内个数的字符,超出就报错,不够就用空格填充
varchar()
变长
最多存储括号内个数的字符,超出就报错,不够有几位存几位
char:
优势:整存整取,速度快
劣势:浪费存储空间
varchar:
优势:节省存储空间
劣势:存储数据比char慢
字段类型之枚举和集合
枚举:
关键字:enum,表示从enum后面的数据中选择一个
集合:
关键字:set,表示从set后面的数据中选择多个,也可以选择一个
字段类型之日期类型
datetime 年月日时分秒
date 年月日
time 时分秒
year 年
MySQL之字段约束条件
无符号、零填充
无符号:unsiged
零填充:zerofill
非空
在mysql中默认记录可以为空,我们可以添加约束让这条数据不能够为空
not null
默认值
比较类似于我们函数的默认参数,如果我们这个字段写入数据用写入的数据,如果没有写入数据则用默认值
关键字:
default
唯一值
单例唯一
某个字段下的数据不能够重复
写法:
字段名 字段类型 unique
联合唯一:
字段组合不能够重复,但是单个字段是可以重复的
写法:
字段名 字段类型,
字段名 字段类型,
unique(字段名,字段名)
主键
在InnoDB引擎中规定有且只有一个主键
从约束层面上可以理解为:非空且唯一的字段
写法:
字段名 字段类型 primary key
1.当表中没有主键且没有其他非空且唯一的字段
InnoDB会采用一个隐藏的字段作为主键
2.当表中没有主键且有其他非空且唯一的字段
会直接将从上到下第一个的非空且唯一的字段默认改为主键
自增
该约束条件不能单独使用,需要配合主键一起使用
自增的特性:
不会随着数据的删除而退回,永远自增向前
如果设置了更大的数,会按照更大的数自增
外键
表的关系判断;
一对多
多对多
一对一
换位思考的方法,站在一方判断己方的一条数据是否可以对应对方多条数据,如果一方可以对应另一方不可能则是一对多关系,如果两方的一条数据都可以对应对方的多条数据则是多对多的关系,如果两方都不可以对应另一方的多条数据则是一对一或者没有关系
一对一外键字段的建立
外键要创建在多的一方
关键字:foreign key(外键) auto_references 来自的表(表中的字段名)
1.需要先创建被关联的表
2.录入数据的时候一定要先录入被关联表
3.修改数据的时候外键字段如法修改和删除
针对3的简化措施:级联更新级联删除
foreign key() auto_references()
on update cascade
on delete cascade
多对多外键字段的建立
针对多对多关系不能直接在表中创建,需要新建第三张表关系
在第三张表中创建两个外键,分别对象多对多两张表中的主键
一对一外键字段的建立
针对一对一关系外键可以建立在任何一方,但是建议建立在查询频率比较高的一方
注意:
一对一的外键需要添加约束条件唯一值,否则就和多对多一样了
外键 unique
foreign key(外键) references 表名()
MySQL关键字查询
SQL语句查询关键字
select 查询指定字段的信息
from 查询指定表内的信息
where 筛选表内的信息
group by 分组,显示最小为组的单位
having 二次筛选,where在group之前,having在之后
distinct 去重
order by 排序,默认为升序,order by 字段名 desc 修改为降序
limiti 分页展示,limit()展示数据的个数
regexp 正则表达式