一、多进程实现TCP服务端并发
通过之前的学习我们了解到可以使用process模块创建多进程,但是服务端在接收的时候如果跟之前一样的方式接收会出现端口被占用的报错提示,这时候我们把创建服务端和接受客户端信息并返回值的代码包装到两个函数中,然后在用process类调用方法接收客户端的信息并产生多个进程服务多个客户端来达成目的。
二、互斥锁
当我们在模拟抢票软件的时候会出现客户端根据旧的数据进行计算,返回所有客户端都抢到票的情况,这种情况下我们需要使用互斥锁来解决问题。
互斥锁的原理就是对共享的数据进行锁定,让多个线程或是进程来抢这个锁,抢到的人才能来使用这个数据,别的人需要排队才能使用。
虽然互斥锁解决了数据混乱的问题,但是他降低了程序运行效率。
在python中multiprocessing模块内有一个叫Lock的类,这个就是锁的模块,在使用的时候我们创建一个锁,然后在要进行数据操作的时候让线程进行抢锁(acqurie),使用完了数据之后让线程放锁(release)。
但是在使用锁的时候我们需要避免死锁现象,所谓死锁现象就是一个进程拿了另一个锁然后他需要拿到两个锁才会同时释放两个锁,但是这时候另一个进程拿了另一个锁,这个进程的工作流程也跟上一个锁一样,因为两者都不放锁,就会导致程序卡住,一直处于等待别的程序放锁的等待状态。在没有外力改变的情况下,没有办法改变这个状态。
三、线程理论
说到线程,我们就会想到进程,通过进程的运行方式我们可以把进程看成一个py文件,一个进程就相当于是运行了一个py文件,因为运行py文件的时候需要去内存中申请空间,因此我们可以把进程看成是一个资源单位。
回头说线程,线程就相当于进程的执行单位,把进程看成一点店铺,一个线程就是一个服务员,相当于py文件中的代码指令。
一个进程内最少也有一个线程,多线程在运行纯计算的代码时,会比较快,在运行需要执行I/O操作的代码时就会变得更慢,这是因为多进程需要去内存中申请内存空间,而多线程则不用,同时多进程之间数据不互通,但是在多线程中,只要在一个进程内,数据是互通的。在执行线程的时候,多线程其实是以串行的方式运行的,也就是同步的方式,因此在遇到I/O操作的时候就会进入阻塞态,导致总耗时需要用1+1的方式来计算所有的线程的运算时间,而到了纯运算的线程中,会使用时间片轮转法和多级队列的方式进行线程的运行,导致我们觉得多线程是同时运行的,也就是通过多道程序计数中的切换和保存来执行的。
创建线程的两种方式
在创建线程的时候用到的是threading 模块,但是用的是Thread类,在创建的时候方式跟创建进程的一样,分成两种,一种是直接定义函数,通过调用函数创建线程,另一种是用派生方法重新定义一个类,继承thread的方法,然后让创建出的对象调用方法创建线程。
然后在创建线程的时候我们可以使用current_thread().name查看线程名称
然后使用account_count()可以查看主线程的名称(执行一个py文件的时候,那个文件中本来的一些代码叫主线程,用模块创出来的其他线程叫做子线程)。
四、GIL全局解释器锁
显示提到了cpython解释器,也就是我们现在使用的解释器。GIL存在与cpython解释器中。
本事上来说他也是一种互斥锁,最早的时候是为了利用多核cpu,运行多线程。
但是他存在于python解释器中,作用在解释器的运行上。当我们在执行python解释器运行很多指令的时候就相当于创建了多线程,这时候如果不加上这个GIL运行效率会很快,但是会出现混乱,比如我们在前面学习过python解释器的垃圾回收机制运行规律,如果我们在解释器中不加上这个GIL,变量名绑定数据值的时候,就会出现数据值刚创建还没绑定给变量名,就被垃圾回收机制干掉的情况。
他就相当于让python代码在执行的时候,排队调用解释器工作,也是用acquire和release来抢锁和释放锁。
接下去就是用代码验证GIL的存在,验证方式就是用time.sleep让线程睡一会,然后开启多个线程执行,计算运行时间,这时候我们会发现时间就是所有线程的运行时间的总结。
最后我们提了一下GIL和别的普通锁有没有必要一起用,这里的话GIL只是确保运行python解释器的时候数据不会被垃圾回收机制提前干掉,并不能确保进程内部的数据会不会混乱。
多线程和多进程的使用场景优先级
多核cpu
在多核的情况下如果是I/O操作密集的代码,适合使用多进程,如果是计算密集型的代码,还是适合使用多线程。
单核cpu
在单核的情况下因为不论多进程还是多线程,其实都是用的多道程序技术运行的,用的都是一个cpu,只是每个进程或线程占用一点时间运行,来达到同时运行的视觉效果,因此我们应该多使用多线程,毕竟申请内存空间用时会更长。
五、信号量
信号量作用就是限制一个进程内同时最多可以有几个锁,抢锁的进程或线程很多的时候就会出现排队的状况。
在python中使用的时候还是导入multiprocessing模块,然后导入Semaphore类,调用类产生对象时写上参数,参数的作用是设置同时可以有几个锁供程序抢。
六、event事件
event时间就相当于一个红绿灯,所有的线程运行到event位置,获取状态,如果event的状态对应的情况停止,所有线程就会进入等待状态,当状态变化后就会同时往下运行后续代码。
python中使用的时候需要导入threading模块然后导入Event类,接着用类创建对象,对象调用.wait()就是让程序等待,调用.start()就是让所有的等待中的程序继续运行,如果直接使用.start()就相当于没有这个代码一样,会直接运行下去。
七、进程池和线程池
当我们在使用计算机的时候进程和线程是可以无线创建的,但是计算机的性能不是无线的,因此我们需要使用进程池和线程池来控制。这两个池子的作用跟半连接池相似,
在用python代码创建进程池的时候,导入concurrent.futures模块然后导入其中的ProcessPoolExecutor类,创建对象的时候括号内写上数字,数字为多少,就是设置成同时可以运行几个进程。其余的进程会进行排队等候使用。然后我们使用submit创建进程。
然后当调用的函数或是对象的方法有返回值的时候,我们用变量名接收submit方法运行的结果就能接受到返回的结果。
关闭进程池用的是.shutdown方法,他并不会立刻关闭,会等到进程结束才关闭
当我们在运行多进程的时候有些进程会有返回值,我们在进程的最后使用名称.add_done_callback()来让他自动打印调用结果。
然后线程池是用到ThreadPoolExecutor类,导入方法和使用方法和进程池一致
八、协程
所谓的写成是程序员创建的,意味用代码欺骗cpu,在进程或线程进入I/O操作的时候不进入阻塞态,加快程序运行效率。
python中使用的时候需要用到gevent模块中的monkey类、spawn类来创建协程
九、MySQL来历
在我们学习python的过程中最开始我们使用的是txt文件存储信息,第二个阶段我们使用软件开发目录规范,把信息存到db目录中,第三个阶段就是使用数据库。
txt文件阶段,存储数据的位置、存储的格式都不一致,换台设备不一定能使用。
第二个阶段虽然规定了db目录,但仍旧不能确实数据的存储格式,比如一些人习惯两种数据之间使用‘|’符隔开。
第三个阶段就是解决了上述问题,使用统一 的软件,进行开发,效率高的同时学习成本低。
接着我们聊到了数据库软件的应用过程,最开始的时候我们可以理解成数据库软件就想存储单机游戏的数据一样,只能在一台电脑上保存,更换电脑需要拷贝文件去另一台电脑上操作。
接着进入了网游阶段,数据库服务端在别的计算机上,但是游戏客户端可以获取服务端的数据,所有的数据都是存储在服务器中。数据的保密性,安全性,可靠性都很高。
十、数据库的本质
从底层原理来说,数据库就相当于是一个进程,用于对数据进行操作。
从实际应用角度来说,数据库就相当于是一个可视化软件,可以对数据进行操作,也有数据库的第三方软件,对各种功能进行了简化处理的,但是我们学习的时候不用。
然后上文中我们讲了,数据库也是用cs架构的方式,使用客户端和服务端来提供服务的,这意味着数据库其实也是程序员编写的,只不过我们短期没这水平。
十一、数据库的分类
数据库分为关系型数据库和非关系型数据库
关系型数据库
特点有固定的表结构,如字段等
数据库的表之间可以建立联系
常见的关系型数据库有MySQL、oracle、mariaDB、postgresql、access、sql server等
其中MySQL使用最广,开源免费,是甲骨文公司所有的。
oracle是收费的数据库软甲,但是安全性高,银行等地方用的是他,也是甲骨文公司的软件。
postgresql也是开源免费的,但是他支持二次开发,兼容性好,可以定制功能。
mariaDB也是开源免费的,是MySQL的开发者编写的,原因就是开发者开发了MySQL后被收购了,他们担心收费就开发了mariaDB这个数据库。
非关系型数据库
特点就是没有固定的表结构
表之间不能建立关系
常见的有redis、mongoDB、memcache
redis是目前用的最多的非关系型数据库,他是一款基于缓存工作的数据库,但是又有保存数据等其他功能。
mongedb是非关系型数据库中最像关系型数据库的,他是一种文档型数据库。
memcache是老款的,被redis淘汰了。
十二、mysql安装和服务设置
官网查找安装包,然后解压,接着把文件内的bin目录添加环境变量,接下去就是添加到服务中,省去打开服务端的操作(cmd界面输入mysqld的命令)。
首先我们用管理员身份打开一个cmd界面,然后输入mysqld --install
然后去服务窗口中查看是否出现了mysql服务,win+R然后输入servers.msc
接着我们可以用两种方式启动,第一种是在服务窗口中右键启动他,第二种是在cmd中输入net start mysql
如果需要卸载
需要先输入net stop mysql
然后输入mysqld --remove
才能删除服务
十三、sql和nosql
sql是操作关系型数据库的语言
nosql是操作非关系型数据库的语言
我们目前流行的数据库被很多软件使用,因此是数据库提供语言,客户端也就是使用数据库服务的那一方,需要遵循数据库的规定使用sql和nosql来操作数据库,虽然客户端有很多版本,有程序员自己编写的,有数据库提供的,但是他们底层逻辑都是容不同的语言,对数据库使用sql和nosql语言进行操作。
十四、数据库中的小概念
库
相当于文件夹
表
相当于一个文件
记录
相当于文件中的数据和记录
十五、数据库中的代码指令
注意事项
1、mysql中的语句需要用;结尾
2、mysql中的语句如果有问题执行报错了,可以看报错提示修改,报错的语句不会被执行。
修改密码的
1、mysqladmin -uroot -p密码 password 新密码
2、直接修改存用户信息的表
3、有些局限性的方式,只能修改当前登陆用户的密码
set password=password('新密码')
忘了密码
1、重装
2、删除data目录中的数据,拷贝别人的,就相当于用别人的账号登陆
3、用代码以不校验密码的方式登陆
库的一些命令
create database 库名称;
创建库
drop database 库名称;
删除库
show databases;
查看所有的库的名称
其中第一个库是存在于内存中,本地看不到文件
show create database 库名称;
查看指定的库
alter database 库名称 charset='utf8';
修改库的字符编码类型
5.6版本中用到了gbk和拉丁文
我们可以在配置文件中修改,配置的代码不用记忆
表的指令
show tabels;
查看所有的表名称
show create table 表名称;
查看指定的表的信息
create table 表名称;
创建表
drop table 表名称;
删除表
desc 表名称
查看表的具体内容
alter table 表名称 rename 新表名;
重新命名
基于记录的指令
insert into 表名称 values(字段名称 字段类型(参数) 约束条件);
select * from 表名称;
查看指定表中的所有数据值
delete from 表名称;
删除表中所有数据,后面可以跟上对应的条件删除指定记录。
update 表名称 set 字段名=新记录 where 筛选条件;
修改指定位置的记录
十六、配置文件修改字符编码
首先我们要说一下配置文件的作用,他会影响服务端的启动(启动的时候会读取配置文件执行),他还会影响客户端的连接,连接的时候会用到配置文件的信息。
接着我们介绍配置文件。
my-default.ini
我们通常不直接修改配置文件,而是使用拷贝出来的文件,命名成my.ini来使用新的配置信息。
十七、数据库存储引擎
数据库存储引擎就相当于是一个用于对数据进行操作的工具。是数据库的底层核心。
我们可以使用show engines;
查看当前版本支持的数据库存储引擎
需要介绍的四个引擎
myisam
5.5和之前版本的mysql使用的默认引擎
特点是存储速度快,但是安全性低
innodb
这是5.5版本之后的MySQL软件使用的默认引擎,特点是安全性高,支持事物、外键、行锁等功能,但是速度没myisam快
memeory
基于内存工作的存储引擎,仅用于临时的数据存取
blackhole
写进去的数据会立刻丢失
其中memory和blackhole创建的表只有一个文件,innodb有两个,myisam有三个。表结构是都有的,innodb把表数据和索引放到了一个文件中,myisam则是拆开放了。
十八、严格模式
我们在存储数据的时候如果不符合表的格式规定就会存不进去,这是通常情况下的状况,这个状态叫严格模式,如果我们删了配置文件中的sql_modes的配置信息就会退出严格模式,这个时候存入的数据也要符合格式,但是遇到不符合格式的数据的时候会让他失真,变得符合格式,但是对于数据库来说数据失真就没有意义了。
show variables like '%mode%';
我们可以使用这个代码查看是否处于严格模式
十九、字段类型
整形
就是存储整数的,常见的字段类型有tinyint、smallint、int、bigint
这写整形的字段类型都是默认情况下自带正负号的,符号要占一个字节,然后所有的类型能存储的整数的大小是根据大小来确定的。
比如tinyint只有一个字节的大小,也就是八位二进制,所以他只能存256个数
浮点型
用于存储小数
float、double、decimal
前两个对精度要求不高,第三个decimal有精度要求,小数点后很多位的时候不会数据混乱。
浮点型在设置字段类型的时候括号内有两个数用逗号隔开,这里的第一个数是设置总共可以有多少个数字,第二个数就是设置小数点后需要有一个数字。
字符类型
也就是python的字符串类型
char、varchar
char是定长
varchar是变成
char类型的记录在存储的时候,位数不够的会用空格填充,varchar则是用报头获取每次存的数据值的内容,然后不存储空格,速度较慢,每个报头要占1字节,我们在使用的使用应该考虑实际的应用情况。
数字的含义
在整形中
数字并不代表能存储的数据值的位数,而是代表展示的时候显示的位数。
枚举和集合
enum枚举
set集合
枚举就是给定一些数据值,需要在里面选一个
集合就是给定一些数据集,可以在里面选一个,也可以选多个
日期类型
有datetime、date、time、year、等类型
其中datetime就是显示年月日时分秒的
date就是显示年月日
time就是显示时分秒
year是显示年分的日期类型
二十、字段的约束条件
unsigned无符号(-+号)
zerofill用0填充(char类型)
not null非空
default默认值,关键字后跟上默认值,跟关键字参数一样的
unique唯一
分成单列唯一和多列唯一
单列唯一就是一个字段中数据值不能重复
多列唯一就是多个字段组合起来的数据值不能初夏重复
primary key
主键,同时有唯一和非空的性质
auto_increment自增,只能有一个自增字段,通常配合主键使用
在innodb存储引擎中创建表的时候必须要有一个主键
当没有人为规定主键的时候分两种情况
第一种什么约束条件都没有的时候,就会创建一个隐藏的主键,我们用不了他
第二种,在有字段的约束条件有非空和唯一的情况下,我们就会把第一个满足这样条件的字段设置成主键
二十一、外键
foreign key(字段名称) reference 表名称(表中字段名称)
外键就是关系型数据库建立关系用的
我们在创建关系的时候,需要先定义一个字段存放有关系的记录,然后把这个字段跟有关系的表中的对应字段联系起来。
on update cascade
on delete cascade
这两个代码跟在外键语句的后面可以把两个表直接设置成关联、级联状态,会同步修改
但是使用的时候需要根据使用环境修改,当表很多的时候反倒会影响修改
表与表之间有多种关系
根据存储的内容进行判断分类
比如学生跟课程的表格
一个学生可以有多个课程,一个课程可以有多个学生来学习
这就是一个多对多的情况
这种情况需要创建第三个表来存储关系信息
如果一方是多,一方是只能有一个,这种情况就是一对多的情况,我们需要在可以对应多个的表中创建外键建立关系
如果一对一的关系,就看哪一个表的使用频率高,把外键创在使用频率高的一方。
二十二、语句查询关键字
所谓的查询关键字就是查找记录的时候用到的select和from
我们需要注意两者的运行顺序并不固定,比如我们查看表中数据的时候是先用from获取表,然后再用select获取表中数据的。
在执行复杂的查询语句的时候可以先写上select * from 表名称;
然后慢慢修改
where关键字
用于筛选符合条件的数据
可以加上逻辑运算符和成员运算符还有比较运算符
这里在判断记录内部的值是否为null的时候有个特殊情况,规定为非空的地方,可以用''来填充,查看的时候结果就是空的,不会显示null
grop by
5.6版本可以不对数据进行限制,在关键词后面直接跟上分组的条件就可以对数据进行分组,如果要更改需要去配置文件中修改,也可以用set global设置成当前服务端的配置,只要不重启就能使用下去
在分组的时候可以使用一些聚合函数对数据进行筛选,比如max、min、avg、sum、count等
group_concat可以查看一个字段中的所有的值,我们可以用它查看对应中类中所有的用户名称。
having
过滤
作用跟where相似
但是where是筛选分组前的数据值,having可以筛选分组后的值
distinct去重
跟python中的集合作用相似
当我们使用去重的时候可以写一个字段也可以写多个字段,写一个字段的时候就相当于普通的去重,多个字段的时候就相当于是对多个字段组合起来的数据值进行去重,跟多列唯一的判断条件类似
order by
排序
后面跟上字段名称就会排序,默认情况和字段名称后跟asc的情况下会是升序排序
跟desc 的时候会是降序
limit
分页
在我们查看数据的时候会出现数据很多一下子占满屏幕的情况,这个时候在后面跟上limit就可以限制显示的记录数量,如果写上两个数字,第一个数据就是表示起始为止,第二个位置表示读取的记录数量
regexp
正则表达式的关键字
当我们使用一些模糊的运算符号筛选记录的时候会觉得不方便,这时候我们可以使用正则来写
二十三、多表查询
当我们在查询记录的时候同时写上两个表的名称,两个表中的所有数据,会互相组合一次,这时候的数据没有什么实际用处,但是表现出来了一格现象,叫做笛卡尔积
但是我们在后面跟上where进行筛选就可以让记录进行有规律的组合,变成可用的数据。
标签:回顾,数据库,使用,线程,时候,进程,内容,第九,数据 From: https://www.cnblogs.com/zhihuanzzh/p/16930135.html