Java分布式事务(三)

news2024/11/16 5:35:34

文章目录

    • 🔥MySQL事务-MySQL中锁的分类
    • 🔥MySQL事务-MySQL中的死锁问题

🔥MySQL事务-MySQL中锁的分类

MySQL中锁的分类
在这里插入图片描述

从本质上讲,锁是一种协调多个进程或多个线程对某一资源的访问的机制,MySQL使用锁和MVCC机制实现了事务隔离级别。

锁的分类
在这里插入图片描述

悲观锁和乐观锁
悲观锁
顾名思义,悲观锁对于数据库中数据的读写持悲观态度, 即在整个数据处理的过程中,它会将相应的数据锁定。在数据库中,悲观锁的实现需要依赖数据库提供的锁机制,以保证对数据库加锁后,其他应用系统无法修改数据库中的数据。
在这里插入图片描述

注意:
在悲观锁机制下,读取数据库中的数据时需要加锁,此时不能对这些数据进行修改操作。修改数据库中的数据时也需要加锁,此时不能对这些数据进行读取操作。

乐观锁
悲观锁会极大地降低数据库的性能,特别是对长事务而言,性能的损耗往往是无法承受的。乐观锁则在一定程度上解决了这个问题。
在这里插入图片描述

注意⭐:
实现乐观锁的一种常用做法是为数据增加一个版本标识,如果是通过数据库实现,往往会在数据表中增加一个类似version的版本号字段。

读锁和写锁

读锁
读锁又称为共享锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。

写锁
写锁又称为排他锁,排他锁就是不能与其他所并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。

⭐需要注意的是,对同一份数据,如果加了读锁,则可以继续为其加读锁,且多个读锁之间互不影响,但此时不能为数据增加写锁。一旦加了写锁,则不能再增加写锁和读锁。因为读锁具有共享性,而写锁具有排他性。

表锁、行锁和页面锁

表锁
表锁也称为表级锁,就是在整个数据表上对数据进行加锁和释放锁。典型特点是开销比较小,加锁速度快,一般不会出现死锁,锁定的粒度比较大,发生锁冲突的概率最高,并发度最低。

手动增加表锁

mysql> lock table userinfo read;
Query OK, 0 rows affected (0.00 sec)
mysql> lock table userinfo write;
Query OK, 0 rows affected (0.00 sec)

查看数据表上增加的锁

show open tables;

在这里插入图片描述

删除表锁

行锁
行锁也称为行级锁,就是在数据行上对数据进行加锁和释放锁。典型特点是开销比较大,加锁速度慢,可能会出现死锁,锁定的粒度最小,发生锁冲突的概率最小,并发度最高。
⭐行锁主要加在索引上,如果对非索引的字段设置条件进行更新,行锁可能会变成表锁。
⭐InnoDB的行锁是针对索引加锁,不是针对记录加锁,并且加锁的索引不能失效,否则行锁可能会变成表锁。
⭐锁定某一行时,可以使用lock in share mode命令来指定共享锁,使用for update命令来指定排他锁,例如下面的SQL语句。

select * from userinfo where id = 1 for update;

页面锁
页面锁也称为页级锁,就是在页面级别对数据进行加锁和释放锁。对数据的加锁开销介于表锁和行锁之间,可能会出现死锁,锁定的粒度大小介于表锁和行锁之间,并发度一般。
在这里插入图片描述

间隙锁和临键锁

间隙锁
在MySQL中使用范围查询时,如果请求共享锁或排他锁,InnoDB会给符合条件的已有数据的索引项加锁。如果键值在条件范围内,而这个范围内并不存在记录,则认为此时出现了“间隙(也就是GAP)”。InnoDB存储引擎会对这个“间隙”加锁,而这种加锁机制就是间隙锁(GAP Lock)。

例如,userinfo数据表中存在如下数据。
在这里插入图片描述
此时,userinfo数据表中的间隙包括id为(3,15]、(15,20]、
(20,正无穷]的三个区间。如果执行如下命令,将符合条件的用户的账户余额增加100元。
update userinfo set balance = balance + 100 where id > 5
and id <16;
则其他事务无法在(3,20]这个区间内插入或者修改任何数据。这里需要注意的是,间隙锁只有在可重复读事务隔离级别下才会生效。

临键锁
临键锁(Next-Key Lock)是行锁和间隙锁的组合,例如上面例子中的区间(3,20]就可以称为临键锁。

🔥MySQL事务-MySQL中的死锁问题

在这里插入图片描述

什么是死锁
死锁是并发系统中常见的问题,同样也会出现在数据库MySQL的并发读写请求场景中。当两个及以上的事务,双方都在等待对方释放已经持有的锁或因为加锁顺序不一致造成循环等待锁资源,就会出现“死锁”。

Deadlock found when trying to get lock...

举例来说 A 事务持有 X1 锁 ,申请 X2 锁,B事务持有 X2 锁,申请X1 锁。A 和 B 事务持有锁并且申请对方持有的锁进入循环等待,就造成了死锁。
在这里插入图片描述

出现死锁的几个要素:
⭐两个或者两个以上事务
⭐每个事务都已经持有锁并且申请新的锁
⭐锁资源同时只能被同一个事务持有或者不兼容
⭐事务之间因为持有锁和申请锁导致彼此循环等待

第一步
打开终端A,登录MySQL,将事务隔离级别设置为可重复读,开启事务后为userinfo数据表中id为1的数据添加排他锁,如下所示。

mysql> set session transaction isolation level
repeatable read;
Query OK, 0 rows affected (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from userinfo;
+----+-------+---------+
| id | name  | balance |
+----+-------+---------+
|  1 | Java  |  100.00 |
|  2 | MySQL |  200.00 |
+----+-------+---------+
2 rows in set (0.00 sec)

第二步
打开终端B,登录MySQL,将事务隔离级别设置为可重复读,开启事务后为userfinfo数据表中id为2的数据添加排他锁,如下所示。

mysql> set session transaction isolation level
repeatable read;
Query OK, 0 rows affected (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from userinfo where id = 2;
+----+-------+---------+
| id | name  | balance |
+----+-------+---------+
|  2 | MySQL |  200.00 |
+----+-------+---------+
1 row in set (0.00 sec)

第三步
在终端A为userinfo数据表中id为2的数据添加排他锁,如下所示。
⭐此时,线程会一直卡住,因为在等待终端B中id为2的数据释放排他锁。

第四步
在终端B中为userinfo数据表中id为1的数据添加排他锁,如下所示。

mysql> select * from userinfo where id =1 for
update;
ERROR 1213 (40001): Deadlock found when trying
to get lock; try restarting transaction

通过如下命令可以查看死锁的日志信息。

show engine innodb status\G

⭐通过命令行查看LATEST DETECTED DEADLOCK选项相关的信息,可以发现死锁的相关信息,或者通过配置
innodb_print_all_deadlocks(MySQL 5.6.2版本开始提供)参数为ON,将死锁相关信息打印到MySQL错误日志中。

如何避免死锁
⭐合理的设计索引,区分度高的列放到组合索引前面,使业务SQL 尽可能通过索引定位更少的行,减少锁竞争
⭐调整业务逻辑 SQL 执行顺序, 避免 update/delete 长时间持有锁的 SQL 在事务前面。
⭐合理设计索引,尽量缩小锁的范围。
⭐尽量减少查询条件的范围,尽量避免间隙锁或缩小间隙锁的范围。
⭐尽量控制事务的大小,减少一次事务锁定的资源数量,缩短锁定资源的时间。
⭐如果一条SQL语句涉及事务加锁操作,则尽量将其放在整个事务的最后执行。
⭐优化 SQL 和表设计,减少同时占用太多资源的情况。比如说,减少连接的表 ,将复杂 SQL 分解 为多个简单的 SQL。

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

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

相关文章

TIA博途中将硬件目录更改为中文的具体方法演示

TIA博途中将硬件目录更改为中文的具体方法演示 基本步骤可参考如下: 第一步: 第二步: 具体的操作演示: 如下图所示,在所示的目录中找到zh-chs文件夹,删除或修改文件夹的名称均可,这里建议大家修改文件夹的名称,防止以后需要恢复成英文目录, 如下

3DEXPERIENCE Works 成为了中科赛凌实现科技克隆环境的催化剂

您的企业是否想过实现设计数据的统筹管理&#xff0c;在设计上实现标准化&#xff0c;并把每位设计工程师串联起来协同办公?中科赛凌通过使用3DEXPERIENCE Works 实现了上述内容&#xff0c;一起来看本期案例分享吧!中科赛凌 通过其自主研发的单压缩机制冷技术实现零下190℃制…

Hbase 的复制

HBase默认采用异步复制的方式同步数据&#xff0c;即客户端执行完put之后&#xff0c;RegionServer的后台线程不断地推送HLog的Entry到Peer集群。这种方式一般能满足大多数场景的需求&#xff0c;例如跨集群数据备份、HBase集群间数据迁移等。但是HBase 1.x版本的复制功能&…

【群晖Drive私有云】利用cpolar内网穿透实现公网远程群晖Drive

文章目录前言1.群晖Synology Drive套件的安装1.1安装Synology Drive套件1.2 设置Synology Drive套件1.3 局域网内电脑测试和使用2.使用cpolar远程访问内网Synology Drive2.1 Cpolar云端设置2.2 Cpolar本地设置2.3 测试和使用3. 结语前言 群晖作为专业的数据存储中心&#xff0…

路径规划 | 图解动态A*(D*)算法(附ROS C++/Python/Matlab仿真)

目录0 专栏介绍1 什么是D*算法&#xff1f;2 D*算法核心概念一览3 D*算法流程图4 步步图解&#xff1a;算法实例5 算法仿真与实现5.1 ROS C实现5.2 Python实现0 专栏介绍 &#x1f525;附C/Python/Matlab全套代码&#x1f525;课程设计、毕业设计、创新竞赛必备&#xff01;详…

【工具】logseq 使用分享

Github: https://github.com/logseq/logseq 三月八日国际劳动妇女节&#xff0c;当然要分享一款好用的记事本软件。 这次介绍的笔记本软件叫 logseq。 logseq 与传统的笔记软件不同&#xff0c;传统的笔记软件有各种数据单元&#xff08;post、title、refs、category、tags、…

智慧灌区信息化解决方案

系统概述智慧灌区信息化解决方案主要对对灌区的水情、雨情、土壤墒情、气象等信息进行监测&#xff0c;对重点区域进行视频监控&#xff0c;同时对泵站、闸门进行远程控制&#xff0c;实现了信息的测量、统计、分析、控制、调度等功能。为灌区管理部门科学决策提供了依据&#…

VITA/PYTHON/LUPA families

Image Sensor Group Top to Bottom Portfolio in Industrial Imaging Machine Vision • Factory automation and inspection • Robotic vision • Biometrics High-End Surveillance • Aerial Surveillance • Intelligent Traffic Systems (ITS) • Mapping Medical and Sc…

【UML】软件需求说明书

目录&#x1f981; 故事的开端一. &#x1f981; 引言1.1编写目的1.2背景1.3定义1.4参考资料二. &#x1f981; 任务概述2.1目标2.2用户的特点2.3假定和约束三. &#x1f981; 需求规定3.1 功能性需求3.1.1系统用例图3.1.2用户登录用例3.1.3学员注册用例3.1.4 学员修改个人信息…

Uipath DataTable-FilterDataTable(筛选数据表)

FilterDataTable(筛选数据表) 活动描述 FilterDataTable(筛选数据表)&#xff1a;通过在“筛选器向导”窗口中指定条件来筛选“DataTable”数据表变量&#xff0c;可以根据在该向导中指定的逻辑条件保留或删除行或列。使用如下图&#xff1a; FilterDataTable(筛选数据表)属…

Graph Partition: Edge cut and Vertex cut

Graph PartitionEdge cut and Vertex cutEdge cutVertex cut实际如何进行点分割和边分割的呢&#xff1f;Graph store format情况1&#xff1a;按照边列表存储&#xff1a;情况2&#xff1a;按照邻接表存储&#xff1a;Edge cut and Vertex cut 图结构描述了数据流动&#xff…

项目经理必看!常用的项目管理工具及方法

本文为你介绍&#xff1a;1、好用的项目管理工具&#xff1b;2、项目管理方法 随着企业日益复杂的业务流程和庞大的项目数量&#xff0c;如何高效地管理项目成为了必须面对的挑战&#xff0c;许多企业开始使用项目管理工具和方法来更好地管理项目。 今天我就来介绍几个好用的…

【UE】大世界子关卡StreamingLevel加载流程

受限于硬件&#xff0c;当项目需要制作大世界的时候&#xff0c;整张大地图无法也没必要全部加载进内存。和所有支持大世界的引擎一样&#xff0c;UE采取了分块加载的方式&#xff1a;除了一个持久关卡&#xff08;PersistentLevel&#xff09;的加载以外&#xff0c;采用的都是…

网络通信快速入门

&#x1f3e1;个人主页 &#xff1a; 守夜人st &#x1f680;系列专栏&#xff1a;Java …持续更新中敬请关注… &#x1f649;博主简介&#xff1a;软件工程专业&#xff0c;在校学生&#xff0c;写博客是为了总结回顾一些所学知识点 目录网络编程实现网络编程的三要素&#x…

少儿编程 电子学会图形化编程等级考试Scratch一级真题解析(选择题)2022年12月

少儿编程 电子学会图形化编程等级考试Scratch一级真题解析2022年12月 选择题(共25题,每题2分,共50分) 1、小明想在开始表演之前向大家问好并做自我介绍,应运行下列哪个程序 A、 B、 C、 D、 答案:D

【MySQL】第17章_触发器

第17章_触发器 在实际开发中&#xff0c;我们经常会遇到这样的情况&#xff1a;有 2 个或者多个相互关联的表&#xff0c;如商品信息和库存信息分别存放在 2 个不同的数据表中&#xff0c;我们在添加一条新商品记录的时候&#xff0c;为了保证数据的完整性&#xff0c;必须同时…

Linux - 内存性能评估

文章目录概述free 命令指定的时间段内不间断地监控内存的使用情况通过watch与free相结合动态监控内存状况vmstat命令监控内存“sar –r”命令组合小结概述 内存的管理和优化是系统性能优化的一个重要部分&#xff0c;内存资源的充足与否直接影响应用系统的使用性能。在进行内存…

C语言-基础了解-07-C运算符

c运算符 一、算术运算符 假设变量 A 的值为 10&#xff0c;变量 B 的值为 20&#xff0c;则&#xff1a; 实例 #include <stdio.h>int main() {int a 21;int b 10;int c ;c a b;printf("Line 1 - c 的值是 %d\n", c );c a - b;printf("Line 2 - …

机器学习100天(四十一):041 对偶支持向量机-公式推导

《机器学习100天》完整目录:目录 机器学习 100 天,今天讲的是:对偶支持向量机-公式推导! 本节主要延续上一节的内容,推导线性支持向量机的对偶形式。本节内容包含的数学理论和推导很多,我尽量简化其中的数学部分,只做感性的介绍,便于大家在理解的同时不受数学复杂公式…

ubuntu 18.04 虚拟机分区扩容

我的虚拟机存在一个问题&#xff0c;原来分配的是60G的空间&#xff0c;但实际只用了30G就已经最显示空间已经满&#xff0c;没办法使用:通过fdisk -l查看分区情况查看LVM卷组的信息Free PE / Size 7551 / <29..50 GiB&#xff0c;这是还可以扩充的大小#lvextend -L 10G /de…