当前位置: 首页 > news >正文

数据库锁简析

  • 数据库大并发操作要考虑死锁和锁的性能问题。
  • 用T1代表一个数据库执行请求,T2代表另一个请求,
  • 也可以理解为T1为一个线程,T2 为另一个线程。
  • T3,T4以此类推。下面以SQL Server为例。

锁的种类

共享锁(Shared lock)

  • 例1:
  • T1: select * from table (请想象它需要执行1个小时之久,后面的sql语句请都这么想象)
  • T2: update table set column1='hello'
  • 过程:
  • T1运行 (加共享锁)
    T2运行
    If T1 还没执行完
    T2等......
    else
    锁被释放
    T2执行
    endif
  • T2之所以要等,是因为T2在执行update前,试图对table表加一个排他锁,
  • 而数据库规定同一资源上不能同时共存共享锁和排他锁。所以T2必须等T1
  • 执行完,释放了共享锁,才能加上排他锁,然后才能开始执行update语句。
  • 例2:
  • T1: select * from table
  • T2: select * from table
  • 这里T2不用等待T1执行完,而是可以马上执行。
  • 分析:
  • T1运行,则table被加锁,比如叫lockA
  • T2运行,再对table加一个共享锁,比如叫lockB。
  • 两个锁是可以同时存在于同一资源上的(比如同一个表上)。
  • 这被称为共享锁与共享锁兼容。
  • 这意味着共享锁不阻止其它session同时读资源,
  • 但阻止其它session update
  • 例3:
  • T1: select * from table
  • T2: select * from table
  • T3: update table set column1='hello'
  • 这次,T2不用等T1运行完就能运行,
  • T3却要等T1和T2都运行完才能运行。
  • 因为T3必须等T1和T2的共享锁全部释放才能进行加排他锁然后执行update操作
  • 例4:(死锁的发生)
  • T1:
    begin tran
    select * from table (holdlock) (holdlock意思是加共享锁,直到事务结束才释放)
    update table set column1='hello'T2:
    begin tran
    select * from table(holdlock)
    update table set column1='world'
  • 假设T1和T2同时达到select,
  • T1对table加共享锁,T2也对加共享锁,
  • 当T1的select执行完,准备执行update时,
  • 根据锁机制,
  • T1的共享锁需要升级到排他锁才能执行接下来的update.在升级排他锁前,
  • 必须等table上的其它共享锁释放,
  • 但因为holdlock这样的共享锁只有等事务结束后才释放,
  • 所以因为T2的共享锁不释放而导致T1等
  • (等T2释放共享锁,自己好升级成排他锁),
  • 同理,也因为T1的共享锁不释放而导致T2等。死锁产生了。
  • 例5:
  • T1:
    begin tran
    update table set column1='hello' where id=10T2:
    begin tran
    update table set column1='world' where id=20
  • 这种语句虽然最为常见,
  • 很多人觉得它有机会产生死锁,
  • 但实际上要看情况,
  • 如果id是主键上面有索引,
  • 那么T1会一下子找到该条记录(id=10的记录),
  • 然后对该条记录加排他锁,T2,同样,一下子通过索引定位到记录,
  • 然后对id=20的记录加排他锁,这样T1和T2各更新各的,互不影响。T2也不
  • 需要等。
  • 但如果id是普通的一列,没有索引。
  • 那么当T1对id=10这一行加排他锁后,
  • T2为了找到id=20,需要对全表扫描,
  • 那么就会预先对表加上共享锁或更新锁或排他锁
  • (依赖于数据库执行策略和方式,比如第一次执行和第二次执行数据库执行策略就会不同)。
  • 但因为T1已经为一条记录加了排他锁,
  • 导致T2的全表扫描进行不下去,就导致T2等待

死锁怎么解决呢?一种办法是,如下:

例6:

T1:

begin tran

select * from table(xlock) (xlock意思是直接对表加排他锁)

update table set column1='hello'

T2:

begin tran

select * from table(xlock)

update table set column1='world'

这样,当T1的select 执行时,直接对表加上了排他锁,T2在执行select时,就需要等T1事物完全执行完才能执行。排除了死锁发生。

但当第三个user过来想执行一个查询语句时,也因为排他锁的存在而不得不等待,第四个、第五个user也会因此而等待。在大并发

情况下,让大家等待效果可想而知,所以,这里引入了更新锁。

更新锁(Update lock)

为解决死锁,引入更新锁。

例7:

----------------------------------------

T1:

begin tran

select * from table(updlock) (加更新锁)

update table set column1='hello'

T2:

begin tran

select * from table(updlock)

update table set column1='world'

更新锁的意思是:“我现在只想读,你们别人也可以读,但我将来可能会做更新操作,我已经获取了从共享锁(用来读)到排他锁

(用来更新)的资格”。一个事务只能有一个更新锁获此资格。

T1执行select,加更新锁。

T2运行,准备加更新锁,但发现已经有一个更新锁在那儿了,只好等。

当后来有user3、user4...需要查询table表中的数据时,并不会因为T1的select在执行就被阻塞,照样能查询,相比起例6,这提高

了效率。

例8:

----------------------------------------

T1: select * from table(updlock) (加更新锁)

T2: select * from table(updlock) (等待,直到T1释放更新锁,因为同一时间不能在同一资源上有两个更新锁)

T3: select * from table (加共享锁,但不用等updlock释放,就可以读)

这个例子是说明:共享锁和更新锁可以同时在同一个资源上。这被称为共享锁和更新锁是兼容的。

例9:

----------------------------------------

T1:

begin

select * from table(updlock) (加更新锁)

update table set column1='hello' (重点:这里T1做update时,不需要等T2释放什么,而是直接把更新锁升级为排他锁,然后执行update)

T2:

begin

select * from table (T1加的更新锁不影响T2读取)

update table set column1='world' (T2的update需要等T1的update做完才能执行)

我们以这个例子来加深更新锁的理解,

第一种情况:T1先达,T2紧接到达;在这种情况中,T1先对表加更新锁,T2对表加共享锁,假设T2的select先执行完,准备执行update,

发现已有更新锁存在,T2等。T1执行这时才执行完select,准备执行update,更新锁升级为排他锁,然后执行update,执行完成,事务

结束,释放锁,T2才轮到执行update。

第二种情况:T2先达,T1紧接达;在这种情况,T2先对表加共享锁,T1达后,T1对表加更新锁,假设T2 select先结束,准备

update,发现已有更新锁,则等待,后面步骤就跟第一种情况一样了。

这个例子是说明:排他锁与更新锁是不兼容的,它们不能同时加在同一子资源上。

排他锁(独占锁,Exclusive Locks)

这个简单,即其它事务既不能读,又不能改排他锁锁定的资源。

例10

T1: update table set column1='hello' where id<1000

T2: update table set column1='world' where id>1000

假设T1先达,T2随后至,这个过程中T1会对id<1000的记录施加排他锁.但不会阻塞T2的update。

例11 (假设id都是自增长且连续的)

T1: update table set column1='hello' where id<1000

T2: update table set column1='world' where id>900

如同例10,T1先达,T2立刻也到,T1加的排他锁会阻塞T2的update.

意向锁(Intent Locks)

意向锁就是说在屋(比如代表一个表)门口设置一个标识,说明屋子里有人(比如代表某些记录)被锁住了。另一个人想知道屋子

里是否有人被锁,不用进屋子里一个一个的去查,直接看门口标识就行了。

当一个表中的某一行被加上排他锁后,该表就不能再被加表锁。数据库程序如何知道该表不能被加表锁?一种方式是逐条的判断该

表的每一条记录是否已经有排他锁,另一种方式是直接在表这一层级检查表本身是否有意向锁,不需要逐条判断。显然后者效率高。

例12:

----------------------------------------

T1: begin tran

select * from table (xlock) where id=10 --意思是对id=10这一行强加排他锁

T2: begin tran

select * from table (tablock) --意思是要加表级锁

假设T1先执行,T2后执行,T2执行时,欲加表锁,为判断是否可以加表锁,数据库系统要逐条判断table表每行记录是否已有排他锁,

如果发现其中一行已经有排他锁了,就不允许再加表锁了。只是这样逐条判断效率太低了。

实际上,数据库系统不是这样工作的。当T1的select执行时,系统对表table的id=10的这一行加了排他锁,还同时悄悄的对整个表

加了意向排他锁(IX),当T2执行表锁时,只需要看到这个表已经有意向排他锁存在,就直接等待,而不需要逐条检查资源了。

例13:

----------------------------------------

T1: begin tran

update table set column1='hello' where id=1

T2: begin tran

update table set column1='world' where id=1

这个例子和上面的例子实际效果相同,T1执行,系统对table同时对行加排他锁、对页加意向排他锁、对表加意向排他锁。

计划锁(Schema Locks)

例14:

----------------------------------------

alter table .... (加schema locks,称之为Schema modification (Sch-M) locks

DDL语句都会加Sch-M锁

该锁不允许任何其它session连接该表。连都连不了这个表了,当然更不用说想对该表执行什么sql语句了。

例15:

----------------------------------------

用jdbc向数据库发送了一条新的sql语句,数据库要先对之进行编译,在编译期间,也会加锁,称之为:Schema stability (Sch-S) locks

select * from tableA

编译这条语句过程中,其它session可以对表tableA做任何操作(update,delete,加排他锁等等),但不能做DDL(比如alter table)操作。

Bulk Update Locks 主要在批量导数据时用(比如用类似于oracle中的imp/exp的bcp命令)。不难理解,程序员往往也不需要关心,不赘述了。

3 何时加锁?

如何加锁,何时加锁,加什么锁,你可以通过hint手工强行指定,但大多是数据库系统自动决定的。这就是为什么我们可以不懂锁也可

以高高兴兴的写SQL。

例15:

----------------------------------------

T1: begin tran

update table set column1='hello' where id=1

T2: SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED -- 事务隔离级别为允许脏读

go

select * from table where id=1

这里,T2的select可以查出结果。如果事务隔离级别不设为脏读,则T2会等T1事物执行完才能读出结果。

数据库如何自动加锁的?

1) T1执行,数据库自动加排他锁

2) T2执行,数据库发现事务隔离级别允许脏读,便不加共享锁。不加共享锁,则不会与已有的排他锁冲突,所以可以脏读。

例16:

----------------------------------------

T1: begin tran

update table set column1='hello' where id=1

T2: select * from table where id=1 --为指定隔离级别,则使用系统默认隔离级别,它不允许脏读

如果事务级别不设为脏读,则:

1) T1执行,数据库自动加排他锁

2) T2执行,数据库发现事务隔离级别不允许脏读,便准备为此次select过程加共享锁,但发现加不上,因为已经有排他锁了,所以就

等啊等。直到T1执行完,释放了排他锁,T2才加上了共享锁,然后开始读....

4 锁的粒度

锁的粒度就是指锁的生效范围,就是说是行锁,还是页锁,还是整表锁. 锁的粒度同样既可以由数据库自动管理,也可以通过手工指定hint来管理。

例17:

----------------------------------------

T1: select * from table (paglock)

T2: update table set column1='hello' where id>10

T1执行时,会先对第一页加锁,读完第一页后,释放锁,再对第二页加锁,依此类推。假设前10行记录恰好是一页(当然,一般不可能

一页只有10行记录),那么T1执行到第一页查询时,并不会阻塞T2的更新。

例18:

----------------------------------------

T1: select * from table (rowlock)

T2: update table set column1='hello' where id=10

T1执行时,对每行加共享锁,读取,然后释放,再对下一行加锁;T2执行时,会对id=10的那一行试图加锁,只要该行没有被T1加上行锁,

T2就可以顺利执行update操作。

例19:

----------------------------------------

T1: select * from table (tablock)

T2: update table set column1='hello' where id = 10

T1执行,对整个表加共享锁. T1必须完全查询完,T2才可以允许加锁,并开始更新。

以上3例是手工指定锁的粒度,也可以通过设定事务隔离级别,让数据库自动设置锁的粒度。不同的事务隔离级别,数据库会有不同的

加锁策略(比如加什么类型的锁,加什么粒度的锁)。具体请查联机手册。

5 锁与事务隔离级别的优先级

手工指定的锁优先,

例20:

----------------------------------------

T1: GO

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

GO

BEGIN TRANSACTION

SELECT * FROM table (NOLOCK)

GO

T2: update table set column1='hello' where id=10

T1是事物隔离级别为最高级,串行锁,数据库系统本应对后面的select语句自动加表级锁,但因为手工指定了NOLOCK,所以该select

语句不会加任何锁,所以T2也就不会有任何阻塞。

6 数据库的其它重要Hint以及它们的区别

1) holdlock 对表加共享锁,且事务不完成,共享锁不释放。

2) tablock 对表加共享锁,只要statement不完成,共享锁不释放。

与holdlock区别,见下例:

例21

----------------------------------------

T1:

begin tran

select * from table (tablock)

T2:

begin tran

update table set column1='hello' where id = 10

T1执行完select,就会释放共享锁,然后T2就可以执行update. 此之谓tablock. 下面我们看holdlock

例22

----------------------------------------

T1:

begin tran

select * from table (holdlock)

T2:

begin tran

update table set column1='hello' where id = 10

T1执行完select,共享锁仍然不会释放,仍然会被hold(持有),T2也因此必须等待而不能update. 当T1最后执行了commit或

rollback说明这一个事务结束了,T2才取得执行权。

3) TABLOCKX 对表加排他锁

例23:

----------------------------------------

T1: select * from table(tablockx) (强行加排他锁)

其它session就无法对这个表进行读和更新了,除非T1执行完了,就会自动释放排他锁。

例24:

----------------------------------------

T1: begin tran

select * from table(tablockx)

这次,单单select执行完还不行,必须整个事务完成(执行了commit或rollback后)才会释放排他锁。

4) xlock 加排他锁

那它跟tablockx有何区别呢?

它可以这样用,

例25:

----------------------------------------

select * from table(xlock paglock) 对page加排他锁

而TABLELOCX不能这么用。

xlock还可这么用:select * from table(xlock tablock) 效果等同于select * from table(tablockx)

7 锁的超时等待

例26

SET LOCK_TIMEOUT 4000 用来设置锁等待时间,单位是毫秒,4000意味着等待

4秒可以用select @@LOCK_TIMEOUT查看当前session的锁超时设置。-1 意味着

永远等待。

T1: begin tran

udpate table set column1='hello' where id = 10

T2: set lock_timeout 4000

select * from table wehre id = 10

T2执行时,会等待T1释放排他锁,等了4秒钟,如果T1还没有释放排他锁,T2就会抛出异常: Lock request time out period exceeded.

8 附:各种锁的兼容关系表

| Requested mode | IS | S | U | IX | SIX | X |

| Intent shared (IS) | Yes | Yes | Yes | Yes | Yes | No |

| Shared (S) | Yes | Yes | Yes | No | No | No |

| Update (U) | Yes | Yes | No | No | No | No |

| Intent exclusive (IX) | Yes | No | No | Yes | No | No |

| Shared with intent exclusive (SIX) | Yes | No | No | No | No | No |

| Exclusive (X) | No | No | No | No | No | No |

9 如何提高并发效率

悲观锁:利用数据库本身的锁机制实现。通过上面对数据库锁的了解,可以根据具体业务情况综合使用事务隔离级别与合理的手工指定锁的方式比如降低锁的粒度等减少并发等待。

乐观锁:利用程序处理并发。原理都比较好理解,基本一看即懂。方式大概有以下3种

对记录加版本号.

对记录加时间戳.

对将要更新的数据进行提前读取、事后对比。

不论是数据库系统本身的锁机制,还是乐观锁这种业务数据级别上的锁机制,本质上都是对状态位的读、写、判断。

转载:数据库锁 - 口渴的火麒麟 - 博客园

相关文章:

数据库锁简析

数据库大并发操作要考虑死锁和锁的性能问题。用T1代表一个数据库执行请求&#xff0c;T2代表另一个请求&#xff0c;也可以理解为T1为一个线程&#xff0c;T2 为另一个线程。T3,T4以此类推。下面以SQL Server为例。 锁的种类 共享锁(Shared lock) 例1&#xff1a;T1: select…...

说说广播流与普通流

分析&回答 user actions 可以看作是事件流&#xff08;普通流&#xff09;patterns 为广播流,把全量数据加载到不同的计算节点。 广播流 Broadcast是一份存储在TaskManager内存中的只读的缓存数据在执行job的过程中需要反复使用的数据&#xff0c;为了达到数据共享&am…...

内卷的本质和大数据在计量经济学领域的运用思考

内卷的本质和大数据在计量经济学领域的运用思考 今天我们来思考两个问题&#xff1a; 当下经济的困局在哪里&#xff1f;为何内卷越来越严重&#xff1f;内卷的本质是什么&#xff1f;为何会出现内卷&#xff1f;市场经济运行的底层逻辑是什么&#xff1f;西方经济学理论的指导…...

毕业设计-摄像头识别二维码

本毕业设计采用imx6ull-linux4.1.15-qt5.6开发板进行测试 相关交叉编译包和摄像头测试程序已上传&#xff1a;https://download.csdn.net/download/qq_42952079/88282608 将zbar和opencv下的lib库文件拷贝到开发板的lib目录下&#xff0c;将camera可执行文件拷贝到开发板目录下…...

封装动态表单组件

技术栈&#xff1a;vue2 js webpack 需求&#xff1a; 利用数据渲染表单&#xff0c;实现代码的精简化及效率的提升。 效果图&#xff1a; 封装的组件&#xff1a; <div v-if"formConfig"><el-formv-bind"$attrs"ref"formDom":model…...

提高Python并发性能 - asyncio/aiohttp介绍

在进行大规模数据采集时&#xff0c;如何提高Python爬虫的并发性能是一个关键问题。本文将向您介绍使用asyncio和aiohttp库实现异步网络请求的方法&#xff0c;并通过具体结果和结论展示它们对于优化爬虫效率所带来的效果。 1. 什么是异步编程&#xff1f; 异步编程是一种非阻…...

网络性能的四大指标:带宽、时延、抖动、丢包

原文链接&#xff1a;https://www.eet-china.com/mp/a82420.html 怎么去描述网络性能的好坏&#xff1f; 你如果说这个网络很好&#xff0c;那里的网络有点差&#xff01;这无异于看这风景美如画,本想吟诗赠天下,怎奈自己没文化,只能卧槽浪好大。 我们得用专业的术语去描述它…...

MySQL高阶查询语句

目录 一、常用查询 1、按关键字排序 1.1 升序排序 1.2 降序排序 1.3 结合where进项条件过滤再排序 1.4 多条件排序 2、区间判断及查询不重复记录 2.1 and/or&#xff08;且/或&#xff09; 2.2 嵌套 /多条件 2.3 distinct 查询不重复记录 3、对结果进行分组 4、限…...

未来科技城携手加速科技 共建集成电路测试公共服务平台!

8月26日&#xff0c;2023未来产业发展大会在杭州未来科技城国际会议中心开幕&#xff01;会上&#xff0c;发布了未来科技城培育发展未来产业行动计划&#xff0c;启动了未来产业发展共同体&#xff0c;进行了未来产业公共服务平台签约仪式。未来科技城与加速科技签约共建集成电…...

渗透测试漏洞原理之---【失效的访问控制】

文章目录 1、失效的访问控制1.1、OWASP Top 101.1.1、A5:2017-Broken Access Control1.1.2、A01:2021 – Broken Access Control 1.2、失效的访问控制类别1.2.1、水平越权1.2.2、垂直越权 1.3、攻防案例1.3.1、Pikachu靶场 Over Permision1.3.2、DVWA越权利用失效的访问控制漏洞…...

opencv的使用(Ubuntu linux环境,AS jni,AS java)

最近要完成一个功能,就是把四个视频合成左右上下分布的一个视频。尝试很多方法,最终使用opencv来实现该功能。(通过opencv实现的视频好像没有声音。)研究的步骤,首先在Ubuntu环境测试,该功能是否实现。然后再将生成的库文件放到AS中,使用jni的方法调用,或者将源码放到A…...

ChatGPT(对话AI)汇总

ChatGPT的全称为”Conversational Generative Pre-trained Transformer”&#xff0c;是一个基于预训练的自然语言处理模型。 1.商量SenseChat&#xff08;商汤&#xff09; SenseChat (sensetime.com) 2.文心一言&#xff08;百度&#xff09; 文心一言 (baidu.com) 3.百…...

【Docker】用Dockerfile制作个人的镜像文件

作者简介&#xff1a; 辭七七&#xff0c;目前大一&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; 七七的闲谈 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f…...

前端面试基础面试题——4

1.谈谈你对 ES6 的理解 2.说说你对 promise 的了解 3.解构赋值及其原理 4.Vue常用的修饰符及使用的场景 5.vue 中 key 值的作用 6.什么是 vue 的计算属性&#xff1f; 7.watch的作用是什么 8.计算属性的缓存和方法调用的区别 9.响应式系统的基本原理 10.vue-loader …...

【08期】ArrayList常见面试题

简介 ArrayList是我们开发中非常常用的数据存储容器之一&#xff0c;其底层是数组实现的&#xff0c;我们可以在集合中存储任意类型的数据&#xff0c;ArrayList是线程不安全的&#xff0c;非常适合用于对元素进行查找&#xff0c;效率非常高。 线程安全性 对ArrayList的操作…...

Android studio之GridView使用

目录 效果图&#xff1a;![在这里插入图片描述](https://img-blog.csdnimg.cn/86e4a48a71164dec82613d58b1fbaa1c.jpeg)代码&#xff1a; 效果图&#xff1a; 代码&#xff1a; UserGridviewAdapter package com.example.gridviewpro.Adapter;import android.content.Contex…...

Ubuntu系统环境搭建(七)——Ubuntu安装MySQL8.0

ubuntu环境搭建专栏&#x1f517;点击跳转 Ubuntu系统环境搭建&#xff08;七&#xff09;——Ubuntu安装MySQL8.0 文章目录 Ubuntu系统环境搭建&#xff08;七&#xff09;——Ubuntu安装MySQL8.01、安装1.1、下载1.2、解压安装 2、配置工作2.1、基本设置2.1.1、文件夹重命名…...

Nginx详解 三:高级配置

文章目录 1. 网页的状态页2. Nginx第三方模块2.1 echo模块 3. 变量3.1 内置变量3.1.1 示例 3.2 自定义变量3.2.1 自定义访问日志3.2.2 自定义json 格式日志 3.4 Nginx压缩功能 4. HTTPS4.1 Nginx的HTTPS工作原理4.2 启用功能模块的配置过程 5、自定义图标 1. 网页的状态页 基于…...

mysql 表备份 遇到的问题 【全网最全】

目录 省流&#xff1a; 正文&#xff1a; 1、报错 2、原因 3、解决方法 方法一&#xff1a;关闭 ENFORCE_GTID_CONSISTENCY &#xff08;不推荐&#xff09;&#xff1a; 方法二&#xff08;推荐&#xff09;&#xff1a; 4、开启关闭GTID 省流&#xff1a; 不推荐如…...

11.添加侧边栏,并导入数据

修改CommonAside的代码&#xff1a; <template><div><el-menu default-active"1-4-1" class"el-menu-vertical-demo" open"handleOpen" close"handleClose":collapse"isCollapse"><!--<el-menu-it…...

ThinkPHP 通用的API格式封装

ThinkPHP 通用的API格式封装 1.创建status.php 用于设置通用的状态码返回枚举类2.将API返回格式统一封装3.重写BaseController中的__call方法4.在控制器下面新建Error控制器&#xff0c;然后添加__call方法 1.创建status.php 用于设置通用的状态码返回枚举类 <?phpreturn[…...

自己动手写数据库:实现一个小型 SQL 解释器(下)

本节我们完成 SQL 解释器的最后一部分&#xff0c;它涉及到数据的删除和更改&#xff0c;首先我们看删除语句的解析。我们先看 delete 对应的语法&#xff1a; Delete -> DELETE FROM ID (where Predicate)?从语法规则可以看出&#xff0c;delete 语句必须以关键字 DELETE…...

2023年信息安全管理与评估任务书模块一网络平台搭建与设备安全防护

全国职业院校技能大赛 高等职业教育组 信息安全管理与评估 任务书 模块一 网络平台搭建与设备安全防护 比赛时间 本阶段比赛时长为180分钟。 赛项信息 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段 网络平台搭建与设备安全防护 任务1 网络平台搭建 9:00- 12:00 …...

JS -RSA 明文加密--用户密码加密

1 配置文件引入 加密包 package.json "jsencrypt": "^3.0.0-rc.1",2 加密公钥配置 import { JSEncrypt } from jsencrypt import request from "/utils/request";const RSA_PUBLIC_KEY "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJVol0cJ…...

clickhouse中replacingMergeTree

ReplacingMergeTree是在MergeTree上添加了去重的功能&#xff0c;但是这个功能不可控&#xff0c;合并是一个后台的操作&#xff0c;除非手动触发&#xff0c;不然无法控制&#xff0c;并且它会删除具有相同(区内)主键的重复项。 特点&#xff1a; 1&#xff0c;去重时机不定&a…...

pdf怎么转换成word?

随着数字化时代的到来&#xff0c;PDF(Portable Document Format)已成为最受欢迎的文档格式之一&#xff0c;因其在各种设备上的可视性和稳定性而备受推崇。然而在某些情况下&#xff0c;将PDF转换为Word文档可能是必要的&#xff0c;这使得编辑、修改和重新格式化文本变得更加…...

汇编攻城记-Cortex-M3指令集

类型 指令 全称 功能 内存访问 LDR Load register 加载字到寄存器 LDRB 加载字节到寄存器 LDRH 加载半字到寄存器 LDRSH 加载半字到寄存器&#xff0c;再带符号扩展到32位 LDRD 从连续的地址空间加载双字&#xff08;64位整数&#xff09;到…...

大语言模型之五 谷歌Gemini

近十年来谷歌引领着人工智能方向的发展&#xff0c;从TensorFlow到TPU再到Transformer&#xff0c;都是谷歌在引领着&#xff0c;然而&#xff0c;在大语言模型上&#xff0c;却被ChatGPT&#xff08;OpenAI&#xff09;抢了风头&#xff0c;并且知道GPT-4&#xff08;OpenAI&a…...

使用selenium实现对页面元素的抓取

一、背景介绍 工作中有个需求是需要对某个页面进行监控&#xff0c;但由于要监控页面数据是异步加载的&#xff0c;因此很难从状态码和返回结果层面进行校验。于是乎想到了通过判断页面元素是否存在且显示内容是否正确来达到此目标。调研了一下发现selenium可以实现对这种动态…...

大数据课程K12——Spark的MLlib概述

文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解Spark的MLlib概念; ⚪ 掌握Spark的MLlib基本数据模型; ⚪ 掌握Spark的MLlib统计量基础; 一、Spark MLlib介绍 1. 概述 MLlib是Apache Spark的可迭代机器学习库。 2. 易于使用 …...