第一部分 必答题
简述 OSI 7层模型及其作用?(2分)
应用层 表示层 会话层 传输层 :端口 ,TCP,UDP 四层交换机,四层路由器 网络层 :ip,路由器,三层交换机 数据链路层 :mac,arp协议,网卡,二层交换机 物理层
简述 TCP三次握手、四次回收的流程。(3分)
三次握手: 1、客户端将标志位SYN置为1,随机产生一个seq=j的值,将该值发送给服务端,客户端进入等待状态 2、服务端收到标志位SYN=1的值之后,服务端将标志位和ACK都置为1,随机产生一个ack=j+1的值返回给客户端, 3、客户端收到服务端发送过来的ack数据,检查是否与自己的数值相符,如果一致则正确建立连接,客户端和服务端完成通信,开始传输数据 四次挥手: 1、当客户端向服务端发送断开请求之后,这时会发出一个fin标记的报文 2、当服务端收到客户端fin报文之后,可能正在处理数据,此时服务端会给客户端返回一个ack的报文, 3、当服务端处理完成数据之后,会再次向客户端发送fin报文,表示此时可以断开连接 4、客户端收到服务端fin报文之后,会向服务端发送ack报文,客户端收到之后正是断开连接
TCP和UDP的区别?(3分)
TCP:上传/下载/发邮件,可靠,面向连接,速度慢,传输数据的长度不限 1、必须要先建立连接,三次握手 2、消息传递 可靠传输 3、断开连接 四次挥手 UDP:即时通讯,不可靠,面向数据报,速度快,能传输的数据长度有限 1、不管对方在不在线,都可以直接发送 2、不占连接 3、随时可以收发消息
什么是黏包?(2分)
当多条消息在发送之后接收之后变成了一条或者出现接收不准确的情况 本质是发送的数据之间没有边界
什么 B/S 和 C/S 架构?(2分)
B/S:指浏览器和服务端架构,只需要在浏览器输入网址就可以直接使用 C/S:指客户端和服务端
请实现一个简单的socket编程(客户端和服务端可以进行收发消息)(3分)
server: import socket sk = socket.socket() sk.bind(("127.0.0.1",9043)) sk.listen() conn,addr = sk.accept() conn.send(b'hi') msg = conn.recv(1024).decode("utf-8") print(msg) conn.close() sk.close()
client: import socket sk = socket.socket() sk.connect(("127.0.0.1",9043)) msg = sk.recv(1024).decode("utf-8") print(msg) sk.send("傻子".encode("utf-8")) sk.close()
简述进程、线程、协程的区别?(3分)
都可以提高并发能力 1、进程是计算机资源分配的最小单位 2、线程是计算机中能被cpu调度的最小资源单位 3、协程是程序员人为创建出来的 4、一个进程中可以有多个线程 5、同一个进程中的线程可以共享进程中的资源 6、一个进程中至少要有一个线程 7、协程又可以称为“微线程”,实际上是让一个线程轮番去执行一些任务 8、资源开销小,能够把单线程的效率提高,协程能够是别的io操作不如线程多 9、在Python中因为有GIL锁,同一时刻保证一个进程中只有一个线程可以被cpu调度,所以在使用python开发时计算密集型的代码使用多进程,IO密集型使用多线程 10、默认进程之间无法进行资源共享,如果主要想要通讯可以基于:文件/网络/Queue.
什么是GIL锁?(2分)
GIL锁被称为全局解释器锁,导致了CPython解释器下同一个进程下的多个线程不能利用多核优势,同一时刻保证一个进程中只有一个线程可以被cpu调度,所以在使用cpython开发时计算密集型代码使用多进程,io密集型使用多线程
进程之间如何进行通信?(2分)
进程之间数据是隔离的,意味着不能通信,但我们通过开发工具进行通信。主要是IPC机制
Python如何使用线程池、进程池?(2分)
python2中没有线程池,python3之后才提供了线程池 import time from concurrent.futures import ThreadPoolExecutor def task(arg1,arg2): time.sleep(0.2) print("任务") return arg1 + arg2 #创建线程 pool = ThreadPoolExecutor(10) future_lst = [] for i in range(10): #提交线程 fu = pool.submit(task,i,2) future_lst.append(fu) #等待线程执行 pool.shutdown(True) for fu in future_lst: print(fu.result())#result是固定的写法,阻塞方法
进程池 import time from concurrent.futures import ProcessPoolExecutor def task(n1,n2): time.sleep(0.2) print("开始任务") return n1 + n2 if __name__ == '__main__': future = [] #创建线程 pool = ProcessPoolExecutor(61)#实际测试这里最大填写的是61 ,加上主进程之后就是62,进程池最大就是63 for i in range(20): pool1 = pool.submit(task,i,1) future.append(pool1) pool.shutdown(True) print("结束") for fu in future: print(fu.result())
请通过yield关键字实现一个协程? (2分)
什么是异步非阻塞? (2分)
程序在执行任务的过程中调用另一个任务,并不等待当前任务结束就继续执行下一个任务
什么是死锁?如何避免?(2分)
锁两次或者多个锁交叉使用 避免多次交叉用锁,或者使用递归锁进行上锁
程序从flag a执行到falg b的时间大致是多少秒?(2分)
import threading import time def _wait(): time.sleep(60) # flag a t = threading.Thread(target=_wait) t.setDeamon(False) t.start() # flag b 0-1秒
程序从flag a执行到falg b的时间大致是多少秒?(2分)
import threading import time def _wait(): time.sleep(60) # flag a t = threading.Thread(target=_wait) t.setDeamon(True) t.start() # flag b 60秒
程序从flag a执行到falg b的时间大致是多少秒?(2分)
import threading import time def _wait(): time.sleep(60) # flag a t = threading.Thread(target=_wait) t.start() t.join() # flag b 60秒
读程序,请确认执行到最后number是否一定为0(2分)
import threading loop = int(1E7) def _add(loop:int = 1): global number for _ in range(loop): number += 1 def _sub(loop:int = 1): global number for _ in range(loop): number -= 1 number = 0 ta = threading.Thread(target=_add,args=(loop,)) ts = threading.Thread(target=_sub,args=(loop,)) ta.start() ta.join() ts.start() ts.join() 为0
读程序,请确认执行到最后number是否一定为0(2分)
import threading loop = int(1E7) def _add(loop:int = 1): global number for _ in range(loop): number += 1 def _sub(loop:int = 1): global number for _ in range(loop): number -= 1 number = 0 ta = threading.Thread(target=_add,args=(loop,)) ts = threading.Thread(target=_sub,args=(loop,)) ta.start() ts.start() ta.join() ts.join() 0
MySQL常见数据库引擎及区别?(3分)
innodb:索引+数据 表结构,持久化存储 myisam:索引,数据,表结构,支持持久化存储 memory:表结构
简述事务及其特性? (3分)
事务就是一组原子性的sql查询,或者说一个独立的工作单元 特性: 1、原子性:一个事物必须市委一个不可分割的最小工作单元,整个事务中的所有操作要么全部成功,要么全部失败回滚 2、一致性:数据库总数从一个一致性的状态转换成另一个一致性的状态 3、隔离性:一个事物所做的修改在最终提交一千,对其他事务是不可见的 4、持久性:一旦失误提交,择期所做的修改就会永久保存在数据库中,
事务的隔离级别?(2分)
读未提交 不可重复度 可重复读 串行化
char和varchar的区别?(2分)
char 0-255字节 定长字符串 varchar 0-65535字节 变长字符串
mysql中varchar与char的区别以及varchar(50)中的50代表的含义。(2分)
50表示最长字节长度为50
MySQL中delete和truncate的区别?(2分)
delete 表示清空表数据但不重置自增字段的设置 truncate 清空表数据且重置自增字段的设置
where子句中有a,b,c三个查询条件, 创建一个组合索引abc(a,b,c),以下哪种会命中索引(3分)
(a) (b) (c) (a,b) (b,c) (a,c) (a,b,c)
组合索引遵循什么原则才能命中索引?(2分)
要服从最左前缀原则
列举MySQL常见的函数? (3分)
sum 求和 avg 求平均值 min 求最小值 count 计数 max 求最大数
MySQL数据库 导入、导出命令有哪些? (2分)
导入:mysql -h ip -u 账户名 -p密码 数据库名 < 文件路径 导出:mysqldump -u root -p 数据库名 > 文件路径
什么是SQL注入?(2分)
注释之后的代码
简述left join和inner join的区别?(2分)
left join 左外连接,显示左边表的全部数据 inner join 内连接, 所有不在条件匹配内的数据们都会被剔除连表
SQL语句中having的作用?(2分)
过滤筛选 优先级:from > where > group by> select > distinct> having>order by >limit
MySQL数据库中varchar和text最多能存储多少个字符?(2分)
varchar 65535字节 text:65535 长文本数据
MySQL的索引方式有几种?(3分)
聚集索引 非聚集索引
什么时候索引会失效?(有索引但无法命中索引)(3分)
不能从使用了范围的条件开始之后的索引都失效
数据库优化方案?(3分)
分析sql,优化sql语句 选择合适的引擎存储 建立索引 优化表结构:水平分表和垂直分表,减少表的关联
什么是MySQL慢日志?(2分)
记录sql语句中超过设定的时间阈值的查询语句。
设计表,关系如下: 教师, 班级, 学生, 科室。(4分)
科室与教师为一对多关系, 教师与班级为多对多关系, 班级与学生为一对多关系, 科室中需体现层级关系。1. 写出各张表的逻辑字段 2. 根据上述关系表 a.查询教师id=1的学生数 b.查询科室id=3的下级部门数 c.查询所带学生最多的教师的id
有staff表,字段为主键Sid,姓名Sname,性别Sex(值为"男"或"女"),课程表Course,字段为主键Cid,课程名称Cname,关系表SC_Relation,字段为Student表主键Sid和Course表主键Cid,组成联合主键,请用SQL查询语句写出查询所有选"计算机"课程的男士的姓名。(3分)
根据表关系写SQL语句(10分)
查询所有同学的学号、姓名、选课数、总成绩;
select student.name,student.sid,sum(number) from score
查询姓“李”的老师的个数;
select count(id) from teacher where tname like '李%';
查询平均成绩大于60分的同学的学号和平均成绩;
select avg(number),student_id from score group by student_id having avg(number)>60;
查询有课程成绩小于60分的同学的学号、姓名
select distinct student.sname,score.student_id from student inner join score on student.sid = student_id where num<60;
删除学习“叶平”老师课的score表记录;
查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分;
查询每门课程被选修的学生数;
查询出只选修了一门课程的全部学生的学号和姓名;
查询选修“杨艳”老师所授课程的学生中,成绩最高的学生姓名及其成绩;
查询两门以上不及格课程的同学的学号及其平均成绩;