第五十八篇 epoll模型、数据库

一、IO模型回顾

为了解决IO操作导致CPU闲置的问题

1.阻塞模型

执行recv或accept时,如果数据没到达,就阻塞当前程序,并让出CPU,让其去执行其他任务

2.非阻塞模型

1.将recv、accept、send 都设置成了非阻塞

2.非阻塞情况下,没有数据会立马抛出异常,我们可以捕捉异常,然后切换到其他任务

3.缺点:如果一直没有数据,程序将一直做无意义的循环,浪费CPU资源

4.优势:单线程内并发可以处理多个客户端

3.多路复用

使用select来帮助我们检测socket的状态

4.异步IO模型

整个过程都是异步,包括wait_data和copy_data两个步骤

5.信号驱动IO模型

二、epoll模型

1.select 的问题:

1.当进程被唤醒,但它不清楚到底哪个socket有数据,因此只能遍历一遍存放进程的队列

2.每一次select的执行,都需要将这些进程加入到等待队列中

3.为了防止重复添加等待队列,当某一次操作完成时,也必须从等待队列中删除进程,所以select最大限制被设置为了1024,如此看来select连多线程都比不上

4.于是推出了poll 和epoll,而poll只是简单对select进行了优化,但是还不够完美 ,epoll才是最后的解决方案

**5.注意:epoll仅能在linux中使用 **

2.epoll解决的问题

1.避免频繁的对等待队列进行操作

2.避免遍历所有socket

3.epoll相关函数

import select 导入select模块

epoll = select.epoll() 创建一个epoll对象

epoll.register(文件句柄,事件类型) 注册要监控的文件句柄和事件

事件类型:

  select.EPOLLIN    可读事件

  select.EPOLLOUT   可写事件

  select.EPOLLERR   错误事件

  select.EPOLLHUP   客户端断开事件

epoll.unregister(文件句柄)   销毁文件句柄

epoll.poll(timeout)  当文件句柄发生变化,则会以列表的形式主动报告给用户进程,timeout

                     为超时时间,默认为-1,即一直等待直到文件句柄发生变化,如果指定为1

                     那么epoll每1秒汇报一次当前文件句柄的变化情况,如果无变化则返回空

epoll.fileno() 返回epoll的控制文件描述符(Return the epoll control file descriptor)

epoll.modfiy(fineno,event) fineno为文件描述符 event为事件类型  作用是修改文件描述符所对应的事件

epoll.fromfd(fileno) 从1个指定的文件描述符创建1个epoll对象

epoll.close()   关闭epoll对象的控制文件描述符

4.举例

1.服务端

# coding:utf-8
import socket, select

server = socket.socket()
server.bind(("127.0.0.1", 1688))
server.listen(5)

msgs = []


fd_socket = {server.fileno(): server}
epoll = select.epoll()
# 注册服务器的 写就绪
epoll.register(server.fileno(), select.EPOLLIN)

while True:
    for fd, event in epoll.poll():
        sock = fd_socket[fd]
        print(fd, event)
        # 返回的是文件描述符 需要获取对应socket
        if sock == server:  # 如果是服务器 就接受请求
            client, addr = server.accept()
            # 注册客户端写就绪
            epoll.register(client.fileno(), select.EPOLLIN)
            # 添加对应关系
            fd_socket[client.fileno()] = client

        # 读就绪
        elif event == select.EPOLLIN:
            data = sock.recv(2018)
            if not data:
                # 注销事件
                epoll.unregister(fd)
                # 关闭socket
                sock.close()
                # 删除socket对应关系
                del fd_socket[fd]
                print(" somebody fuck out...")
                continue

            print(data.decode("utf-8"))
            # 读完数据 需要把数据发回去所以接下来更改为写就绪=事件
            epoll.modify(fd, select.EPOLLOUT)
            #记录数据
            msgs.append((sock,data.upper()))
        elif event == select.EPOLLOUT:
            for item in msgs[:]:
                if item[0] == sock:
                    sock.send(item[1])
                    msgs.remove(item)
            # 切换关注事件为写就绪
            epoll.modify(fd,select.EPOLLIN)

2.客户端


#coding:utf-8
#客户端
#创建客户端socket对象
import socket
clientsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#服务端IP地址和端口号元组
server_address = ('127.0.0.1',1688)
#客户端连接指定的IP地址和端口号
clientsocket.connect(server_address)

while True:
    #输入数据
    data = raw_input('please input:')
    if data == "q":
        break
    if not data:
      continue
    #客户端发送数据
    clientsocket.send(data.encode("utf-8"))
    #客户端接收数据
    server_data = clientsocket.recv(1024)
    print ('客户端收到的数据:',server_data)
#关闭客户端socket
clientsocket.close()

三、数据库

1.数据库是什么

1.存放数据的仓库

2.存放数据的其他容器:列表、字典...实在内存中。优点:速度快;缺点:断电丢失

3.文件存储。优点:永久保存;缺点:速度慢

4.数据库的本质:基于CS架构(客户端/服务端)的程序,最终会将数据存储在服务端的磁盘上

2.为什么使用数据库

1.解决直接使用文件存储带来的问题

2.文件存储的问题:

  • 1.速度慢

  • 2.由于单台机器性能肯定有上限,通过数据库联网的特性,可以用多个机器共同完成数据存储和操作的任务,如果是将数据以文件的形式分布在不同的机器上,处理起来则会比较麻烦,效率低

  • 3.不方便用户权限管理

  • **4.多个客户端并发访问,数据很难保证安全 ****

3.服务器架构:

  • 1.分布式:每个服务器提供不同的服务(有时候某个业务流程也可能会涉及到多个服务器)

    • 1.优点: 耦合度降低 易维护

    • **2.缺点:通讯繁琐,容灾性没有集群好 **

  • 2.集群:所有服务器提供的服务是一模一样的

    • 优点:容灾性强,易扩展,可插拔

通过网络 访问

3.数据库的分类

1.关系型数据库

1.数据之间可以存在关联关系,关系型数据库会帮我们维护这种关系

2.通常存储介质都是磁盘

3.常见的关系型型数据库:

# mysql      
是我们学习的重点,是目前最流行的关系型数据库,因为其免费开源,性能不错 
目前已经被oracle收购了,适用于中小型企业 

# sqlserver	
是微软推出的, 因为其只能运行在windows平台所以发展不咋地 

# oracle
目前最强大的关系型数据库,主要是在集群,和用户管理上,非常适合大型企业 

# db2
IBM的产品,主要面向企业级用户,不差钱的用户 捆绑硬件销售 

2.非关系型数据库

1.一般不帮我们维护数据之间的关系

**2.通常存储介质都是内存 **

3.常见的非关系型:

mongoDB

redis

memcache   

4.数据库的重要概念

1.字段/具体数据(Column:列):文件中的某个字符串,比如,姓名:King

2.记录(Row:行):文件中的某一行,比如,姓名:King,年龄:26,性别:male

3.表(Table):某个文件。库下面有多个文件,比如,mysql文件夹中的user.MYD文件。这些文件中存放着多行记录

4.库(DataBase):某个文件夹。数据库软件中有多个文件夹,比如,mysql文件夹

5.DBMS:数据库管理系统(就是数据库软件,比如:mysql-5.6.43-winx64)

**6.数据库服务器:运行DBMS的计算机(在电脑上搜索“服务”)

5.数据库的安装和简单使用

1.bin中存储所有执行文件(mysqld.exe是服务端,mysql.exe是客户端)

2.data中存储数据:文件夹(库)--文件(表)

3.运行客户端时,如果直接双击运行是进入游客模式,正确的运行方式是,在终端里指定用户名密码等参数:

-h        主机名称 如果是本机 可以忽略

-P(大写)   指定端口 默认3306  可以不写  

-u        指定用户名   

-p(小写)   指定密码


# -h127.0.0.1 -P3306 -uroot -p

4.添加环境变量:

1.将bin的路径复制到系统环境变量中

2.通过cmd管理员权限:注册系统服务,cmd中输入 mysqld  --install 

5.一些简单操作:

# cmd中输入

1.如果之前装过mysql,想卸载:sc delete mysql(注意:mysql是服务名称不是文件名称)

2.启动服务 net start mysql;

3.停止服务 net stop mysql;

4.查找某个进程 tasklist | findstr mysqld 

5.杀死进程 taskkill /f /pid    111111

6.mysql 5.6管理员密码的设置

1.知道原始密码

  • 1.1登录到mysql 执行更新语句来修改:
# 在MySQL下写SQL语句,注意末尾加分号

1.先use mysql之后;
2.再输入 update user  set password = password("123") where host="localhost" and  user="root";

3.刷新全新 flush privileges;   
3.或者重启mysqld;() 
  • 2.2 mysqladmin小工具:
# 在cmd中输入不需要加分号

1.mysqladmin -uroot -p123 password 321

2.注意:-p是原始密码   

**2.不知道原始密码 **

  • 2.1删除权限相关的文件 (容易挨打)

  • 2.2 跳过授权表:

# 1.手动启动mysqld 指定参数   
在cmd中输入  mysqld --skip-grant-tables

# 2.开启一个客户端
在mysql中输入 use mysql;
再输入update user  set password = password("111") where host="localhost" and  user="root";

# 3.重启mysqld 即可 

7.库和表的增删改查

1.数据必须存在表(文件)中,表必须存在库(文件夹)中

1.库的操作

  • 1.不区分大小写
  • 2.不要使用关键字 例如create select 等.....
  • 3.不能使用纯数字
  • 4.可以下滑线 通常字符下滑线数字的组合
# 均在MySQL中输入SQL语句(注意加分号)

# 1.切换数据库(可以在库中切换到其他库)
use 数据库名称(可以不加分号)

# 2.增加库
create database 数据库名称 charset urf8   /*创建库*/;

# 3.查看所有数据库
show databases   #查看有哪些库;

# 4.查看数据客详细信息
show create database 数据库名称  -- 查看mydb库的详细信息;

# 5.删除数据库
drop database 数据库名称



# 6.修改数据库编码  可以进入到数据库文件夹中修改db.opt  
#  第一行是编码 第二行是排序规则 自己搜索一个

# 7.修改数据库名 可以直接修改对应的文件夹名称 

2.表的操作

# 1.查看当前库下的所有表
show tables  -- 需要先 use 库名 之后;

# 2.查看单个表的结构(内容)
desc 表名称;

# 3.查看表的创建语句(如何写的,我们要注意的规范)
show create table 表名称;

# 4.创建表(注意列的数据类型有char、text、int...但是没有str/string类型)
create table 表名称(列名称1 列1的数据类型, 列名称2 列2的数据类型,...) charset gbk;

# 5.修改表的名称
rename table 旧名称 to 新名称;

# 6.修改表的编码
alter table 表名 charset utf8 -- 注意:在MySQL中只能写'utf8',别写‘utf-8'; 

# 7.删除表
drop table 名称;

# 8.修改表的结构(内容)
## 8.1 添加字段(列)
alter table 表名 add 列名 数据类型:
## 8.2 删除字段(列)
alter table 表名 drop 列名:
## 8.3 修改字段(列)的数据类型
alter table 表名 modify 列名 新的数据类型:
## 8.4 修改字段(列)名、数据类型
alter table 表名 change 旧列名 新列名 新数据类型:

# 9.清空表数据
truncate table 表名;

3.注释

# 1.#注释内容
show databases #注释内容;

# 2.-- 注释内容(注意--后面必须空一格)
show databases -- 注释内容;

# 3./*注释内容*/
show databases /*注释内容*/;
原文地址:https://www.cnblogs.com/itboy-newking/p/11185368.html