8000字 | 32 张图 | 一文搞懂事务+隔离级别+阻塞+死锁

来源 | 悟空聊架构(ID:PassJava666)

头图  | CSDN下载自视觉中国

事务


1.1 什么是事务

为单个工作单元而执行的一系列操作。如查询、修改数据、修改数据定义。

1.2 语法

「(1)显示定义事务的开始、提交」

BEGIN` `TRAN``INSERT` `INTO` `b(t1) ``VALUES``(1)``INSERT` `INTO` `b(t1) ``VALUES``(2)``COMMIT` `TRAN

「(2)隐式定义」

如果不显示定义事务的边界,则SQL Server会默认把每个单独的语句作为一个事务,即在执行完每个语句之后就会自动提交事务。

1.3 事务的四个属性ACID

「(1)原子性Atomicity」

原子性Atomicity**

  • 1.事务必须是原子工作单元。事务中进行的修改,要么全部执行,要么全都不执行;

  • 2.在事务完成之前(提交指令被记录到事务日志之前),系统出现故障或重新启动,SQL Server将会撤销在事务中进行的所有修改;

  • 3.事务在处理中遇到错误,SQL Server通常会自动回滚事务;

  • 4.少数不太严重的错误不会引发事务的自动回滚,如主键冲突、锁超时等;

  • 5.可以使用错误处理来捕获第4点提到的错误,并采取某种操作,如把错误记录在日志中,再回滚事务;

  • 6.SELECT @@TRANCOUNT可用在代码的任何位置来判断当前使用SELECT @@TRANCOUNT的地方是否位于一个打开的事务当中,如果不在任何打开的事务范围内,则该函数返回0;如果在某个打开的事务返回范围内,则返回一个大于0的值。打开一个事务,@@TRANCOUNT=@@TRANCOUNT+1;提交一个事务,@@TRANCOUNT-1。

「(2)一致性Consiitency」

一致性Consiitency

  • 1.同时发生的事务在修改和查询数据时不发生冲突;

  • 2.一致性取决于应用程序的需要。后面会讲到一致性级别,以及如何对一致性进行控制。

「(3)隔离性Isolation」

隔离性Isolation

  • 1.用于控制数据访问,确保事务只访问处于期望的一致性级别下的数据;

  • 2.使用锁对各个事务之间正在修改和查询的数据进行隔离。

「(4)持久性Durability」

持久性Durability

  • 1.「写事务日志:」 在将数据修改写入到磁盘上数据库的数据分区之前会把这些修改写入到磁盘上数据库的事务日志中,把提交指令记录到磁盘的事务日志中以后,即时数据修改还没有应用到磁盘的数据分区,也可以认为事务是持久化的。

  • 2.「系统重新启动:」 正常启动或在发生系统故障之后启动,SQL Server会每个数据库的事务日志,进行回复处理。

  • 3.「恢复处理包含两个阶段:」 重做阶段和撤销阶段。

  • 4.「前滚:」 在重做阶段,对于提交指令已经写入到日志的事务,但数据修改还没有应用到数据分区的事务,数据库引擎会重做这些食物所做的所有修改。

  • 5.「回滚:」 在撤销阶段,对于提交指令没有写入到日志中的事务,数据库引擎会撤销这些事务所做的修改。(这句话需要research,可能是不正确的。因为提交指令没有写入到数据分区,撤销修改是指撤销哪些修改呢?)



2.1 事务中的锁

(1)SQL Server使用锁来实现事务的隔离。

(2)事务获取锁这种控制资源,用于保护数据资源,防止其他事务对数据进行冲突的或不兼容的访问。

2.2 锁模式

「(1)排他锁」

排他锁

  • a.当试图修改数据时,事务只能为所依赖的数据资源请求排他锁。

  • b.持有排他锁时间:一旦某个事务得到了排他锁,则这个事务将一直持有排他锁直到事务完成。

  • c.排他锁和其他任何类型的锁在多事务中不能在同一阶段作用于同一个资源。

如:当前事务获得了某个资源的排他锁,则其他事务不能获得该资源的任何其他类型的锁。其他事务获得了某个资源的任何其他类型的锁,则当前事务不能获得该资源的排他锁。

「(2)共享锁」

共享锁

  • a.当试图读取数据时,事务默认会为所依赖的数据资源请求共享锁。

  • b.持有共享锁时间:从事务得到共享锁到读操作完成。

  • c.多个事务可以在同一阶段用共享锁作用于同一数据资源。

  • d.在读取数据时,可以对如何处理锁定进行控制。后面隔离级别会讲到如何对锁定进行控制。

2.3 排他锁和共享锁的兼容性

(1)如果数据正在由一个事务进行修改,则其他事务既不能修改该数据,也不能读取(至少默认不能)该数据,直到第一个事务完成。

(2)如果数据正在由一个事务读取,则其他事务不能修改该数据(至少默认不能)。

2.4 可锁定的资源的类型

RID、KEY(行)、PAGE(页)、对象(例如表)、数据库、EXTENT(区)、分配单元(ALLOCATION_UNIT)、堆(HEAP)、以及B树(B-tree)。

「RID: 标识页上的特定行」

  • 格式: fileid: pagenumber: rid (1:109:0 )

其中fileid标识包含页的文件, pagenumber标识包含行的页,rid标识页上的特定行。

fileid与sys.databases_files 目录视图中的file_id列相匹配。

  • 例子:

在查询视图sys.dm_tran_locks的时候有一行的resource_description列显示RID 是1:109:0 而status列显示wait,

表示第1个数据文件上的第109页上的第0行上的锁资源。

2.5 锁升级

SQL Server可以先获得细粒度的锁(例如行或页),在某些情况下将细粒度锁升级为更粗粒度的锁(例如,表)。
例如单个语句获得至少5000个锁,就会触发锁升级,如果由于锁冲突而导致无法升级锁,则SQL Server每当获取1250个新锁时出发锁升级。

阻塞


3.1 阻塞

当多个事务都需要对某一资源进行锁定时,默认情况下会发生阻塞。被阻塞的请求会一直等待,直到原来的事务释放相关的锁。锁定超时期限可以限制,这样就可以限制被阻塞的请求在超时之前要等待的时间

阻塞

  • 阶段1:事务A请求资源S1,事务不对资源S1进行操作

  • 阶段2:事务A用锁A锁定资源S1,事务B请求对资源S1进行不兼容的锁定(锁B),锁B的请求被阻塞,事务B将进入等待状态

  • 阶段3:事务A正在释放锁A,事务B等待锁A释放,

  • 阶段4:事务A的锁A已释放,事务B用锁B锁定资源S1

3.2 排除阻塞问题

例子:

3.2.1 准备工作

  • 1.准备测试数据

--先创建一张表Product作为测试。id为表的主键,price为product的价格
CREATE TABLE [dbo].[myProduct]([id] [int] NOT NULL,[price] [money] NOT NULL
) ON [PRIMARY]
GO
--插入一条数据,id=1,price=10
INSERT INTO [TSQLFundamentals2008].[dbo].[myProduct]([id],[price])VALUES(1,10)
2.模拟阻塞发生的情况

在SQL Server中打开三个查询窗口Connection1、Connection2、Connection3,分别按顺序执行表格中的执行语句。

--Connection1BEGIN TRANUPDATE dbo.myProduct SET price = price + 1 WHERE id=1

Connection1结果

「结论1:」

为了更新id=1这一行数据,会话必须先获得一个排他锁。事务处于一直打开状态,没有提交,所以事务一直持有排他锁,直到事务提交并完成。

--Connection2
SELECT * FROM dbo.myProduct WHERE id=1
Connection2结果

「结论2:」

事务为了读取数据,需要请求一个共享锁,但是这一行已经被其他会话持有的排他锁锁定,而且共享锁和排他锁不是兼容的,所以会话被阻塞,进入等待状态。

--Connection3SELECT  request_session_id AS 会话id ,        resource_type AS 请求锁定的资源类型 ,        resource_description AS 描述 ,        request_mode AS 模式 ,        request_status AS 状态FROM    sys.dm_tran_locks

Connection3查询结果

「结论3:」

「会话56:」(1)状态WAIT-等待锁

(2)正在等待第1个数据文件上的第109页上的第0行资源的共享锁

(3)持有第1个数据文件上的第109页资源的意向共享锁

(3)持有OBJECT资源,意向共享锁

(4)持有DATABASE资源,意向共享锁

「会话52:」

(1)状态WAIT-授予锁

(2)正在等待第1个数据文件上的第109页上的第0行资源的排他锁(3)持有第1个数据文件上的第109页资源的排他锁

(3)持有OBJECT资源,排他锁

(4)持有DATABASE资源,排他锁

演示与总结如下所示:

演示与总结

3.2.2 分析阻塞原因

3.2.2.1 sys.dm_tran_locks 视图

(1)该动态视图可以查询出哪些资源被哪个进程ID锁了

(2)查询出对资源授予或正在等待的锁模式

(3)查询出被锁定资源的类型

上面的查询语句3已经用到了这个视图,可以参考上图中的分析说明。

3.2.2.2 sys.dm_exec_connections 视图

(1)查询出该动态视图可以查询出进程相关的信息

(2)查询出最后一次发生读操作和写操作的时间last_read,last_write

(3)查询出进程执行的最后一个SQL批处理的二进制标记most_recent_sql_handle

SELECT  session_id ,        connect_time ,        last_read ,        last_write ,        most_recent_sql_handleFROM    sys.dm_exec_connections WHERE   session_id IN ( 52, 56 )

查询结果1

查询结果2

「结论:」

「会话52:」

(1)connect_time连接时间:2016-06-07 07:09:41.103

(2)last_read最后一次读操作时间:2016-06-07 07:10:56.233

(3)last_write最后一次写操作时间:2016-06-07 07:10:57.873

(4)most_recent_sql_handle这是一个二进制标记,最后一个SQL批处理

「会话56:」

(1)状态WAIT-授予锁

(2)正在等待第1个数据文件上的第109页上的第0行资源的排他锁(3)持有第1个数据文件上的第109页资源的排他锁

(3)持有OBJECT资源,排他锁

(4)持有DATABASE资源,排他锁

演示与总结如下所示:

演示与总结

3.2.2.3 sys.dm_exec_sql_text 表函数

示例:

会话52:执行的SQL语句:BEGIN TRANUPDATE dbo.myProductSET price = price + 1WHERE id = 1
会话56:执行的SQL语句:(@1 tinyint)SELECT * FROM [dbo].[myProduct]WHERE [id]=@1
(1)该函数可以将二进制标记most_recent_sql_handle作为参数,然后返回SQL代码。

(2)阻塞进程在不断地运行,所以在代码中看到的最后一个操作不一定是导致问题的语句。在本例中最后一条执行语句是导致阻塞的语句。

SELECT  session_id ,        textFROM    sys.dm_exec_connections        CROSS APPLY sys.dm_exec_sql_text        (most_recent_sql_handle) AS STWHERE   session_id IN ( 52, 56 )

查询结果

演示与总结如下所示:

演示与总结

3.2.2.4 sys.dm_exec_sessions 视图

(1)会话建立的时间login_time

(2)特定于会话的客户端工作站名称host_name

(3)初始化会话的客户端程序的名称program_name

(4)会话所使用的SQL Server登录名login_name

(5)最近一次会话请求的开始时间last_request_start_time

(6)最近一次会话请求的完成时间last_request_end_time

SELECT * FROM sys.dm_exec_sessions

查询结果

演示与总结如下所示:

演示与总结

3.2.2.5 sys.dm_exec_requests 视图

(1)识别出阻塞链涉及到的会话、争用的资源、被阻塞会话等待了多长时间。

SELECT * FROM sys.dm_exec_sessions

查询结果1

查询结果2

「结论:」

「会话56:」

(1)被会话52阻塞,blocking_session_id = 52

(2)会话52的开始时间start_time

(3)状态挂起status = suspended

(4)挂起的命令command

演示与总结如下所示:

演示与总结

3.2.3 解决阻塞问题

3.2.3.1 Lock_TIMEOUT 选项

(1)设置会话等待锁释放的超时期限

(2)默认情况下会话不会设置等待锁释放的超时期限

(3)设置会话超时期限为5秒, SET Lock_TIMEOUT 5000

(4)锁定如果超时,不会引发事务回滚

(5)取消会话超时锁定的设置,SET LOCK_TIMEOUT -1

如果超时,将显示以下错误:

错误提示

3.2.3.1 KILL命令

(1)杀掉会话52,KILL 52

(2)杀掉会话,会引起事务回滚,同时释放排他锁

隔离级别


4.1 基本概念

「(1)隔离级别用来做什么」

  • a.隔离级别用于决定如何控制并发用户读写数据的操作

「(2)写操作」

  • a.任何对表做出修改的语句

  • b.使用排他锁

  • c.不能修改读操作获得的锁和锁的持续时间

「(3)读操作:」

  • a.任何检索数据的语句

  • b.默认使用共享锁

  • c.使用隔离级别来控制读操作的处理方式

4.2 隔离级别的分类

(1)未提交读 (READ UNCOMMITTED)

(2)已提交读(READ COMMITTED)(默认值)

(3)可重复读(REPEATABLE READ)

(4)可序列化(SERIALIZABLE)

(5)快照(SNAPSHOT)

(6)已经提交读快照(READ_COMMITTED_SNAPSHOT)

4.3 隔离级别的设置

「(1)设置整个会话的隔离级别」

SET TRANSACTION ISOLATION LEVEL <isolation name>;SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

「(2)用表提示设置查询的隔离级别」

SELECT ... FROM <table> WITH (<isolation name>);SELECT * FROM dbo.myProduct WITH (READCOMMITTED);

注意:

  • 1.设置会话选项的隔离级别时,隔离级别中的每个单词之间需要用空格分隔

  • 2.用表提示的隔离级别时,隔离级别中的每个单词之间不需要用空格分隔

  • 3.表提示的隔离级别有同义词,如:NOLOCK->READUNCOMMITTED,HOLDLOCK->REPEATABLEREAD

  • 4.隔离级别的严格性:1.未提交读<2.已提交读<3.可重复读<4.可序列化

  • 5.隔离级别越高,一致性越高,并发性越低

  • 6.基于快照的隔离级别,SQL Server将提交过的行保存到tempdb数据库中,当读操作发现行的当前版本和它们预期的不一致时,可以立即得到行的以前版本,从而不用请求共享锁也能取得预期的一致性

4.4 隔离级别的行为方式

4.4.1 未提交读 (READ UNCOMMITTED)

打开两个查询窗口,Connetion1,connection2

  • Step1: 执行Connection1的阶段2的SQL 语句,然后执行connection2的SQL语句

  • Step2: 执行Connection1的阶段3的SQL 语句,执行connection2的SQL语句

  • Step3: 执行Connection1的阶段4的SQL 语句,执行connection2的SQL语句

--阶段2UPDATE  myProductSET     price = price + 1WHERE   id = 1;  SELECT  id ,        priceFROM    dbo.myProductWHERE   id = 1;  --阶段3UPDATE  myProductSET     price = price + 5WHERE   id = 1;  SELECT  id ,        priceFROM    dbo.myProductWHERE   id = 1;  --阶段4COMMIT TRAN
--在阶段2执行之后SET TRAN ISOLATION LEVEL READ UNCOMMITTEDBEGIN TRAN;SELECT  id ,        priceFROM    dbo.myProductWHERE   id = 1 COMMIT TRAN;

两个事务的流程图:

1.未提交读 READ UNCOMMITTED

  • 阶段1:Price=10,事务A对myProduct表请求排他锁

  • 阶段2:事务A对myProduct表使用了排他锁,更新price = price + 1,然后事务A查询price的价格: price=11。事务B不请求任何锁,事务B在A更新Price之后进行查询,price=11

  • 阶段3:事务A更新price = price + 5,然后事务A查询price的价格,price = 16。事务B查询price的价格: price=16

  • 阶段4:事务A释放排他锁

  • 阶段5:事务A中查询price的价格:price = 16。事务B查询price的价格: price=16

「大家可以看到事务B有两种结果,这就是“未提交读 (READ UNCOMMITTED)”隔离级别的含义:」

(1)读操作可以读取未提交的修改(也称为脏读)。

(2)读操作不会妨碍写操作请求排他锁,其他事务正在进行读操作时,写操作可以同时对这些数据进行修改。

(3)事务A进行了多次修改,事务B在不同阶段进行查询时可能会有不同的结果。

4.4.2 已提交读(READ COMMITTED)(默认值)

打开两个查询窗口,Connetion1,connection2

Step1: 执行Connection1的SQL 语句

UPDATE` `dbo.myProduct ``SET` `price = price + 1 ``WHERE` `id=1SELECT` `* ``FROM` `dbo.myProduct ``WHERE` `id =1

Step2: 执行Connection2的SQL 语句

SET` `TRANSACTION` `ISOLATION` `LEVEL` `READ` `COMMITTEDSELECT` `* ``FROM` `dbo.myProduct ``WHERE` `id = 1

两个事务的流程图:

4.2.2.已提交读 READ COMMITTED

  • 阶段1:Price=10,事务A对myProduct表请求排他锁

  • 阶段2:事务A对myProduct表使用了排他锁,更新price = price + 1,然后事务A查询price的价格: price=11。然后事务B请求共享锁进行读操作,查询price,

由于在当前隔离级别下,事务A的排他锁和事务B的共享锁存在冲突,所以事务B需要等待事务A释放排他锁后才能读取数据。

  • 阶段3:事务A提交事务(COMMIT TRAN)

  • 阶段4:事务A提交完事务后,释放排他锁

  • 阶段5:事务B获得了共享锁,进行读操作,price=11

    「“已提交读 (READ UNCOMMITTED)”隔离级别的含义:」

(1)必须获得共享锁才能进行读操作,其他事务如果对该资源持有排他锁,则共享锁必须等待排他锁释放。

(2)读操作不能读取未提交的修改,读操作读取到的数据是提交过的修改。

(3)读操作不会在事务持续期间内保留共享锁,其他事务可以在两个读操作之间更改数据资源,读操作因而可能每次得到不同的取值。这种现象称为“不可重复读”。

4.4.3 可重复读(REPEATABLE READ)

打开两个查询窗口,Connetion1,connection2

Step1: 执行Connection1的SQL 语句

SET` `TRANSACTION` `ISOLATION` `LEVEL` `REPEATABLE` `READSELECT` `* ``FROM` `dbo.myProduct ``WHERE` `id = 1

Step2: 执行Connection2的SQL 语句

UPDATE` `dbo.myProduct ``SET` `price = price + 1 ``WHERE` `id=1  

演示与总结如下所示:

演示与总结

两个事务的流程图:

4.4.3.可重复读 REPEATABLE READ

  • 阶段1:Price=10,事务A对myProduct表请求共享锁

  • 阶段2:事务A对myProduct表使用了共享锁,事务A查询price的价格: price=10,事务A一直持有共享锁直到事务A完成为止。然后事务B请求排他锁进行写操作price=price+1,

由于在当前隔离级别下,事务A的共享锁和事务B请求的排他锁存在冲突,所以事务B需要等待事务A释放共享锁后才能修改数据。

  • 阶段3:事务A查询price, price=10, 说明事务B的更新操作被阻塞了,更新操作没有被执行。然后事务A提交事务(COMMIT TRAN)

  • 阶段4:事务A提交完事务后,释放共享锁

  • 阶段5:事务B获得了排他锁,进行写操作,price=11

**“可重复读 (REPEATABLE READ)”隔离级别的含义:  **

(1)必须获得共享锁才能进行读操作,获得的共享锁将一直保持直到事务完成之止。

(2)在获得共享锁的事务完成之前,没有其他事务能够获得排他锁修改这一数据资源,这样可以保证实现可重复的读取。

(3)两个事务在第一次读操作之后都将保留它们获得的共享锁,所以任何一个事务都不能获得为了更新数据而需要的排他锁,这种情况将会导致死锁(deadlock),不过却避免了更新冲突。

4.4.4 可序列化(SERIALIZABLE)

打开两个查询窗口,Connetion1,connection2
Step1: 执行Connection1的SQL 语句

BEGIN TRANSACTIONSET TRANSACTION ISOLATION LEVEL SERIALIZABLE   SELECT * FROM dbo.myProduct WHERE id = 1

Step2: 执行Connection2的SQL 语句

INSERT` `INTO` `dbo.myProduct(id, price) ``VALUES` `(1, 20)

演示与总结如下所示:

演示与总结

两个事务的流程图:

4.4.4.可序列化SERIALIZABLE

  • 阶段1:Price=10,事务A对myProduct表请求共享锁

  • 阶段2:事务A对myProduct表使用了共享锁,事务A查询id=1的price的价格:1行记录,price=10,事务A一直持有共享锁直到事务A完成为止。然后事务B请求排他锁进行插入操作id=1,price=20,

由于在当前隔离级别下,事务B试图增加能够满足事务A的读操作的查询搜索条件的新行,所以事务A的共享锁和事务B请求的排他锁存在冲突,事务B需要等待事务A释放共享锁后才能插入数据。

  • 阶段3:事务A查询出id=1的数据只有1行,说明事务B的插入操作被阻塞了,插入操作没有被执行。然后事务A提交事务(COMMIT TRAN)

  • 阶段4:事务A提交完事务后,释放共享锁

  • 阶段5:事务B获得了排他锁,进行插入操作,插入成功,查询出id=1的数据有两条-

「“可序列化(SERIALIZABLE)”隔离级别的含义:」

(1)必须获得共享锁才能进行读操作,获得的共享锁将一直保持直到事务完成之止。

(2)在获得共享锁的事务完成之前,没有其他事务能够获得排他锁修改这一数据资源,且当其他事务增加能够满足当前事务的读操作的查询搜索条件的新行时,其他事务将会被阻塞,直到当前事务完成然后释放共享锁,其他事务才能获得排他锁进行插入操作。

(3)事务中的读操作在任何情况下读取到的数据是一致的,不会出现幻影行(幻读)。

(4)范围锁:读操作锁定满足查询搜索条件范围的锁。

4.5 隔离级别总结

「脏读:」 读取未提交的更改。

「不可重复读:」 读操作不会在事务持续期间内保留共享锁,其他事务可以在两个读操作之间更改数据资源,读操作因而可能每次得到不同的取值。

「丢失更新:」 两个事务进行读操作,获得资源上的共享锁,读取完数据后,不再持有资源上的任何锁,两个事务都能更新这个值,最后进行更新的事务将会覆盖其他事务做的更改,导致其他事务更改的数据丢失。

「幻读:」 第一次和第二次读取到的数据行数不一致。

「范围锁:」 读操作锁定满足查询搜索条件范围的锁。

隔离级别总结

死锁

死锁

死锁是指一种进程之间互相永久阻塞的状态,可能涉及两个或更多的进程。

打开两个查询窗口,Connetion1,connection2

Step1: 执行Connection1的SQL 语句

SET` `TRANSACTION` `ISOLATION` `LEVEL` `READ` `COMMITTEDBEGIN` `TRANUPDATE` `dbo.myProduct ``SET` `price = price + 1 ``WHERE` `id=1SELECT` `* ``FROM` `dbo.myOrder ``WHERE` `id =1

Step2: 执行Connection2的SQL 语句

SET` `TRANSACTION` `ISOLATION` `LEVEL` `READ` `COMMITTEDBEGIN` `TRANUPDATE` `dbo.myOrder ``SET` `customer = ``'ddd'` `WHERE` `id = 1SELECT` `* ``FROM` `dbo.myProduct ``WHERE` `id = 1

演示与总结如下所示:

演示与总结

两个事务的流程图:

5.死锁 Dead Lock

  • 阶段1:Price=10,事务A对myProduct表请求排他锁。Customer = aaa,事务B对myOrder请求排他锁。

  • 阶段2:事务A对myProduct表使用了排他锁,更新price = price + 1。然后事务B对myOrder表使用了排他锁,更新customer=ddd。

  • 阶段3:事务A查询myOrder表,对myOrder表请求共享锁,因为事务A的请求的共享锁与事务B的排他锁冲突,所以事务A被阻塞。然后事务B查询myProduct表,对myProduct表请求共享锁,因为事务B的请求的共享锁与事务A的排他锁冲突,所以事务B被阻塞。

  • 阶段4:事务A等待事务B的排他锁释放,事务B等待事务A的排他锁释放,导致死锁。事务A和事务B都被阻塞了。

  • 阶段5:SQL Server在几秒之内检测到死锁,会选择一个事务作为死锁的牺牲品,终止这个事务,并回滚这个事务所做的操作。在这个例子中,事务A被终止,提示信息:事务(进程 ID 53)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。

「死锁 (Dead Lock)」” 的一些注意事项:

(1)如果两个事务没有设置死锁优先级,且两个事务进行的工作量也差不多一样时,任何一个事务都有可能被终止。

(2)解除死锁要付出一定的系统开销,因为这个过程会涉及撤销已经执行过的处理。

(3)事务处理的时间时间越长,持有锁的时间就越长,死锁的可能性也就越大,应该尽可能保持事务简短,把逻辑上可以不属于同一个工作单元的操作移到事务以外。

(4)上面的例子中,事务A和事务B以相反顺序访问资源,所以发生了死锁。如果两个事务按同样的顺序来访问资源,则不会发生这种类型的死锁。在不改变程序的逻辑情况下,可以通过交换顺序来解决死锁的问题。

更多阅读推荐

  • 放弃 Windows 后 ,开源操作系统能成为主流桌面系统吗?

  • 高校毕业生:今年“太惨了”,网友:更惨的可能还在后头!

  • 【我想进大厂】Redis夺命连环11问

  • 采摘工人月薪十万却无人应聘,英澳农场求助 AI

  • 错过了秋天的第一杯奶茶,不要错过秋天第一场黑客松

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

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

相关文章

uni-app中使用腾讯地图sdk(解析经纬度)获取用户所在位置信息

前言&#xff1a; 技术选定 https://lbs.qq.com/dev/console/custom/apply 具体步骤&#xff1a; 注册开发者账号、申请密钥、开通webserviceAPI服务、下载小程序SDK、微信后台配置请求request域名。 &#xff08; 请按官方完成以上操作&#xff1a;https://lbs.qq.com/mini…

4月数据库流行度排行出炉:MySQL 成事实王者

2020年4月DB-Engines 数据库流行度排行出炉。在本月的排行榜上&#xff0c;Oracle 较上月微涨 4.78 分&#xff0c;MySQL 微涨 8.62 分&#xff0c;甲骨文公司成为最大赢家。而微软的两个产品 Microsoft SQL Server 下降 14.43 分&#xff0c;Microsoft Access 下降 3.22分&…

MySQL 在 Mac 环境下的安装

目录 Mac 系统配置 MySql 数据库1. 安装 MySql 数据库2. 安装 MySql Workbench 可视化工具Mac 系统配置 MySql 数据库 1. 安装 MySql 数据库 1.1 双击打开安装包 mysql-8.0.19-macos10.15-x86_64.dmg: 1.2 双击 mysql-8.0.19-macos10.15-x86_64.pkg 运行安装包,并点击 继续…

微信小程序console.log出来的是object的问题解决方法

在开发微信小程序的时候&#xff0c;从后台传过来的数据没有问题&#xff0c;但是在开发的过程中&#xff0c;console.log出来的结果为object。 解决方案&#xff1a; 把加好改为逗号,即可

超大福利 | 这款免费 Java 在线诊断利器,不用真的会后悔!

线上系统为何经常出错&#xff1f;数据库为何屡遭黑手&#xff1f;业务调用为何频频失败&#xff1f;连环异常堆栈案&#xff0c;究竟是哪次调用所为&#xff1f; 数百台服务器意外雪崩背后又隐藏着什么&#xff1f;是软件的扭曲还是硬件的沦丧&#xff1f; 走进科学带你了解 A…

面试官:因为这个语言,我淘汰了90%的人!!

很多人都有这样的经历&#xff1a;大量重复性工作&#xff1b;日报、周报、各种报&#xff0c;无穷无尽&#xff1b;不计其数的数据提取琐碎繁杂的事务让工作的效率极低。如果可以一键完成就好了。对这些问题来说&#xff0c;最高效的解决途径就是 Python。1991 年&#xff0c;…

MySQL在Windows 环境中的安装

文章目录 MySQL 在 Windows 系统下的安装MySQL 在 Windows 系统下的安装 双击 mysql-installer-community-8.0.19.0.msi,启动 MySQL 安装程序。 如果弹框提示如下的警告信息,证明你的电脑需要安装额外的 .NET Framework 依赖包。此时,先退出 MySQL 的安装程序,然后双击 ND…

灵魂发明家自述:我就是靠这个创业成功的

扫描二维码&#xff0c;了解低代码的高科技 原文链接 本文为云栖社区原创内容&#xff0c;未经允许不得转载。

前端数据解构

案例&#xff1a; 数据如下&#xff1a; {success: true, code: 10000, data: {…}, message: "执行成功"} code: 10000 data:list: Array(7)0: {_id: "608b70ecf9d99a7594662466", id: "0", label: "热榜"}1: {_id: "608b70ec…

基于云存储网关的Veeam备份归档上云方案

前言 面对数据可靠性和合规性要求的不断增长&#xff0c;只备份一份数据已经不能满足用户对于数据可靠性的需求。传统备份厂商的异地备份方案是将用户生产环境里的数据备份至不同机柜或者异地机房来保护数据&#xff0c;规避单机房存在的机柜或机房断电断网等问题。公共云的出现…

阿里达摩院青橙奖“硬核10人”出炉,钟南山寄语青年科学家

9月9日&#xff0c;2020年阿里巴巴达摩院青橙奖获奖名单公布&#xff0c;梁文华等10位青年科学家获得达摩院的1000万元奖金。这群平均年龄不足32岁的科研后浪收到了中国工程院院士钟南山的鼓励&#xff1a;“你们处在最好的时候&#xff0c;要记得把握机遇。” 青橙奖是阿里巴巴…

vue 微信开发工具 Maximum call stack size exceeded

文章目录现象原因解决方案现象 某段代码出现了内存溢出的现象 原因 出现了死循环调用的代码片段 解决方案 仔细检查一下&#xff0c;很容易发现的 案例场景&#xff1a; [Vue warn]: Error in v-on handler: “RangeError: Maximum call stack size exceeded” (found in…

深源恒际上线二代个人信用报告OCR识别服务

1月中旬&#xff0c;央行征信中心启动了二代征信系统切换上线工作&#xff0c;开始面向社会公众和金融机构开放二代格式信用报告查询服务。随后&#xff0c;深源恒际及时跟进信用报告OCR识别产品的升级工作。目前产品迭代已完成&#xff0c;深源恒际将于本周内上线二代个人信用…

直播预告 | 阿里巴巴自研代码管理平台技术解密

4月23日&#xff0c;企业级一站式DevOps平台——阿里云云效正式开启公测&#xff0c;我们特别策划了《为云研发而生&#xff0c;解密云效公测版专场》视频直播活动&#xff0c;邀请了5位阿里巴巴技术专家通过视频直播的方式与大家在线交流&#xff0c;分享云效产品的亮点和技术…

1024程序员节开源技术英雄会,参会“英雄榜”发榜

10月23-25日&#xff0c;由CSDN等多家单位精心筹划的“长沙 中国1024程序员节”将盛大举行。程序员节活动以开源为主议题&#xff0c;包括2场岳麓尖峰对话&#xff1b;2020开源技术英雄大会&#xff1b;10场热门技术分论坛/峰会&#xff1b;创意集市&#xff1b;体验感超强的科…

uni-app 微信小程序授权登录

文章目录一、appID相关申请和配置1. appid获取方式2. appID配置二、获取用户基础数据2.1. 获取用户信息2.2. 获取用户信息2三、调用登录api3.1. 登录api3.2. 案例代码四、获取唯一标识信息4.1. 官网文档4.2. 接口简述五、绑定用户 实现登录5.1. 代码案例&#xff08;未封装&…

从图森未来的数据处理平台,看Serverless工作流应用场景

Serverless工作流来了&#xff01; 发布会传送门 抢先了解Serverless技术干货 4月&#xff0c;阿里云Serverless工作流正式商业化&#xff0c;这是一款用于协调多个分布式任务执行的全托管 Serverless 云服务。产品致力于简化开发和运行业务流程所需要的任务协调、状态管理以及…

uniapp 开发基础环境搭建和配置

文章目录一、下载并安装开发工具1. 官网下载2. 点击 DOWNLOAD3. 版本选择二、安装 sass 依赖2.1. 打开 HBuilder X2.2. 打开插件地址2.3. 导入插件2.4. 在弹出框中点击2.5. 点击【是】2.6. 下载状态2.7. 等待完成即可三、创建 uni-app 项目3.1. 创建项目3.2. 项目目录介绍一、下…

大厂技术文档:Python基础+爬虫+数据分析+面试经精选

有段时间没跟各位粉丝分享编程资源福利了&#xff0c;看了下自己的资料夹&#xff0c;就剩下我认为比较好的Python学习资料了。相信这套资料可以对你进阶高级工程师有帮助&#xff01;为什么只有Python这么火&#xff0c;能有机会成为通用语言&#xff1f;核心还是因为企业需要…

金融业务数字化,用户体验和安全防护双重挑战,你该怎么办?

在数字化转型的浪潮中&#xff0c;金融行业一直是最活跃的行业之一。受到新冠疫情影响&#xff0c;各商业银行、券商、保险企业的线上流量迅速攀升&#xff0c;线上金融业务将从互金时代直接跃迁到全面线上化时代。2月24日&#xff0c;中国银保监会下发的《关于进一步做好疫情防…