数据库三大范式是什么
-https://zhuanlan.zhihu.com/p/618012849
-# 第一范式:1NF 是指数据库表的每一列都是不可分割
-每列的值具有原子性,不可再分割。
-每个字段的值都只能是单一值
-# 第二范式(2NF)是在第一范式(1NF)的基础上建立起来得,满足第二范式(2NF)必须先满足第一范式(1NF)
如果表是单主键,那么主键以外的列必须完全依赖于主键,其它列需要跟主键有关系
如果表是复合主键,那么主键以外的列必须完全依赖于主键,不能仅依赖主键的一部分。
-# 第三范式(3NF)是在第二范式的基础上建立起来的,即满足第三范式必须要先满足第二范式
第三范式(3NF)要求:表中的非主键列必须和主键直接相关而不能间接相关;也就是说:非主键列之间不能相关依赖
不存在传递依赖
mysql有哪些索引类型,分别有什么作用
https://blog.csdn.net/ghost_hell/article/details/119822128
-主键索引(聚簇索引)---》主键,表不建立主键,也会有个隐藏字段是主键,是主键索引,mysql是基于主键索引构建的b+树,如果没有主键,如果按主键搜索,速度是最快的---》一定会有主键索引
-辅助索引(普通索引)-->咱们给某个自己加索引,django index=True,通过该字段查询,会提高速度,如果字段 变化小(性别,年龄),不要建立普通索引
-CREATE INDEX index_id ON tb_student(id);
-唯一索引(unique)
-不是为了提高访问速度,而是为了避免数据出现重复
-唯一索引通常使用 UNIQUE 关键字
-CREATE UNIQUE INDEX index_id ON tb_student(id);
-组合索引(联合索引)
-django 中:class Meta:
-CREATE INDEX index_name
ON table_name (column1, column2, column3);
-全文索引-->基本不用---》
全文索引主要用来查找文本中的关键字,只能在 CHAR、VARCHAR 或 TEXT 类型的列上创建。
在 MySQL 中只有 MyISAM 存储引擎支持全文索引。
全文索引允许在索引列中插入重复值和空值。
不过对于大容量的数据表,生成全文索引非常消耗时间和硬盘空间。
创建全文索引使用 FULLTEXT 关键字
3 事务的特性和隔离级别
-https://www.cnblogs.com/liuqingzheng/p/16480047.html
# 事务四大特性(ACID)
原子性(Atomicity):数据库把“要么全做,要么全部做”的这种规则称为原子性
隔离性(Isolation):事务之间相互隔离,不受影响,这与事务的隔离级别密切相关
-事务隔离级别
一致性(Consistency):事务执行前后的状态要一致,可理解为数据一致性
持久性(Durable):事务完成之后,她对数据的修改是永恒的,即时出现故障也能够正常保持
# 隔离级别---》为了保证四个特性的隔离性而有的
-Read uncommitted(读未提交)-ru :一个事物读到了另一个事务未提交的数据
-Read committed(读已提交)-rc:如果设置了这个级别一个事物读不到另一个事务未提交的数据
-写事务提交之前不允许其他事务的读操作
-Repeatable read(可重复读取)-rr:
-在开始读取数据(事务开启)时,不再允许修改操作,这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别
-Serializable(串行化):求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行
脏读---------
https://www.cnblogs.com/liuqingzheng/p/16480047.html
脏读指的是读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并一定最终存在的数据,这就是脏读
脏读就是读取到了不一定存在的的数据,比如事务A读取数据前,事务B更新了数据,事务A读取到了更新的数据,但是事务B又4回滚了,所以就出现了,读取到了数据库不存在的数据
不可重复读
不可重复读指的是在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据出现不一致的情况
解释:事物B多次读取数据,在事务B读取数据的过程中,事务A对数据进行了修改并提交了,导致事务B度的数据不一致
幻读---------解决了不可重复读的问题了
事务B查询时,没有这条数据,但是事务A插入了这条数据,当事务B插入这条数据时,发现插入不成功,主键冲突,就像幻觉一样
更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读
mysql5.7以后默认隔离级别是什么
REPEATABLE READ(可重复读)-RR-解决了脏读和不可重复读,存在幻读
##每个隔离级别解决了什么问题
Read uncommitted(读未提交)-ru:存在脏读,不可重复读,幻读
Read committed(读已提交)-rc: 解决了脏读,但存在不可重复读,幻读
Repeatable read(可重复读取)-rr:解决了不可重复读,但存在幻读
Serializable(串行化):解决了脏读,不可重复读和幻读问题,牺牲了效率
#Oracle仅支持两种隔离级别:
Read Committed:读已提交
Serializable:默认基本为RC 存在不可重复读问题
#查询隔离级别的命令:
mysql5.7及之后版本
show variables like 'transaction_isolation';
select @@transaction_isolation;
mysql5.7之前版本
show variables like 'tx_isolation';
select @@tx_isolation;
什么是qps,tps,并发量,pv,uv
#QPS Queries Per Second
每秒查询率,一台服务器每秒能够响应的查询次数,每秒的响应请求数也即是最大吞吐能力。
如何估算自己项目的QPS?
#TPS Transactions Per Second
是每秒处理的事务数,包括一条消息入和一条消息出,加上一次用户数据库访问
TPS 的过程包括:客户端请求服务端、服务端内部处理、服务端返回客户端。
也就是事务数/秒。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数,
##并发数(并发度):
指系统同时能处理的请求数量,同样反应了系统的负载能力。这个数值可以分析机器1s内的访问日志数量来得到
系统同时处理的请求或事务数,可以直接理解为:系统同时处理的请求数量
QPS = 并发量 / 平均响应时间
并发量 = QPS * 平均响应时间
例如当前系统QPS为1w,每个请求的响应时间都是2s,那么并发量就是2w
##PV(Page View):
页面访问量,即页面浏览量或点击量,用户每次刷新即被计算一次。可以统计服务一天的访问日志得到。
#UV(Unique Visitor):
独立访客,统计1天内访问某站点的用户数。可以统计服务一天的访问日志并根据用户的唯一标识去重得到。
#响应时间(RT):
响应时间是指系统对请求作出响应的时间,一般取平均响应时间。可以通过Nginx、Apache之类的Web Server得到。
#DAU(日活)
DAU(Daily Active User),日活跃用户数量。常用于反映网站、app、网游的运营情况。
DAU通常统计一日(统计日)之内,登录或使用了某个产品的用户数(去除重复登录的用户),与UV概念相似
#MAU(月活)
MAU(Month Active User):月活跃用户数量,指网站、app等去重后的月活跃用户数量
什么是接口幂等性问题,如何解决?
接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。
解决方法:
https://zhuanlan.zhihu.com/p/345512692
https://blog.csdn.net/Weixiaohuai/article/details/114896111
-幂等:幂等(idempotent、idempotence)是一个数学与计算机学概念
-一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同
-接口幂等性:无论调用多少次,产生的效果是一样的
-get 获取数据天然幂等
-put 修改数据天然幂等
-修改库存(数字加减):不幂等
-delete 删除 天然幂等
-post 新增数据,会出现不幂等的情况,要把它做成幂等性的
#通过token 机制实现接口的幂等性,这是一种比较通用性的实现方法。
3.1客户端会先发送一个请求去获取 token,服务端会生成一个全局唯一的 ID 作为 token 保存在 redis 中,同时把这个 ID 返回给客户端
3.2客户端第二次调用业务请求的时候必须携带这个 token
3.3服务端会校验这个 token,如果校验成功,则执行业务,并删除 redis 中的 token
3.4如果校验失败,说明 redis 中已经没有对应的 token,则表示重复操作,直接返回指定的结果给客户端
#防重表 解决新增数据
使用订单号orderNo做为去重表的唯一索引,把唯一索引插入去重表,再进行业务操作,且他们在同一个事务中。这个保证了重复请求时,因为去重表有唯一约束,导致请求失败,避免了幂等问题。这里要注意的是,去重表和业务表应该在同一库中,这样就保证了在同一个事务,即使业务操作失败了,也会把去重表的数据回滚。这个很好的保证了数据一致性。
# 前端:
按钮只能点击一次
什么是gil锁,有什么作用
# 1 GIL:Global Interpreter Lock又称全局解释器锁。本质就是一个互斥锁,
# 2 保证了cpython进程中得每个线程必须获得这把锁才能执行,不获得不能执行
# 3 使得在同一进程内任何时刻仅有一个线程在执行
# 4 gil锁只针对于cpython解释器----》
-JPython
-PyPy
-CPython-JPython
-PyPy
-CPython
# 为什么要有gil锁?
-python是动态强类型语言,因为有垃圾回收机制,如果同一个进程下有多个线程同时在执行,垃圾回收是垃圾回收线程【同一个进程下变量是共享的】,该线程做垃圾回收时,如果其他线程在运行,就可能会出并发安全的问题【数据安全的问题】,由于当时,只有单核cup【即便开启多线程,同一时刻,也只有一个线程在运行】,作者就强行做了一个GIL锁,保证在一个进程内,同一时刻只有一个线程执行,目的是为了防止垃圾回收线程做垃圾回收时,出现数据紊乱问题,所以加了gil锁
-垃圾回收是垃圾回收线程,它在执行的时候,其他线程是不能执行的,而限于当时的条件,只有单核cpu,所以作者直接做了个GIL锁,保证一个进程内同一时刻只有一个线程在执行
python的垃圾回收机制是什么样的
-https://www.jianshu.com/p/52ab26890114
-什么是垃圾回收?
-编程语言在运行过程中会定义变量--->申请了内存空间---》后期变量不用了---》这个内存空间应该释放掉
-有些编程语言,这个操作,需要程序员自己做(c)
-像java,python,go这些语言,都自带垃圾回收机制,可以自动回收内存空间,gc机制
-不同语言垃圾回收的方式是不一样的,python是使用如下三种方式做gc,以引用计数为主,标记-清除和分代回收两个算法为辅
#引用计数:
每个对象都有一个引用次数的计数属性,如果对象被引用了,那这个数就会 加1,如果引用被删除,引用计数就会 减1,那么当该对象的引用计数为0时,就说明这个对象没有被使用,垃圾回收线程就会把它回收掉,释放内存
-有问题:循环引用问题---》回收不了
#标记清除
-解决引用计数无法回收循环引用的问题
-对象之间通过引用连在一起,节点就是各个对象,从一个根对象向下找对象,可以到达的标记为活动对象,不能到达的是非活动对象,而非活动对象就是需要被清除的
#分代回收
-分代回收是解决垃圾回收效率问题
-算法原理是Python把对象的生命周期分为三代,分别是第0代、第1代、第2代。每一代使用双向链表来标记这些对象。每一代链表都有总数阈值,当达到阈值的时候就会出发GC回收,将需要清除的清除掉,不需要清除的移到下一代。以此类推,第2代中的对象存活周期最长的对象
-python垃圾回收最核心是:引用计数----》标记清除解决引用计数的循环引用问题---》分代回收解决垃圾回收的效率问题
解释为什么计算密集型用多进程,io密集型用多线程
https://zhuanlan.zhihu.com/p/151855962
————————只针对于cpython解释器(其他语言,都开多线程即可,能够利用多核优势)
-计算是消耗cpu的:代码执行,算术,for都是计算
-io不消耗cpu:打开文件,写入文件,网络操作都是io
-如果遇到io,该线程会释放cpu的执行权限,cpu转而去执行别的线程
#什么计算密集型用多进程
-由于python有gil锁,开启多条线程,统一时刻,只能有一条线程在执行
-如果是计算密集型,开了多线程,同一时刻,只有一个线程在执行
-多核cpu,就会浪费多核优势
-如果是计算密集型,我们希望,多个核(cpu),都干活,同一个进程下绕不过gil锁
-所以我们开启多进程,gil锁只能锁住某个进程中得线程,开启多个进程,就能利用多核优势
#io密集型用多线程
-io密集型---》只要遇到io,就会释放cpu执行权限
-进程内开了多个io线程,线程多半都在等待,开启多进程是不能提高效率的,反而开启进程很耗费资源,所以使用多线程即可。
为什么有了gil锁还要互斥锁
-https://www.cnblogs.com/zx0524/p/17303467.html
#前提
1 GIL 本身就是大的互斥锁
2 同一个进程下,资源是共享的----》多条线程可以操作同一个变量
3 多个线程操作同一个变量,就会出现数据安全问题
4 临界区:指一段代码或一段程序片段,需要在同一时间只能被一个线程执行---》多个线程操作临界区,会出现并发安全问题
# 什么时候会释放gil锁?
-1 线程遇到io
-2 时间片轮转,时间片到了,就会自动切换
#解释
gil锁就是一个大的互斥锁,线程执行需要先去获得gil锁,然后执行,但是没办法控制gil锁什么时候释放,它也不能锁住共享数据,就会造成数据错乱,这就需要互斥锁,线程执行,加锁,一直到执行结束,释放锁,这样就可以保证数据的安全。举个例子:同一进程下,有两条线程,其中一条线程先抢到了gil锁,他开始执行,但是当它执行临界区时,遇到了io或者gil锁的时间片到了,释放掉gil锁,另一条线程获得gil锁,也去执行临界区代码,这样就造成了数据错乱,但是第一条线程加上个互斥锁,就算释放了gil锁,另一条线程也执行不了临界区代码。
#编译型语言和解释性语言都有哪些?
编译型:C语言、C++、Golang、Pascal(Delphi)、汇编
解释性:Python、JavaScript、PHP、Shell、MATLAB
#两者有什么区别
https://www.cnblogs.com/tsingke/p/12285650.html
#什么是互斥锁
-https://blog.csdn.net/weixin_48135624/article/details/115313703
对共享数据进行锁定,保证同一时刻只能有一个线程去操作。
注意: 互斥锁是多个线程一起去抢,抢到锁的线程先执行,没有抢到锁的线程需要等待,等互斥锁使用完释放后,其它等待的线程再去抢这个锁。
互斥锁的作用就是保证同一时刻只能有一个线程去操作共享数据,保证共享数据不会出现错误问题
使用互斥锁的好处确保某段关键代码只能由一个线程从头到尾完整地去执行
使用互斥锁会影响代码的执行效率,多任务改成了单任务执行
互斥锁如果没有使用好容易出现死锁的情况
进程,线程和协程
进程:是资源分配的最小单位,一个应用程序应用起来,至少需要一个进程,在进程管理器(资源管理器)中可以看到一个个进程
线程:是cpu调度,执行的最小单位,一个进程下至少有一个线程
协程:单线程下的并发,程序层面控制的任务切换
#####如果具体使用
# 开启多进程两种方式
-1 写一个类,继承Process,重写类的run方法---》实例化得到对象,对象.start 开启了进程
-2 通过Process类实例化得到一个对象,传入任务 ,调用对象.start 开启了进程
# 开启线程两种方式
-1 写一个类,继承Thread,重写类的run方法---》实例化得到对象,对象.start 开启了进程
-2 通过Thread类实例化得到一个对象,传入任务 ,调用对象.start 开启了进程
# 开启协程
- 早期之前:借助于第三方gevent,基于greelet写的
- async 和 await 关键字,不借助于第三方,开启协程 asyncio 包
-必须写在一个函数前, async def task()----》这个函数执行的结果是协程函数
-await 只要是io操作的代码,前面必须加 await
async def task1():
a+=1
time.sleep()
a+=10
async def task2():
a+=2
await 遇到io
a+=20
# 什么场景用过
-我一般遇到计算密集型的操作,我会开多进程,io密集型的操作,我一般开多线程
-闲来无事,爬别人数据,喜欢开多线程,爬虫io居多
-程序中,异步做一件事情,也可以开多线程
比如一个视图函数,异步的吧数据写的文件中
异步的发送钉钉通知
异步的发送邮件
-但实际上,在项目中,不需要我们开启进程线程,可以借助于第三方的框架比如celery就可以做异步的操作
而celery的worker,就是进程线程架构
-django框架,是支持并发,我们没有开启多进程和多线程,但是符合uwsgi的web服务器在进入djagno框架之前,开启了进程和线程来执行视图函数
# 拓展
不同进程下,资源是隔离的
进程间通信:IPC 机制
-消息队列
什么是鸭子类型
走路像鸭子,说话像鸭子,我们就可以叫它鸭子
解释:鸭子类型是Python面向对象中描述接口的一个概念,区分与其他编程语言
eg:
java中:实现接口,必须显示继承一个接口
Python中:实现接口,遵循鸭子类型,不需要显示的继承一个接口(类),只要类中有对应的属性跟方法,我们就称这几个类的对象为同一种类型
# 鸭子类型是python语言面向对象中的一个概念
#面向对象三大特性
-继承
-封装
-多态
# 多态和多态性?
-多态同一类事物的多种形态
# 现实生活中
-水:冰,水,水蒸气
-动物:人,狗,猫,猪
# 程序中
-Animal类:子类人,子类狗,子类猫
-多态性:不考虑对象具体类型的情况下使用对象
# 程序中
-len()内置函数---》传参数:字符串对象,列表对象,字典对象
-len(字典)
# 为什么能这样用?就是因为多态的存在
字符串,列表,字典----》属于同一类事物---》有长度的这一类事物
#1 什么是猴子补丁,有什么用途
https://geek-docs.com/python/python-ask-answer/316_python_what_is_monkey_patching-2.html
猴子补丁是一种在运行时修改代码的技术。它允许开发人员在不修改原始代码的情况下,动态地添加、修改或删除类的属性和方法。
#2 什么是反射,python中如何使用反射
https://blog.csdn.net/qq_41775769/article/details/113527799
反射:通过字符串的形式操作对象相关的属性
python中是利用四种方法实现反射:hasattr,getattr,setattr,delattr
#3 http和https的区别
http是互联网上应用很广泛的一种应用层协议,就是一种发布和接收 HTML 页面的方法,被用于在 Web 浏览器和网站服务器之间传递信息。
https:超文本传输安全协议,是一种透过计算机网络进行安全通信的传输协议,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。
#区别
HTTP 明文传输,数据都是未加密的,安全性较差,HTTPS(SSL+HTTP) 数据传输过程是加密的,安全性较好。
使用 HTTPS 协议需要到 CA(Certificate Authority,数字证书认证机构) 申请证书,一般免费证书较少,因而需要一定费用。证书颁发机构如:Symantec、Comodo、GoDaddy 和 GlobalSign 等。
HTTP 页面响应速度比 HTTPS 快,主要是因为 HTTP 使用 TCP 三次握手建立连接,客户端和服务器需要交换 3 个包,而 HTTPS除了 TCP 的三个包,还要加上 ssl 握手需要的 9 个包,所以HTTP 页面响应速度比 HTTPS 快。
http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
HTTPS 其实就是建立在 SSL/TLS 之上的 HTTP 协议,所以,要比较 HTTPS 比 HTTP 要更耗费服务器资源。
标签:面试题,gil,事务,线程,进程,执行,主键
From: https://www.cnblogs.com/zxjwt/p/17604531.html