网络并发 数据库可能的面试题
TCP 协议下的 socket 通信
TCP UDP 的区别
三次握手 四次挥手
七层协议
粘包 (方案)
什么是进程 , 什么是线程 二者的区别
阻塞 和非阻塞
守护进程和守护线程的区别
GIL 锁(重点)
为什么在有 GIL 锁的情况下,还要使用普通锁
SQL 语句
事务四大特性
pymysql
线程池 进程池
简述OSI七层协议
- 为了实现计算机系统的互连,OSI参考模型把整个网络的通信功能划分为7个层次,同时也定义了层次之间的相互关系以及各层所包括的服务及每层的功能。OSI的七层由低到高依次为:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层,下三层(物理层、数据链路层、网络层)面向数据通信,而上三层(会话层、表示层、应用层)则面向资源子网,而传输层则是七层中最为重要的一层。它位于上层和下层中间,起承上启下的作用。
什么是C/S和B/S架构
- C/S 架构是一种典型的两层架构,其全称是Client/Server,即客户端服务器端架构,其客户端包含一个或多个在用户的电脑上运行的程序,而服务器端有两种,一种是数据库服务器端,客户端通过数据库连接访问服务器端的数据;另一种是Socket服务器端,服务器端的程序通过Socket与客户端的程序通信。
- B/S架构的全称为Browser/Server,即浏览器/服务器结构。Browser指的是Web浏览器,极少数事务逻辑在前端实现,但主要事务逻辑在服务器端实现,Browser客户端,WebApp服务器端和DB端构成所谓的三层架构。B/S架构的系统无须特别安装,只有Web浏览器即可
简述TCP三次握手,四次挥手的流程。
-
三次握手
- 第一次握手:客户端的应用进程主动打开,并向客户端发出请求报文段。其首部中:SYN=1,seq=x。
- 第二次握手:服务器应用进程被动打开。若同意客户端的请求,则发回确认报文,其首部中:SYN=1,ACK=1,ack=x+1,seq=y。
- 第三次握手:客户端收到确认报文之后,通知上层应用进程连接已建立,并向服务器发出确认报文,其首部:ACK=1,ack=y+1。当服务器收到客户端的确认报文之后,也通知其上层应用进程连接已建立。
-
四次挥手
- 第一次挥手:数据传输结束以后,客户端的应用进程发出连接释放报文段,并停止发送数据,其首部:FIN=1,seq=u。
- 服务器端收到连接释放报文段之后,发出确认报文,其首部:ack=u+1,seq=v。此时本次连接就进入了半关闭状态,客户端不再向服务器发送数据。而服务器端仍会继续发送。
- 第三次挥手:若服务器已经没有要向客户端发送的数据,其应用进程就通知服务器释放TCP连接。这个阶段服务器所发出的最后一个报文的首部应为:FIN=1,ACK=1,seq=w,ack=u+1。
- 第四次挥手:客户端收到连接释放报文段之后,必须发出确认:ACK=1,seq=u+1,ack=w+1。 再经过2MSL(最长报文端寿命)后,本次TCP连接真正结束,通信双方完成了他们的告别。
如果已经建立了TCP连接,但是客户端突然出现故障了怎么办
- TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
什么是arp协议
- ARP全称“Address Resolution Protocol”,地址解析协议。
- 实现局域网内通过IP地址获取主机的MAC地址。
- MAC地址48位主机的物理地址,局域网内唯一。
- ARP协议类似DNS服务,但不需要配置服务。
- ARP协议是三层协议。
TCP和UDP的区别
- TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
- TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
- UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
- 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
- TCP对系统资源要求较多,UDP对系统资源要求较少。
为什么基于tcp协议的通信比基于udp协议的通信更可靠
- TCP是面向连接的传输协议,每次都需要建立一个可以相互信任的连接,中间有个三次握手过程。而UDP是面向无连接的传输协议,不需要建立安全的连接,
什么是局域网和广域网
- 局域网(Local Area Network),简称LAN,是指在某一区域内由多台计算机互联成的计算机组。“某一区域”指的是同一办公室、同一建筑物、同一公司和同一学校等,一般是方圆几千米以内。局域网可以实现文件管理、应用软件共享、打印机共享、扫描仪共享、工作组内的日程安排、电子邮件和传真通信服务等功能。局域网是封闭型的,可以由办公室内的两台计算机组成,也可以由一个公司内的上千台计算机组成。
- 广域网(Wide Area Network),简称WAN,是一种跨越大的、地域性的计算机网络的集合。通常跨越省、市,甚至一个国家。广域网包括大大小小不同的子网,子网可以是局域网,也可以是小型的广域网。
- 两者区别:
- 范围不同,广域网比局域网广
- 接口类型不同
- 速率不同
- 协议不同
什么是socket?简述基于tcp协议的socket通信流程?
- socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。
- 通信流程:
- 服务端创建一个ServerSocket对象,指定端口号,ServerSocket对象等待客户端的连接请求。
- 客户端创建一个Socket对象,指定主机地址和端口号,向服务端发出连接请求。
- 服务端接收到客户端的连接请求,建立一条TCP连接,再创建一个Socket对象与客户端的Socket对象进行通信。
- 服务端和客户端分别创建字节输入流和字节输出流,通过字节输入流获得对方发来的数据,通过字节输出流向对方发送数据。
- 当一方决定结束通信时,向对方发送结束信息;另一方接收到结束信息后,双方分别关闭各自的TCP连接。
- ServerSocket对象停止等待客户端的连接请求。
什么是粘包?出现粘包的原因?
- 粘包:多个数据包被连续存储于连续的缓存中,在对数据包进行读取时由于无法确定发生方的发送边界,而采用某一估测值大小来进行数据读出,若双方的size不一致时就会使指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。
- 出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能由接收方造成。
- 发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。
- 接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据。
发生粘包现象如何处理?
- 对于发送方引起的粘包现象,用户可通过编程设置来避免,TCP提供了强制数据立即传送的操作指令push,TCP软件收到该操作指令后,就立即将本段数据发送出去,而不必等待发送缓冲区满;
- 对于接收方引起的粘包,则可通过优化程序设计、精简接收进程工作量、提高接收进程优先级等措施,使其及时接收数据,从而尽量避免出现粘包现象;
- 由接收方控制,将一包数据按结构字段,人为控制分多次接收,然后合并,通过这种手段来避免粘包。
IO多路复用的作用?
- I/O多路复用是用于提升效率,单个进程可以同时监听多个网络连接IO。
- 与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。
什么是防火墙?防火墙的作用是什么?
- 在互联网上防火墙是一种非常有效的网络安全模型,通过它可以隔离风险区域(即Internet或有一定风险的网络)与安全区域(局域网)的连接,同时不会妨碍人们对风险区域的访问。所以它一般连接在核心交换机与外网之间。
- 防火墙的作用:
- 过滤进出网络的数据
- 管理进出访问网络的行为
- 封堵某些禁止业务
- 记录通过防火墙信息内容和活动
- 对网络攻击检测和告警
简述进程,线程,协程的区别以及应用场景?
- 区别:
- 线程是资源分配的单位
- 线程是操作系统调度的单位
- 进程切换需要的资源很大,效率很低
- 线程切换需要的资源一般,效率一般(在不考虑GIL的情况下
- 协程切换任务资源很小,效率高
- 多进程,多线程根据cpu核数不一样可能是并行的,但是协程是在一个线程中,所以是并发。)
- 应用场景
- 协程:当程序中存在大量不需要cpu的操作时,适用协程
- 计算密集型,用进程。IO密集型,用线程。
什么是 GIL 锁
- 即全局解释器锁,
- 一个时间点只有一个线程处于执行状态。
python中如何使用进程池和线程池
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import os,time,random
from multiprocessing import Pool
def task(n):
print('%s is runing' %os.getpid())
time.sleep(random.randint(1,3))
return n**2
if __name__ == '__main__':
# 多进程方式一
pool2=Pool()
pool2.map(task,range(10))
# 多进程方式二,下面这种多进程和多线程的用法一模一样
executor=ThreadPoolExecutor(max_workers=3)
futures=[]
for i in range(11):
future=executor.submit(task,i)
futures.append(future)
executor.shutdown(True)
print('+++>')
for future in futures:
print(future.result())
threading.local的作用
- 为每个线程创建一个独立的空间,使得线程对自己的空间中的数据进行操作(数据隔离)。
进程之间如何进行通信?
- 共享内存
- 通过mmap模块实现
- 信号
- 通过Queue队列
- 通过Pipe管道
- 通过socket
什么是并发和并行
- 并发:指应用能够交替执行不同的任务,其实并发有点类似于多线程的原理,多线程并非是同时执行多个任务,如果你开两个线程执行,就是在你几乎不可能察觉到的速度不断去切换这两个任务,已达到"同时执行效果",其实并不是的,只是计算机的速度太快,我们无法察觉到而已.
- 并行:指应用能够同时执行不同的任务,
- 并发是多个事件在同一时间段执行,并行是多个事件在统一时间点执行。
解释什么是异步非阻塞
- 同步和异步:
- 同步:就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。
- 异步:当一个异步过程调用发出后,调用者不会立刻得到结果。实际处理这个调用的部件是在调用发出后,通过状态、通知来通知调用者,或通过回调函数处理这个调用。
- 阻塞和非阻塞
- 阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。
- 非阻塞:指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。
- 阻塞,非阻塞:进程/线程要访问的数据是否就绪,进程/线程是否需要等待;
- 同步,异步:访问数据的方式,同步需要主动读写数据,在读写数据的过程中还是会阻塞;异步只需要I/O操作完成的通知,并不主动读写数据,由操作系统内核完成数据的读写。
路由器和交换机的区别
- 交换机是一种用于电信号转发的网络设备。路由器是链接因特网中各局域网和广域网的设备。
- 区别
- 交换机工作在第二层,数据链路层,路由器工作在第三层,网络层。
- 路由器提供防火墙服务。
- 传统交换机只能风格冲突域,不能分割广播域,二路由器可以分割广播域。
什么是域名解析
- 域名解析是把域名指向网站空间IP,让人们通过注册的域名可以方便地访问到网站一种服务。IP地址是网络上标识站点的数字地址,为方便记忆,采用域名来代替IP地址标识站点地址。域名解析就是域名到IP地址的转换过程。
如何修改本地hosts文件
- 进入c:\windows\system32\drivers\etc进行修改
生产者消费者模型的应用场景
- 说明
- 生产者只在仓库未满时进行生产,仓库满时生产者进程被阻塞;消费者只在仓库非空时进行消费,仓库为空时消费者进程被阻塞;
- 应用场景:处理数据比较消耗时间,线程独占,生产数据不需要即时的反馈等。比如说写入日志,将多线程产生的日志放在队列中,然后写入。
什么是cdn
- cdn全称是内容分发网络。其目的是让用户能够更快速的得到请求的数据。
- cdn就是用来加速的,他能让用户就近访问数据,这样就更更快的获取到需要的数据。
守护线程,守护进程是什么
- 主进程创建守护进程
- 守护进程会在主进程代码运行结束的情况下,立即挂掉。
- 守护进程本身就是一个子进程。
- 主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束,
- 守护线程
- 守护线程会在"该进程内所有非守护线程全部都运行完毕后,守护线程才会挂掉"。并不是主线程运行完毕后守护线程挂掉。这一点是和守护进程的区别之处!
- 守护线程守护的是:当前进程内所有的子线程!
- 主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。
简述多进程开发中join和deamon的区别
- join:当子线程调用join时,主线程会被阻塞,当子线程结束后,主线程才能继续执行。
- deamon:当子进程被设置为守护进程时,主进程结束,不管子进程是否执行完毕,都会随着主进程的结束而结束。
GIL锁对python性能的影响
- 会降低多线程的效率。可以说python就是个单线程的程序。
- 如何避免:
- 用多进程代替多线程
- 使用其他解释器
使用yield实现一个协程
def consumer():
r = ''
while True:
n = yield r
if n is None:
return
print('[CONSUMER] Consuming %s...' % n)
r = '200 OK'
def produce(c):
c.send(None)
n = 0
while n < 5:
n = n + 1
print('[PRODUCER] Producing %s...' % n)
r = c.send(n)
print('[PRODUCER] Consumer return: %s' % r)
c.close()
c = consumer()
produce(c)
使用async语法实现一个协程
import asyncio
import time
now = lambda : time.time()
async def hello():
print("hello")
await asyncio.sleep(2)
return "done"
start = now()
# 协程对象
h1 = hello()
h2 = hello()
h3 = hello()
# 创建一个事件loop
loop = asyncio.get_event_loop()
# 任务(task)对象
tasks = [
asyncio.ensure_future(h1),
asyncio.ensure_future(h2),
asyncio.ensure_future(h3),
]
# 将协程加入到事件循环loop
loop.run_until_complete(asyncio.wait(tasks))
for task in tasks:
print(task.result())
print(now()-start)
简述线程死锁是怎么造成的。如何避免?
- 死锁的产生原因?
- 系统资源的竞争
- 进程运行推进顺序不当
- 解决死锁
- 加锁顺序:线程按照一定的顺序加锁
- 加锁时限:线程尝试获取锁的时候加上一定的时限,超过时限,则放弃对该锁的请求,并释放自己占有的锁。
- 死锁检测
什么是asyncio
- asyncio是并发的一种方式,是一个协程相关的库。也叫异步IO
什么是gevent
- gevent是一个pythn网络框架,它为各种并发和网络相关的任务提供了整洁的API
什么是twisted框架
- twisted是用python实现的基于事件驱动的网络引擎框架。
什么是LVS
- LVS是linux虚拟服务器,是一个虚拟的linux集群系统。
什么是Nginx
- nginx是一个高性能的HTTP和反向代理服务,也是一个IMAP/POP3/SMTP服务
什么是keepalived
- Keepalived是Linux下一个轻量级别的高可用解决方案
什么是haproxy?
- HAProxy是一个使用C语言编写的自由及开放源代码软件,其提供高可用性、负载均衡,以及基于TCP和HTTP的应用程序代理
什么是负载均衡
- 负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。
- 负载均衡其意思就是分摊到多个操作单元上进行执行。
什么是rpc
远程过程调用 (RPC) 是一种协议,程序可使用这种协议向网络中的另一台计算机上的程序请求服务
1.RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。
2.首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。
3.在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结 果,发送答复信息,然后等待下一个调用信息.
4.最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。
什么是正向代理和反向代理?
- 正向代理
- 正向代理类似一个跳板机,代理访问外部资源。
- 正向代理 是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。
- 正向代理作用:
- 访问原来无法访问的资源,如google
- 可以做缓存,加速访问资源
- 对客户端访问授权,上网进行认证
- 代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息
- 反向代理
- 反向代理(Reverse Proxy)实际运行方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器
- 反向代理的作用:
- 保证内网的安全,可以使用反向代理提供WAF功能,阻止web攻击
- 负载均衡,通过反向代理服务器来优化网站的负载
列举常见的关系型数据库和非关系型数据库。
- 关系型数据库:Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL
- 非关系型数据库:mongodb,redis,elasticsearch,NoSql
Mysql常见数据库引擎及区别
- InnoDB:用于事务处理应用程序,具有众多特性,包括ACID事务支持。(提供行级锁)
- MyISAM:默认的MySQL插件式存储引擎,它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。注意,通过更改STORAGE_ENGINE配置变量,能够方便地更改MySQL服务器的默认存储引擎。
- Memory:将所有数据保存再RAM中
简述事务及其特性
- 事务是用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位
- 事务具有4个特性:原子性、一致性、隔离性和持续性。
- 原子性:事务是数据库的逻辑工作单位,事务中包括的诸操作要么都做,要么都不做。
- 一致性:事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。
- 隔离性:一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对其他并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持续性:持续性也称永久性,指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其执行结果有任何影响。
简述触发器、函数、视图和存储过程
- 触发器:触发器是一个特殊的存储过程,它是MySQL在insert、update、delete的时候自动执行的代码块
- 函数:MySQL中提供了许多内置函数,还可以自定义函数(实现程序员需要sql逻辑处理)
- 视图:视图是由查询结果形成的一张虚拟表,是表通过某种运算得到的一个投影
- 存储过程:把一段代码封装起来,当要执行这一段代码的时候,可以通过调用该存储过程来实现(经过第一次编译后再次调用不需要再次编译,比一个个执行sql语句效率高)
mysql索引种类
- 普通索引:仅加速查询
- 唯一索引:加速查询 + 列值唯一(可以有null)
- 主键索引:加速查询 + 列值唯一(不可以有null)+ 表中只有一个
- 组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并
- 全文索引:对文本的内容进行分词,进行搜索
索引再什么情况下遵循最左前缀的规则?
- 在多字段进行索引的时候,会遵循以上原则
Mysql常见的函数
- ABS(x):返回x的绝对值
- ROUND(x):返回参数x的四舍五入的一个整数
- TRIM(str):去除字符串两边的空白
- COUNT():返回值的个数
- AVG():返回平均值
- SUM():求和
列举创建索引但是无法命中索引的情况
- 如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
- 对于多列索引,不是使用的第一部分(第一个),则不会使用索引
- like查询是以%开头
- 如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
- 如果mysql估计使用全表扫描要比使用索引快,则不使用索引
数据库的导入与导出命令
- 导出(mysqldump)
- 导出数据和表结构
- mysqldump -uroot -p dbname > dbname .sql
- 只导出表结构
- mysqldump -uroot -p -d dbname > dbname .sql
- 导出数据和表结构
- 导入
- mysql -u用户名 -p密码 数据库名 < 数据库名.sql
你了解哪些数据库优化方案
- 减少数据访问-创建并正确使用索引
- 返回更少的数据
- 数据分页处理
- 只返回需要的字段
- 减少交互次数
- 使用存储过程
- 优化业务逻辑
- 减少服务器的cpu运算
- 使用绑定变量
- 合理使用排序
- 减少比较操作
- 大量复杂运算在客户端处理
- 利用更多资源
- 客户端多进程访问
- 数据库并行处理
char和varchar的区别
- 保存方式不一样
- char有固定的长度,而varchar属于可变长的字符类型
- char的效率比varchar高
MySQL执行计划的作用和使用方法
- 作用:用来进行查询分析,比如整个查询涉及多少防,使用哪些索引,运行时间等
- 使用方法:使用explain关键字,如explain select xxx from xxx;
为什么数据很大的时候使用limit offset分页时,越往后翻速度越慢,如何优化?
- 使用limit分页时,比如limit 10000,20的意思是扫描满足条件的10020行,扔掉前面的10000行,最后返回20行,问题就出在这,当数据量大的时候,大量时间花在了扫描上面了。
- 优化方法:
- 当一个数据库表过于庞大,LIMIT offset, length中的offset值过大,则SQL查询语句会非常缓慢,你需增加order by,并且order by字段需要建立索引。
- 如果使用子查询去优化LIMIT的话,则子查询必须是连续的,某种意义来讲,子查询不应该有where条件,where会过滤数据,使数据失去连续性
什么是索引合并
- 索引合并是把几个索引的范围扫描合并成一个索引。
- 索引合并的时候,会对索引进行并集,交集或者先交集再并集操作,以便合并成一个索引。
- 这些需要合并的索引只能是一个表的。不能对多表进行索引合并。
什么是覆盖索引
覆盖索引又可以称为索引覆盖。
- 解释一: 就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖。
- 解释二: 索引是高效找到行的一个方法,当能通过检索索引就可以读取想要的数据,那就不需要再到数据表中读取行了。如果一个索引包含了(或覆盖了)满足查询语句中字段与条件的数据就叫做覆盖索引。
- 解释三: 是非聚集组合索引的一种形式,它包括在查询里的Select、Join和Where子句用到的所有列(即建立索引的字段正好是覆盖查询语句[select子句]与查询条件[Where子句]中所涉及的字段,也即,索引包含了查询正在查找的所有数据)。
简述数据库的读写分离
- 垂直切分
- 垂直分库:
- 就是根据业务耦合性,将关联度低的不同表存储在不同的数据库
- 垂直分表:
- 基于数据库中的"列"进行,某个表字段较多,可以新建一张扩展表,将不经常用或字段长度较大的字段拆分出去到扩展表中。
- 垂直分库:
- 横向切分:
- 水平切分分为库内分表和分库分表,是根据表内数据内在的逻辑关系,将同一个表按不同的条件分散到多个数据库或多个表中,每个表中只包含一部分数据,从而使得单个表的数据量变小,达到分布式的效果。
数据库锁的作用
- 锁分为三种:乐观锁,悲观锁和共享锁
- 数据库和操作系统一样,是一个多用户使用的共享资源。当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。加锁是实现数据库并 发控制的一个非常重要的技术。在实际应用中经常会遇到的与锁相关的异常情况,当两个事务需要一组有冲突的锁,而不能将事务继续下去的话,就会出现死锁,严 重影响应用的正常执行。
MySQL的半同步复制原理
- 半同步复制,介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制牺牲了一定的性能,提高了数据的安全性。
- 异步复制,MySQL默认的复制是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理。原理最简单,性能最好,但是主从之间数据不一致的概率很大。
- 全同步复制,指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
MySQL的增删改查
- 增
- 指定字段名
- 语法:INSERT INTO 表名(字段名1,字段名2,…)VALUES(值1,值2,…);
- 举例:INSERT INTO student(id,name,grade) VALUES(1,'zhangshan',98);
- 不指定字段名
- 语法:INSERT INTO 表名 VALUES(值11,值2,…);
- 举例:INSERT INTO student VALUES (2,'lisi',62);
- 其他写法
- 语法:INSERT INTO 表名 SET 字段名1=值1[,字段名2=值2,…]
- 举例:INSERT INTO student SET id=4,name='zhaoliu',grade=72;
- 同时添加多条数据
- 语法:INSERT INTO 表名[(字段名1,字段名2,…)] VALUES (值1,值2,…),(值1,值2,…),…(值1,值2,…)
- 举例:INSERT INTO student VALUES (5,‘lilei’,99), (6,'hanmeimei',87), (8,'poly',76);
- 指定字段名
- 删
- 删除部分数据
- 语法:DELETE FROM 表名 [WHERE 条件表达式]
- 命令:DELETE FROM student WHERE id=7;
- 删除全部数据
- 语法:DELETE FROM 表名
- 命令:DELETE FROM student;
- 推荐的删除全部数据
- 语法:TRUNCTE [TABLE ] 表名
- 举例:TRUNCATE TABLE student
- 删除部分数据
- 改
- 更新部分数据
- 语法:UPDATE 表名 SET 字段名1=值1,[ ,字段名2=值2,…] [ WHERE 条件表达式 ]
- 命令:UPDATE student SET name=‘caocao’,grade=50 WHERE id=1;
- 更新全部数据
- 语法:UPDATE 表名 SET 字段名=值
- 命令:UPDATE student SET grade=80;
- 更新部分数据
- 查
- 查询所有字段
- 语法:SELECT 字段名1,字段名2,… FROM 表名 (该语法也可以查询部分字段)
- 语法:SELECT * FROM 表名;
- 按条件查询
- 语法:SELECT 字段名1,字段名2,… FROM 表名 WHERE 条件表达式
- 命令:SELECT id,name FROM student2 WHERE id=4;
- 带IN关键字的查询
- 语法:SELECT * | 字段名1,字段名2,… FROM 表名 WHERE 字段名 [ NOT ] IN (元素1,元素2,…)
- 命令:SELECT * FROM student2 WHERE id IN (1,2,3);
- 带 BETWEEN AND 关键字的查询
- 语法:SELECT * | { 字段名1,字段名2,… } FROM 表名 WHERE 字段名 [ NOT ] BETWEEN 值1 AND 值2;
- 命令:SELECT id,name FROM students WHERE id BETWEEN 2 AND 5;
- 空值查询
- 语法:SELECT * | 字段名1,字段名2,… FROM 表名 WHERE 字段名 IS [ NOT ] NULL
- 命令:SELECT * FROM student2 WHERE gender IS NULL;
- 带 DISTINCT 关键字的查询
- 语法:SELECT DISTINCT 字段名 FROM 表名;
- 命令:SELECT DISTINCT gender FROM student2;
- 带 LIKE 关键字的查询
- 语法:SELECT * | 字段名1,字段名2,… FROM 表名 WHERE 字段名 [ NOT ] LIKE ‘匹配字符串’;
- 注意:%表示匹配任意长度的字符串,_表示匹配单个字符串
- 命令:SELECT id,name FROM student2 WHERE name LIKE "S%";
- 命令:SELECT id,name FROM student2 WHERE name LIKE 'w%g';
- 命令:SELECT id,name FROM student2 WHERE name NOT LIKE '%y%';
- 命令:SELECT * FROM student2 WHERE name LIKE 'wu_ong';
- 带 AND 关键字的多条件查询
- 语法:SELECT * | 字段名1,字段名2,… FROM 表名 WHERE 条件表达式1 AND 条件表达式2 [ … AND 条件表达式 n ];
- 命令:SELECT id,name FROM student2 WHERE id<5 AND gender='女';
- 带 OR 关键字的多条件查询
- 语法:SELECT * | 字段名1,字段名2,… FROM 表名 WHERE 条件表达式1 OR 条件表达式2 [ … OR 条件表达式 n ];
- 命令:SELECT id,name ,gender FROM student2 WHERE id<3 OR gender='女';
- AND和OR一起使用时,AND的优先级高于OR
- 聚合函数
- COUNT()函数:统计记录的条数
- 语法:SELECT COUNT() FROM 表名举例:
- 命令:SELECT COUNT() FROM student2; - SUM()函数:求出表中某个字段所有值的总和
- 语法:SELECT SUM(字段名) FROM 表名;
- 命令:SELECT SUM(grade) FROM student2; - AVG()函数:求出表中某个字段所有值的平均值
- 语法:SELECT AVG(字段名) FROM 表名;
- 命令:SELECT AVG(grade) FROM student2; - MAX()函数:求出表中某个字段所有值的最大值
- 语法:SELECT MAX(字段名) FROM 表名;
- 命令:SELECT MAX(grade) FROM student2; - MIN()函数:求出表中某个字段所有值的最小值
- 语法:SELECT MIN(字段名) FROM 表名;
- 命令:SELECT MIN(grade) FROM student2; - 对查询结果进行排序
- 语法:SELECT 字段名1,字段名2,… FROM 表名 ORDER BY 字段名1 [ ASC | DESC ],字段名2 [ ASC | DESC ]
- (升序)命令:SELECT * FROM student2 ORDER BY grade;
- (降序)命令:命令:SELECT * FROM student2 ORDER BY grade DESC;
- 分组查询
- 语法:SELECT 字段名1,字段名2,… FROM 表名 GROUP BY 字段名1,字段名2,… [ HAVING 条件表达式 ];
- 单独使用 GROUP BY 进行分组
- 命令:SELECT * FROM student2 GROUP BY gender; - GROUP BY 和聚合函数一起使用
- 命令:SELECT COUNT(*) ,gender FROM student2 GROUP BY gender; - GROUP BY 和 HAVING 关键字一起使用
- 命令:SELECT sum(grade),gender FROM student2 GROUP BY gender HAVING SUM(grade) < 300; - 使用 LIMIT 限制查询结果的数量
- 语法:SELECT 字段名2,字段名2,… FROM 表名 LIMIT [ OFFSET ,] 记录数
- (从0开始的4条)命令:SELECT * FROM student LIMIT 4;
- (从第五条开始的4条)命令:SELECT * FROM student2 ORDER BY grade DESC LIMIT 4,4;
- 为表和字段取别名
- 语法:SELECT * FROM 表名 [ AS ] 别名;
- 命令:SELECT * FROM student2 AS s WHERE s.gender='女';
- 为字段取别名
- 语法:SELECT 字段名 [ AS ] 别名 [ ,字段名 [AS] 别名,…] FROM 表名 ;
- 命令:SELECT name AS stu_name,gender AS stu_gender FROM student2;
- 查询所有字段
MySQL的建表语句
#创建表,例子
#所谓的建表就是声明列的过程,所以要首先分析列
create table member(
id int unsigned auto_increment primary key,
username varchar(20) not null default '',
gender char(1) not null default '',
weight tinyint unsigned not null default 0,
birth date not null default '0000-00-00',
salary decimal(8,2) not null default 0.00,
lastlogin int unsigned not null default 0
)engine myisam charset utf8;
MySQL如何创建索引
- ALTER TABLE
- ALTER TABLE用来创建普通索引、UNIQUE索引或PRIMARY KEY索引。
- ALTER TABLE table_name ADD INDEX index_name (column_list)
- ALTER TABLE table_name ADD UNIQUE (column_list)
- ALTER TABLE table_name ADD PRIMARY KEY (column_list)
- ALTER TABLE用来创建普通索引、UNIQUE索引或PRIMARY KEY索引。
- CREATE INDEX
- CREATE INDEX可对表增加普通索引或UNIQUE索引。
- CREATE INDEX index_name ON table_name (column_list)
- CREATE UNIQUE INDEX index_name ON table_name (column_list)
- CREATE INDEX可对表增加普通索引或UNIQUE索引。
简述SQL注入原理,以及如何在代码层面房子sql注入
通俗点讲,SQL注入的根本原因是: "用户输入数据"意外变成了代码被执行。 "用户输入数据"我这里可以指Web前端$_POST,$_GET获取的数据,也可以指从数据库获取的数据,当然也不排除程序猿无意中使用的特殊字符串。 在SQL语句的拼接中,一些含特殊字符的变量在拼接时破坏了SQL语句的结构,导致"用户输入数据"意外变成了代码被执行。
规避方法:
- 理语句法 (解析协议层面上完全规避SQL注入)
- 字符串转义(不要在sql中拼接字符) # query作为sql模板,args为将要传入的参数 execute(query, args=None)
使用python将数据库的student表中的数据写入db.txt
import pymysql
connect=pymysql.Connect(
host='',
port=,
user='',
passwd='',
db='',
charset='',
)
cursor=connect.cursor()
sql='select * from student'
cursor.execute(sql)
students=cursor.fetchall()
with open('db.txt','w') as f:
for student in students:
f.write(student)
cursor.close()
connect.close()
简述left join和right join的区别
- 左连接和右连接很相似,只是左右表位置的不同罢了。
- left join(左连接) 返回包括左表中的所有记录和右表中连接字段相等的记录
- right join(右连接) 返回包括右表中的所有记录和左表中连接字段相等的记录
索引有什么作用,有哪些分类,有什么好处和坏处?
- 作用:为了增加查询速度,提高系统性能
- 分类:
- 唯一索引:不允许其中任何两行具有相同索引值的索引。
- 非唯一索引:允许其中任何两行具有相同索引值的索引。
- 主键索引:有一列或列组合,其值唯一标识表中的每一行。
- 聚集索引:表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。
- 好处:
- 帮助用户提高查询速度
- 利用索引的唯一性来控制记录的唯一性
- 可以加速表与表之间的连接
- 降低查询中分组和排序的时间
- 坏处:
- 存储索引占用磁盘空间
- 执行数据修改操作(INSERT、UPDATE、DELETE)产生索引维护
mysql慢日志
- MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中。