数据库系统原理与实践 笔记 #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>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎样在PPT中加入音频文件?记好这4个简单操作!

“我要制作一个比较专业的PPT来汇报工作成果&#xff0c;想在PPT里加一段音乐&#xff0c;但是不知道应该如何操作&#xff0c;有没有朋友可以指导一下呢&#xff1f;” PPT作为一种常用的文件形式&#xff0c;很多用户会将其用于工作汇报&#xff0c;期末总结以及各种演讲。在…

六级高频词组2

目录 词组 参考链接 词组 51. arise from&#xff08;be caused by&#xff09; 由…引起。 52. arrange for sb.sth. to do sth. 安排…做… 53. arrive on 到达&#xff1b; arrive at 到达某地&#xff08;小地方&#xff09;&#xff1b;得出&#xff0c;作出&#x…

zookeeper基础内容

文章目录 Zookeeper基础概述数据结构Zookeeper节点操作zookeeper节点操作命令数据模型 znode 结构 zookeeper java客户端ZooKeeper原生APICuratorzkClient对比总结 Zookeeper基础 概述 zookeeper&#xff08;分布式协调服务&#xff09; 本质&#xff1a;小型的文件存储系统监…

Springboot内置Tomcat线程数优化

Springboot内置Tomcat线程数优化 # 等待队列长度&#xff0c;默认100。队列也做缓冲池用&#xff0c;但也不能无限长&#xff0c;不但消耗内存&#xff0c;而且出队入队也消耗CPU server.tomcat.accept-count1000 # 最大工作线程数&#xff0c;默认200。&#xff08;4核8g内存…

Spring 的缓存机制【记录】

一、背景 在最近的业务需求开发过程中遇到了“传说中”的循环依赖问题&#xff0c;在之前学习Spring的时候经常会看到Spring是如何解决循环依赖问题的&#xff0c;所谓循环依赖即形成了一个环状的依赖关系&#xff0c;这个环中的某一个点产生不稳定变化都会导致整个链路产生不…

OpenCV-opencv下载安装和基本操作

文章目录 一、实验目的二、实验内容三、实验过程OpenCV-python的安装与配置python下载和环境配置PIP镜像安装Numpy安装openCV-python检验opencv安装是否成功 openCV-python的基本操作图像输入和展示以及写出openCV界面编程单窗口显示多图片鼠标事件键盘事件滑动条事件 四、实验…

Altman作了多少恶?排挤首席科学家出GPT5开发、离间董事会、PUA员工

在山姆奥特曼&#xff08;Sam Altman&#xff09;被OpenAI董事会突然解职后的几天里&#xff0c;这个消息在科技圈引发轰动&#xff0c;该公司内部员工和许多科技界人士甚至将此举比作一场政变。 奥特曼被解雇后立即传出的说法是&#xff0c;OpenAI的广大员工都很喜欢他&#x…

一入一出模拟量两线制无源 4-20mA隔离变送器

一入一出模拟量两线制无源 4-20mA隔离变送器 特征与应用&#xff1a; ◆薄体积&#xff0c;低成本&#xff0c;国际标准 DIN35mm 导轨安装方式 ◆两端隔离(输入、输出间相互隔离) ◆单通道输入单通道输出 ◆高精度等级(0.1%,0.2% F.S) ◆高线性度(0.1% F.S) ◆高隔离电压(3000…

32位ADC布局的指导方针

接地必须是一个低阻抗连接&#xff0c;以使回流电流不受干扰地流回各自的源。接地面连接尽量短且直。使用过孔连接接地线时&#xff0c;应并联多个过孔&#xff0c;以减小对地阻抗。 混合信号布局有时包含在一个位置捆绑在一起的单独的模拟和数字地平面;但是&#xff0c;当模拟…

活动回顾 | 菊风亮相 GTC2023 全球流量大会

2023年12月5日-12月6日&#xff0c;由白鲸出海主办的【GTC2023 全球流量大会】在中国深圳盛大召开。 本次大会荟聚海内外优质企业品牌&#xff0c;以专业的“展会”形式&#xff0c;全方位呈现跨境出海的成果&#xff0c;探索多元化的跨境商业模式&#xff0c;大会涵盖社交娱乐…

【Jeecg Boot 3 - 第二天】1.1、后端 docker-compose 部署 JEECGBOOT3

一、场景 二、实战 ▶ 2.1 修改配置文件 &#xff1e; 目的一&#xff1a;将 dev 变更为生产环境 prod &#xff1e; 目的二&#xff1a;方便spring项目调用docker同个network下的redis和mysql ▶ 2.2 编写dockerfile ▶ 2.3 编写docker-compose.yaml ▶ 2.4 打…

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

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

cadence中如何在更新原理图封装

cadence中如何在更新原理图封装 一、更改原理图封装 当原理图画好后&#xff0c;如果我们发现某个封装错了&#xff0c;需要改动&#xff0c;需要找到你最初画Library中器件封装文件打开&#xff0c;进行修改&#xff0c;修改好后保存。 二、更新封装 保存好后&#xff0c;…

C/C++ 有效的字母异位词

题目&#xff1a; 给定两个字符串s和t&#xff0c;编写一个函数来判断t是否是s的字母异位词。 注&#xff1a;若s和t中每个字符出现的次数都相同&#xff0c;则称s和t互为字母异位词。 示例 1: 输入: s "anagram", t "nagaram" 输出: true …

【IDEA】反向撤销操作快捷键 ctrl+shift+z 和搜狗热键冲突的解决办法

当我们执行某些操作时与搜狗热键冲突&#xff0c;直接取消搜狗的快捷键即可&#xff01;&#xff01;&#xff01;以下以 ctrlshiftz 为例。 在输入悬浮框右键找到更多设置 按键里面找到系统功能快捷键设置 取消掉冲突的热键即可

ARM day6

2.串口发送指令控制硬件工作 结果&#xff1a; uart.h #ifndef __UART_H__ #define __UART_H__ #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h" #include "stm32mp1xx_uart.h"void myuart4_init(); void myputchar(char i); cha…

C++ this指针

通常情况下&#xff0c;类的成员函数都只涉及一个对象&#xff0c;即调用它的对象。但有时候方法可能涉及到两个对象&#xff0c;在这种情况就需要使用到C的this指针。 class Stock { private: ... double total_val; ... public: double total() const {return total_val;} }…

【Linux】进程周边002之进程状态

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.什么是状态&#xff1f; …

Python中的魔力编程:掌握面向对象之道

Python中的面向对象编程 背景&#xff1a; ​ 最近在看一些代码的时候&#xff0c;对类中的一些内置方法不是很懂&#xff0c;因此出一篇文章来细说一下&#xff0c;希望大家看完后对Python中类有一个清楚的认识。 基础铺垫&#xff1a; ​ 面向对象的三个特点&#xff1a;…