数据库系统原理与实践 笔记 #12

文章目录

  • 数据库系统原理与实践 笔记 #12
  • 事务管理和并发控制与恢复(续)
    • 并发控制
      • SQL-92中的并发级别
      • 基于锁的协议
      • 基于锁的协议的隐患
      • 锁的授予
      • 封锁协议
      • 两阶段封锁协议
      • 多粒度
      • 粒度层次的例子
      • 意向锁类型
      • 相容性矩阵
      • 多粒度封锁模式
      • 基于时间戳的协议
      • 基于时间戳协议的正确性
      • 基于有效性检查的协议
      • 事务Ti的有效性检测
    • 恢复系统
      • 故障分类
      • 恢复机制
      • 数据访问
      • 恢复和原子性
      • 基于日志的恢复机制
      • 数据库修改
      • 事务提交
      • 并发控制和恢复
      • Undo和Redo操作
        • 事务的Undo和Redo
      • 从故障中恢复的Undo和Redo
        • 从故障中恢复时
      • 检查点

数据库系统原理与实践 笔记 #12

事务管理和并发控制与恢复(续)

并发控制

  • 数据库必须提供一种机制来保证所有调度(目标)是:
    • 冲突可串行化
    • 可恢复性,最好是无级联
  • 一个策略是一个时间只允许一个事务,即产生一个串行调度,但是并发性能差
  • 目标:建立一个能够保证串行化的并发控制协议

SQL-92中的并发级别

  • 可串行化(serializable)—通常保证可串行化的执行
  • 可重复读(repeatable read)—只允许读取已提交数据,一个事务对相同数据的重复读取要返回相同的值(其他事务不得更改该数据)
  • 已提交读(read committed)—(默认)只允许读取已提交的数据,但不要求可重复读
  • 未提交读(read uncommitted)—允许读取未提交数据
  • 以上所有隔离性级别都不允许脏写:即如果一个数据项已经被另外一个尚未提交或中止的事务写入,则不允许对该数据项执行写操作
  • 通过命令显式设置隔离性级别:
set transaction isolation level serializable

基于锁的协议

  • 是用来控制对数据项的并发访问的一种机制
  • 给数据加锁有两种方式:
    • 排他锁(X):对数据项即可写又可读,使用lock-X指令
    • 共享锁(S):对数据项只能读,使用lock-S指令
  • unlock指令释放锁
  • 申请锁请求发送给并发控制管理器,只有在并发控制管理器授予所需锁之后,事务才能继续其操作
  • 锁相容性矩阵
      表示为comp(A, B)
SX
Struefalse
Xfalsefalse
  • 指令之间的冲突对应于锁类型之间的不相容性

  • 如果被请求所与数据项上已有的锁相容,那么事务可以被授予该锁:

    • 一个数据项可以同时有多个共享锁
    • 如果一个事务在某个数据项上拥有排他锁,那么其他事物不能再在这个数据项上加任何锁
  • 如果一个锁不能被授予,那么请求该锁的事务必须等待,直到该数据项上的其他不相容锁全部释放,然后再授予锁

  • 事务执行锁的例子:
    T 2 : l o c k − S ( A ) ; r e a d ( A ) ; u n l o c k ( A ) ; l o c k − S ( B ) ; r e a d ( B ) ; u n l o c k ( B ) ; d i s p l a y ( A + B ) ; T_2:lock-S(A);\\ read(A); \\ unlock(A); \\ lock-S(B); \\ read(B);\\ unlock(B); \\ display(A+B); T2:lockS(A);read(A);unlock(A);lockS(B);read(B);unlock(B);display(A+B);

  • 上述锁无法有效地保证可串行化—如果A在read B的时候被其他事务更新了,那么最后的和将会是错误的答案

  • 需指定合理的封锁协议:一组规定事务何时对数据项进行加锁、解锁的规则。封锁协议限制了可能的调度数目

基于锁的协议的隐患

  • 考虑下面的调度:
    在这里插入图片描述

  • T 3 T_3 T3 T 4 T_4 T4都无法被处理—排他锁lock-S(B)导致 T 4 T_4 T4等待 T 3 T_3 T3释放其在B上的锁,而排他锁lock-X(A)导致 T 3 T_3 T3等待 T 4 T_4 T4释放其在A上的锁

  • 这样的情况称为死锁(deadlock):要处理 T 3 T_3 T3 T 4 T_4 T4其中一个死锁,必须回滚并释放锁

  • 大多数封锁协议都会产生死锁

  • 如果并发控制管理器设计得差也有可能导致饿死(starved)

  • 并发控制协议可以通过良好的设计,能够避免事务饿死

锁的授予

  • 避免事务饿死的授权加锁方式:当事务 T i T_i Ti申请对数据项Q加M型锁时,并发控制管理器授权加锁的条件需满足:
    • 1.不存在在数据项Q上持有与M型锁冲突的锁的其他事务
    • 2.不存在等待对数据项Q加锁且**先于 T i T_i Ti申请加锁的事务
  • 这样,一个加锁申请就不会被其后的加锁申请阻塞

封锁协议

  • { T 0 , T 1 , . . . , T n } \{T_0, T_1, ..., T_n\} {T0,T1,...,Tn}是参与调度S的一个事务集,如果存在数据项Q,使得 T i T_i Ti在Q上持有A型锁。后来, T j T_j Tj在Q上持有B型锁,且comp(A,B)=false,则我们称 T i T_i Ti先于 T j T_j Tj,记为 T i → T j T_i\rightarrow T_j TiTj
    • 如果 T i → T j T_i\rightarrow T_j TiTj,这一优先意味着在任何等价的串行调度中, T i T_i Ti必须出现在 T j T_j Tj之前
  • 如果调度S是那些遵从封锁协议规则的事务集的可能调度之一,我们称调度S在规定的封锁协议下是合法的
  • 一个封锁协议当且仅当其所有合法的调度为冲突可串行化时,我们称它保证冲突可串行性
  • 换句话说,对于任何合法的调度,其关联的事务优先关系是无循环

两阶段封锁协议

  • 这是一个能够保证冲突可串行化调度的协议
  • 阶段1:增长阶段
    • 事务可以获得锁
    • 事务不能释放锁
  • 阶段2:缩减阶段
    • 事务可以释放锁
    • 事务不能获得新锁
  • 封锁点:在调度中该事务获得其最后加锁的位置(增长阶段结束点)
  • 两阶段封锁协议保证可串行化:可以证明事务可以按照封锁点来排序(一种可串行化次序)
  • 两阶段封锁不能保证不发生死锁
  • 两阶段封锁下很有可能发生级联回滚
    • 为了避免这个问题,将该协议修改为严格两阶段封锁协议
  • 严格两阶段封锁协议要求未提交事务所写的热河数据在该事务提交之前均以排他方式加锁,防止其他事务读取这些数据
  • 强两阶段封锁协议更加严格:要求是提交之前不得释放任何锁(在这个协议下,事务可以按其提交顺序串行化

多粒度

  • 将多个数据聚成一组,作为同步单元,无需单独对单个数据项进行加锁
  • 多粒度:允许各种大小的数据项,并定义数据粒度的层次结构,可以图形化的表示为树
  • 如果一个事务显式地对树中的某个节点加了锁,那么它也给所有统一模式下的该节点的子节点隐式地加了锁
  • 锁的力度
    • 细粒度(树的低层):高并发性,锁开销多
    • 粗粒度(树的高层):低并发性,锁开销少

粒度层次的例子

  • 如事务 T i T_i Ti需判定某个节点(如 r b 1 r_{b_1} rb1)是否可以加锁,必须从根结点进行遍历至该节点(开销大)

在这里插入图片描述

意向锁类型

  • 除了排他锁及共享锁类型,多粒度下还有其他三种锁类型:
    • 共享型意向锁(IS):将在树的较低层进行显式封锁,但只能加共享锁
    • 排他型意向锁(IX):将在树的较低层进行显式封锁,可以加排他锁共享锁
    • 共享排他型意向锁(SIX):以该节点为根的子树显式地加了共享锁,并且在树的更底层显式地加排他锁
  • 意义:意向锁允许较高层的节点被加上共享锁或排他锁,而无需从树根遍历到子孙节点来检验锁的相容性,提升锁相容检验的效率

相容性矩阵

  • 所有所类型的相容性矩阵
    在这里插入图片描述

多粒度封锁模式

  • 事务 T i T_i Ti按如下规则对数据项Q加锁:
    • 1.必须遵从锁类型相容函数
    • 2.必须首先是封锁树的根节点,并且可以加任意类型的锁
    • 3.仅当事务 T i T_i Ti当前对Q的父节点具有IX或IS时,对结点Q可加S或IS锁
    • 4.仅当事务 T i T_i Ti当前对Q的父节点具有IX时,对节点Q可加X、SIX或IX锁
    • 5.仅当 T i T_i Ti未曾对任何节点解锁时, T i T_i Ti可对节点加锁(满足两阶段封锁)
    • 6.仅当 T i T_i Ti当前不持有Q的子节点的锁时, T i T_i Ti可对节点Q解锁
  • 加锁按自顶向下的顺序,锁的释放按自底向上的顺序

基于时间戳的协议

  • 对于系统中每个事务 T i T_i Ti,我们把一个唯一的固定时间戳和它联系起来,此时间戳记为 T S ( T i ) TS(T_i) TS(Ti);该时间戳是在事务 T i T_i Ti开始执行前由数据库系统赋予的。若事务 T i T_i Ti已被赋予时间戳 T S ( T i ) TS(T_i) TS(Ti),并且有一新事务 T j T_j Tj进入系统,则 T S ( T i ) < T S ( T j ) TS(T_i)<TS(T_j) TS(Ti)<TS(Tj)
  • 事务的时间戳决定了串行化顺序
  • 每个数据项Q需要与两个时间戳值相关联
    • W-timestamp(Q)表示成功执行write(Q) 的所有事务的最大时间戳
    • R-timestamp(Q)表示成功执行read(Q) 的所有事务的最大时间戳
  • 时间戳排序协议保证任何有冲突的readwrite操作按照时间戳顺序执行
  • 假设事务 T i T_i Ti发出指令read(Q)
    • 1.若 T S ( T i ) TS(T_i) TS(Ti) < W-timestamp(Q),则 T i T_i Ti需要读入的Q值已被覆盖:read操作被拒绝, T i T_i Ti回滚
    • 2.若 T S ( T i ) ≥ TS(T_i)\ge TS(Ti)W-timestamp(Q):执行read操作,R-timestamp(Q)被设置为max(R-timestamp(Q), T S ( T i ) TS(T_i) TS(Ti))
  • 假设事务 T i T_i Ti发出指令write(Q)
    • 1.若 T S ( T i ) TS(T_i) TS(Ti) < R-timestamp(Q),则 T i T_i Ti所需更新Q的值已过时:write操作被拒绝, T i T_i Ti回滚
    • 2.若 T S ( T i ) TS(T_i) TS(Ti) <W-timestamp(Q),则 T i T_i Ti试图写入的Q值已过时:write操作被拒绝, T i T_i Ti被饿死
    • 3.其他情况:执行write操作,将W-timestamp(Q)设置为 T S ( T i ) TS(T_i) TS(Ti)

基于时间戳协议的正确性

  • 时间戳排序协议保证冲突可串行化:冲突操作按时间戳的顺序来处理
  • 保证无死锁:不存在等待,可能有长事务饿死
  • 可能产生不可恢复的调度:事务可恢复性与事务提交顺序有关

基于有效性检查的协议

  • 有效性检查协议(适用于大部分只读事务的情况) 要求每个事务 T i T_i Ti在其生命周期中按两个或三个阶段执行:
    • 1.读阶段:事务 T i T_i Ti的所有write操作都是对局部临时变量进行的
    • 2.有效性检查阶段:事务 T i T_i Ti进行有效性检查,判断是否可以write操作而不违反可串行性
    • 3.写阶段:如果 T i T_i Ti已通过有效性检查,则保存任何写操作结果的临时局部变量值被复制到数据库中。只读事务不进入此阶段
  • 每个事务必须按照以上顺序经历这些过程。然而,并发执行的事务三个阶段可以是交叉执行
  • 每个事务 T i T_i Ti都有三个不同的时间戳:
    • Start( T i T_i Ti):事务 T i T_i Ti开始执行的时间
    • Validation( T i T_i Ti):事务 T i T_i Ti完成读阶段
  • 利用时间戳Validation( T i T_i Ti)的值,通过时间戳排序技术决定可串行化顺序,以增加并发性:即 T S ( T i ) = V a l i d a t i o n ( T i ) TS(T_i) = Validation(T_i) TS(Ti)=Validation(Ti)

事务Ti的有效性检测

  • 对于任何满足 T S ( T k ) < T S ( T i ) TS(T_k) <TS(T_i) TS(Tk)<TS(Ti)的事务 T k T_k Tk必须满足下面两条件之一
    • F i n i s h ( T k ) < S t a r t ( T i ) Finish(T_k) < Start(T_i) Finish(Tk)<Start(Ti)
    • S t a r t ( T i ) < F i n i s h ( T k ) < V a l i d a t i o n ( T i ) Start(T_i) < Finish(T_k) < Validation(T_i) Start(Ti)<Finish(Tk)<Validation(Ti)并且需保证 T k T_k Tk锁写的数据项集与 T i T_i Ti所读数据项集不想交;即 T k T_k Tk的写操作不会影响到 T i T_i Ti的读操作
  • 则有效性检测通过, T i T_i Ti可以进入写阶段并提交,否则测试失败 T i T_i Ti中止
  • 有效性检查协议能够自顶预防级联回滚,保证无死锁

恢复系统

故障分类

  • 事务故障
    • 逻辑错误:由于某些内部条件而无法继续正常执行
    • 系统错误:系统进入一种不良状态(如死锁),结果事务无法继续正常执行
  • 系统崩溃:硬件故障,或者是数据库软件或操作系统的漏洞,导致易失性存储器内容丢失,并使得事务处理停止
  • 磁盘故障:由于磁头损坏或故障造成磁盘块上的内容丢失:
    • 毁坏是可探测的:磁盘驱动器用校验和来检测故障

恢复机制

  • 保证数据库一致性以及事务的原子性的算法称为回复算法:
    • 正常事务处理时采取措施,保证有足够的信息可用于故障恢复
    • 故障发生后采取措施,将数据库内容恢复到某个保证数据库一致性、事件原子性及持久性的状态
  • 存储器类型:
    • 易失性存储器(volatile storage):易失性存储器中的信息在系统崩溃时通常无法保存下来
    • 非易失性存储器(nonvolatile storage):非易失性存储器中的信息在系统崩溃时可以保存下来
    • 稳定存储器(stable storage):稳定存储器中的信息永不丢失

数据访问

  • 物理块是位于磁盘上的块

  • 缓冲块是临时位于主存的块

  • 磁盘和主存间的块移动是由下面两个操作引发的:**input(B)**传送物理块B到主存,**output(B)**传送缓冲块B至硬盘,并替换磁盘上相应的物理块

  • 例子
    在这里插入图片描述

  • 每个事务 T i T_i Ti有一个私有工作区,用于保存 T i T_i Ti所访问及更新的所有数据项的拷贝: T i T_i Ti的工作区中保存的每一个数据项X记为 x i x_i xi

  • 使用下面两个操作里完成数据在工作区和系统缓冲区之间的传递:

    • read(X) 将数据项X的值赋予局部变量 x i x_i xi
    • write(X) 将局部变量 x i x_i xi的值赋予缓冲块中的数据项X
    • 注意: output( B x B_x Bx) 不需要立刻在write(X)后执行。系统会在它认为合适的时候执行output操作
  • 事务:必须在第一次访问X之前执行read(X);**write(X)**可以在事务被提交前的任意时刻执行

恢复和原子性

  • 为保证原子性,我们必须在修改数据库本身之前,首先向稳定存储器输出信息,描述要做的修改
  • 目的:确保由中止事务所做的修改不会持久保存与数据库中,即回滚该中止事务
  • 基于日志的恢复系统

基于日志的恢复机制

  • 日志保存于稳定存储器中:日志是日志记录的序列它记录数据库中的所有更新活动
  • 当一个事务 T i T_i Ti开始时,它记录 < T i   s t a r t > <T_i \ start> <Ti start>
  • 事务 T i T_i Ti执行write(X) 前,日志记录: < T i   X , V 1 , V 2 > <T_i\ X, V_1, V_2> <Ti X,V1,V2> V 1 V_1 V1是在write之前X的值(旧值), V 2 V_2 V2是需要写入X的值(新值)
  • T i T_i Ti结束了最后一条指令时, < T i   c o m m i t > <T_i\ commit> <Ti commit>写入日志
  • 当事 T i T_i Ti中止时,日志记录 < T i   a b o r t > <T_i\ abort> <Ti abort>
  • 使用日志的两种方法:延迟的数据库修改(事务提交后还未修改),立即的数据库修改(事务提交前已修改)

数据库修改

  • 立即修改模式允许在事务提交前,将未提交的事务更新至缓冲区或磁盘
  • 延迟修改模式直到事务提交时都没有更新到缓冲区/磁盘:简化了恢复,但是多了存储本地副本的开销
  • 日志记录的更新必须在数据项被write(数据库修改)之前完成

事务提交

  • 当事务将其关于提交的日志记录输出到稳定存储器时,该事务被认为已提交:之前的所有日志记录必须都已经输出
  • 事务提交时,由该事务执行的write操作结果可能仍在缓冲区,随后被输出

并发控制和恢复

  • 在并发事务中,所有事务共享一个磁盘缓冲区和日志:一个缓冲块中的数据项可以来自多个事务的更新
  • 假设如果一个事务 T i T_i Ti习概了一个数据项,那么在 T i T_i Ti提交前,其他事务不能修改同一个数据项(即不允许脏写):
    • 未提交事务的更新不能被其他事务所见
    • 可以通过在被更新数据项上获取排他锁,并持有该锁直到事务提交位置来保证(严格两阶段封锁
  • 不同事务的日志记录在日志中穿插(interspersed)存储

Undo和Redo操作

  • 对日志记录 < T i , X , V i , V 2 > <T_i, X, V_i, V_2> <Ti,X,Vi,V2>Undo操作将旧值 V 1 V_1 V1写入X
  • 对日志记录 < T i , X , V 1 , V 2 > <T_i, X, V_1, V_2> <Ti,X,V1,V2>Redo操作将新值 V 2 V_2 V2写入X
事务的Undo和Redo
  • undo( T i T_i Ti) 将事务 T i T_i Ti所更新的所有数据项的值恢复成旧值,回到 T i T_i Ti的最后一条日志记录:
    • 每次数据项X被恢复成旧值,日志记录 < T i , X , V > <T_i, X, V> <Ti,X,V>会被写入
    • 当事务的undo操作完成时,日志记录 < T i   a b o r t > <T_i \ abort> <Ti abort>被写入
  • redo( T i T_i Ti) 将事务 T i T_i Ti所更新的所有数据项的值置为新值,从 T i T_i Ti的第一条日志记录开始执行(这个情况下没有任何日志记录)

从故障中恢复的Undo和Redo

从故障中恢复时
  • 当日志是以下状态时,事务 T i T_i Ti需要undo操作:
    • 有日志 < T i   s t a r t > <T_i\ start> <Ti start>
    • 没有日志 < T i   c o m m i t > <T_i\ commit> <Ti commit> < T i   a b o r t > <T_i\ abort> <Ti abort>
  • 当日志是以下状态时,事务 T i T_i Ti需要进行redo操作:
    • 有日志 < T i   s t a r t > <T_i\ start> <Ti start>
    • 日志 < T i   c o m m i t > <T_i\ commit> <Ti commit> < T i   a b o r t > <T_i\ abort> <Ti abort>
  • 如果事务 T i T_i Ti之前执行了undo操作, < T i   a b o r t > <T_i\ abort> <Ti abort>被写入到日志,接着故障发生。为了从故障中恢复, T i T_i Ti要执行redo操作
  • 这样的redo操作重新执行了原先的所有操作,包括重新存储旧值:称为重复历史,看起来很浪费,但是最大程度地简化了恢复

检查点

  • 对于日志中的所有事务做Redo/Undo
    • 1.如果系统已经运行了很长一段时间,那么处理整个日志很浪费时间
    • 2.那些已经将输出更新到数据库的事务没必要redo
  • 流线型恢复过程周期性地执行检查点
    • 1.将当前位于主存的所有日志记录输出到稳定存储器上
    • 2.将所有修改了的缓冲块输出到磁盘上
    • 3.将一个日志记录 < c h e c k p o i n t   L > <checkpoint\ L> <checkpoint L>输出到稳定存储器
    • 执行检查点时,所有数据更新都停止
  • 恢复时,我们仅考虑在检查点前最近开始的事务 T i T_i Ti,及在 T i T_i Ti后开始的事务:
    • 从日志末尾反向扫描,找到最近的 < c h e c k p o i n t   L > <checkpoint\ L> <checkpoint L>记录
    • 只要在L未提交/中止的事务或者在检查点后开始的事务需要redo或undo
    • 检查点之前的已提交或者中止的事务已经将其更新输出到了稳定存储器
  • undo操作可能需要一些早期的日志
    • 继续从日志末尾反向扫描直到找到在L的每个事务 T i T_i Ti的记录 < T i   s t a r t > <T_i\ start> <Ti start>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/238309.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解决:TypeError: write() argument must be str, not Tag

解决&#xff1a;TypeError: write() argument must be str, not Tag 文章目录 解决&#xff1a;TypeError: write() argument must be str, not Tag背景报错问题报错翻译报错位置代码报错原因解决方法今天的分享就到此结束了 背景 在使用之前的代码时&#xff0c;报错&#xf…

如何轻松解决企业报修系统问题?有什么比较实用的工单管理系统?

许多企业报修方面的问题就是兼职师傅多&#xff0c;难以管理&#xff0c;导致整个报修流程都比较滞后。关于这个问题&#xff0c;我个人的建议是引入工单管理系统&#xff0c;依靠线上平台进行统一的管理。 引入工单管理系统的好处主要有&#xff1a;   1、沟通报修更加高效 …

频率、概率

频率 在相同的条件下进行试验&#xff0c;假设试验进行了次&#xff0c;其中随机事件A发生了次&#xff0c;那么就称为随机事件A发生的频率。 概率 假设随机试验E的样本空间是S&#xff0c;对于其中每个随机事件&#xff0c;都对应了一个实数&#xff0c;把这个实数称为随机…

Qt/C++音视频开发59-使用mdk-sdk组件/原qtav作者力作/性能凶残/超级跨平台

一、前言 最近一个月一直在研究mdk-sdk音视频组件&#xff0c;这个组件是原qtav作者的最新力作&#xff0c;提供了各种各样的示例demo&#xff0c;不仅限于支持C&#xff0c;其他各种比如java/flutter/web/android等全部支持&#xff0c;性能上也是杠杠的&#xff0c;目前大概…

力扣每日一题day34[110. 平衡二叉树]

给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;t…

Linux学习第46天:Linux音频驱动试验:能不能?不行也得行。

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 CAN 是目前应用非常广泛的现场总线之一&#xff0c;主要应用于汽车电子和工业领域&#xff0c;尤其是汽车 领域&#xff0c;汽车上大量的传感器与模块都是通过 C…

【SpringBoot篇】详解基于Redis实现短信登录的操作

文章目录 &#x1f970;前言&#x1f6f8;StringRedisTemplate&#x1f339;使用StringRedisTemplate⭐常用的方法 &#x1f6f8;为什么我们要使用Redis代替Session进行登录操作&#x1f386;具体使用✨编写拦截器✨配置拦截器&#x1f33a;基于Redis实现发送手机验证码操作&am…

DNSLog漏洞探测(三)之XSS漏洞实战

DNSLog漏洞探测(三)之XSS漏洞实战 通过前面的学习&#xff0c;我们已经明白了什么是DNSLog平台&#xff0c;那么DNSLog平台到底能为我们做些什么呢&#xff1f; DNSLog的平台实际使用很长见的一种情况就是针对漏洞无回显的情况&#xff0c;我们通过让受害者的服务器主动发起对…

Error: Failed to resolve vue/compiler-sfc——vite项目启动报错——npm run serve

运行项目时&#xff0c;报错如下&#xff1a; Error: Failed to resolve vue/compiler-sfc 根据报错信息的提示&#xff1a;vue的版本必须大于3.2.25&#xff0c;经过查看package.json文件&#xff0c;可以看到vue的版本为3.2.36&#xff0c;是满足条件的。 因此考虑缓存问题&…

Python部分基础知识入门学习,十分钟快速上手

文章目录 一、基础语法二、变量类型三、运算符四、条件语句关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼职渠道 一、…

并发编程的基本概念

进程与线程 进程 程序由指令和数据组成&#xff0c;但这些指令要运行&#xff0c;数据要读写&#xff0c;就必须将指令加载至 CPU&#xff0c;数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的当一个程序被运行&…

【计算机网络】UDP报文详解

目录 一. UDP协议概述 二. UDP报文格式 1. 首部 2. 校验和 三. UDP的缓冲区 结束语 一. UDP协议概述 UDP——用户数据报协议&#xff0c;是传输层的一个重要协议 基于UDP的应用层协议有&#xff1a;DNS&#xff0c;TFTP&#xff0c;SNMP&#xff0c;NTP 协议全称默认端…

pt34-python-Celery

Celery异步网络框架 定义 Celery 是一个简单、灵活且可靠的&#xff0c;处理大量消息的分布式系统&#xff0c;它是一个专注于实时处理的任务队列&#xff0c;同时也支持任务调度。中文官网&#xff1a;http://docs.jinkan.org/docs/celery/ 在线安装 sudo pip3 install -U…

语音验证码有哪些优势

稳定高效 链接各国运营商语音通道&#xff0c;不受时间地域限制&#xff0c;到达率较高&#xff0c;验证效果稳定高效&#xff0c;大大提高了客户回填率和转化率&#xff0c;减少客户流失。 海量并发 智能运维系统&#xff0c;实时监控&#xff0c;自动切换&#xff0c;无需…

【二分查找】【滑动窗口】LeeCode2528:最大化城市的最小电量

作者推荐 【动态规划】【广度优先】LeetCode2258:逃离火灾 本文涉及的基础知识点 二分查找算法合集 滑动窗口 题目 给你一个下标从 0 开始长度为 n 的整数数组 stations &#xff0c;其中 stations[i] 表示第 i 座城市的供电站数目。 每个供电站可以在一定 范围 内给所有城…

PR分屏模板|Premiere动态多画面多屏特效视频模板剪辑素材

这一个很棒的分屏效果PR幻灯片模板视频素材&#xff01;为您的视频制作多屏幕动画&#xff01; 非常易于定制、更改颜色。 仅支持Premier Pro 2024及最新版本。 高清分辨率&#xff1a;19201080/30fps。 持续时间–00:37。 21媒体占位符&#xff08;照片或视频&#xff09;。 包…

Mongdb常用复杂语句(nosql)总结

➡️ ➡️ 关于 MongoDB和MongoTemplate 嵌套数据判空查询 的讨论 ⬅️ ⬅️ 在本篇文章中小名会时常维护些来不及分类的日工作常用的复杂语句&#xff1a; 1、按照表id查询 db.getCollection(TABLE_NAME).find({"_id":ObjectId("62947c8fe2a399286a7259f7&q…

Web网站服务(二)

1、客户机地址限制。 Require all granted&#xff1a;表示允许所有主机访问。 Require all denied&#xff1a;表示拒绝所有主机访问。 Require local&#xff1a;表示仅允许本地主机访问。 Require [not] host <主机名或域名列表>&#xff1a;表示允许或拒绝指定主机或…

2、快速搞定Kafka术语

快速搞定Kafka术语 Kafka 服务端3层消息架构 Kafka 客户端Broker 如何持久化数据小结 Kafka 服务端 3层消息架构 第 1 层是主题层&#xff0c;每个主题可以配置 M 个分区&#xff0c;而每个分区又可以配置 N 个副本。第 2 层是分区层&#xff0c;每个分区的 N 个副本中只能有…

【sqli靶场】第二关和第三关通关思路

目录 前言 一、sqli靶场第二关 1.1 判断注入类型 1.2 判断数据表中的列数 1.3 使用union联合查询 1.4 使用group_concat()函数 1.5 爆出users表中的列名 1.6 爆出users表中的数据 二、sqli靶场第三关 2.1 判断注入类型 2.2 观察报错 2.3 判断数据表中的列数 2.4 使用union联合…