0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

浅谈管理并发数据访问:乐观并发控制、悲观并发控制

西西 来源:博客园 作者: 深圳大漠 2020-09-22 15:37 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1.并发冲突

当两个进程试图在同一时间修改同一数据,就会产生冲突。

2.并发控制

有两种方式管理并发数据访问:乐观并发控制、悲观并发控制。

这两种控制模式的区别在于,是在冲突发生前进行防止,还是在发生后采用某种方法来处理冲突。

3.悲观并发控制

悲观并发模式假定系统中存在足够多的数据修改操作,以致任何确定的读操作都可能会受到由别的用户所制造的数据修改的影响。

也就是说,悲观并发模式假定冲突总是会发生的。

悲观并发控制是通过独占正在被读取的数据来避免冲突。

但是独占数据会导致其它进程无法修改该数据,进而产生阻塞——读数据和写数据会互相阻塞。

4.乐观并发控制

乐观并发模式假定系统的数据修改操作只会生产非常少的冲突,也就是说任何进程都不太可能修改别的进程正在访问的数据。

乐观并发模式下,读数据和写数据之间不会发生冲突,只有写数据与写数据之间会发生冲突。即读数据不会产生阻塞,只有写数据才会产生阻塞。

5.并发冲突生产的问题

5.1.丢失更新(Lost updates)

两个进程同时读取一笔数据,然后进行修改,那么后提交的数据会覆盖先提交的数据。

如果数据允许覆盖式更新(比如用户姓名),那么丢失更新并不算太大的问题,如果数据是累加式更新(比如库存数量),那么丢失更新是非常严重的问题,并且在非并发模式下无法重复问题的发生。

5.2.脏读(Dirty reads)

当一个进程更新了数据,但(事务)未提交,这时候另一个进程读取同一笔数据,如果前一个进程取消了更新(事务回滚),那么后一个进程读取的就是脏数据。

脏读会产生严重的问题,在任何情况下都是不允许的。

5.3.不可重复读(Non-repeatable reads)

当一个进程读取了一笔数据后,另一个进程更新了同一笔数据,然后第一个进程再次读取同一笔数据,却得到了与第一次读取不同的结果。

在事务A更新记录之后(update Customers set Name = 'B' where Name = 'A'),事务B读取相同记录(select Name form Customers where Name = 'A'),但事务B拿到的是事务A更新之后的数据(Customers.Name的值为'B'),在事务B读取记录之后,事务A进行了事务回滚(Customers.Name的值为'A'),导致事务B的数据是不真实的。

5.4.幻读(Phantoms)

幻读与脏读的相似之处在于:两者都是两次读取的结果不一致。

不同之处在于:幻读是两次读取的记录数量不一致,而脏读是两次读取的记录的数据不一致。

事务A读取记录之后(select * from Customers where Name like 'A%'),事务B又插入了符合事务A读取条件的新记录(insert into Customers(Name) values('AAA')),那么当事务A再用相同条件读取记录时,得到的集合却与上一次读取不同(多了记录)。

6.隔离级别

SQL Server2005支持5种隔离级别来控制冲突。其中三种只在悲观并发模式中使用,一种只在乐观并发模式中使用,另一个可以在两种模式中使用。

6.1.未提交读(Uncommitted Read)

未提交读只能防止“丢失更新”问题,其它问题不能防止。

未提交读是针对阻塞太频繁的悲观并发控制,因为它只是忽略了锁,而不保障事务的一致性。

6.2.已提交读(Read Committed)

已提交读既可以是乐观的也可以是悲观的,这取决于数据库的read_committed_snapshot设置。默认情况下这个选项是关闭的,所以该隔离级别默认情况下是采用悲观并发控制。

已提交读可以防止脏读问题。

6.3.可重复读(Repeatable Read)

可重复读是一种悲观的隔离级别。它在已提交读的基础上增加了新特性:确保当事务重新访问数据或查询被再一次执行时,数据将不会再发生改变。

可重复读不但可以防止脏读问题,还可以防止不可重复读问题,但是不能防止幻读问题。

注意,可重复读的资源开销是很大的,事务中所有的数据必须等待事务完成之后才能访问。

6.4.快照(Snapshot)

快照是一种乐观隔离级别。

Snapshot事务中任何语句所读取的记录,都是事务启动时的数据。

这相当于事务启动时,数据库为事务生成了一份专用“快照”。

在当前事务中看到不其它事务在当前事务启动之后所进行的数据修改。

Snapshot事务不会读取记录时要求锁定,读取记录的Snapshot事务不会锁住其它事务写入记录,写入记录的事务也不会锁住Snapshot事务读取数据。

快照隔离级别的事务不是串行执行的,两个进程同时使用快照隔离,如果它们执行多次,可能最终产生的结果不会一致。(这段话要证实)

6.5.可串行化(Serializable)

可串行化是一种悲观隔离级别。它在可重复读的基础上增加了新的特性:确保在两次查询的中间,不会增加新的行。

可串行化是最健壮的悲观隔离级别,因为它防止了并发冲突产生的4个问题。

可串行化也是资源开销最大的措施。当使用可串行化隔离时,如果SQL的条件字段没有索引,那么SQL Server会产生表级锁。

6.6.总结

7.锁

7.1.死锁

当二或多个工作各自具有某个资源的锁定,但其它工作尝试要锁定此资源,而造成工作永久封锁彼此时,会发生死锁。例如:

1.事务A取得数据列1的共享锁定。

2.事务B取得数据列2的共享锁定。

3.事务A现在要求数据列2的独占锁定,但会被封锁直到事务B完成并释出对数据列2的共享锁定为止。

4.事务B现在要求数据列1的独占锁定,但会被封锁直到事务A完成并释出对数据列1的共享锁定为止。

等到事务B完成后,事务A才能完成,但事务B被事务A封锁了。这个状况也称为「循环相依性」(Cyclic Dependency)。事务A相依于事务B,并且事务B也因为相依于事务A而封闭了这个循环。

例如以下操作就会产生死锁,两个连接互相阻塞对方的update。

连接1:

begin tran

select * from customers

update customers set CompanyName = CompanyName

waitfor delay '00:00:05'

select * from Employees

–因为Employees被连接2锁住了,所以这里会阻塞。

update Employees set LastName = LastName

commit tran

连接2:

begin tran

select * from Employees

update Employees set LastName = LastName

waitfor delay '00:00:05'

select * from customers

--因为customers被连接1锁住了,所以这里会阻塞。

update customers set CompanyName = CompanyName

commit tran

SQL Server遇到死锁时会自动杀死其中一个事务,而另一个事务会正常结束(提交或回滚)。

SQL Server对杀死的连接返回错误代码是1205,异常提示是:

Your transaction (process ID #52) was deadlocked on {lock | communication buffer | thread} resources with another process and has been chosen as the deadlock victim. Rerun your transaction.

除了Read Uncommitted和Snapshot,其它类型的事务都可能产生死锁。

7.2.悲观锁

悲观锁是指假设并发更新冲突会发生,所以不管冲突是否真的发生,都会使用锁机制。

悲观锁会完成以下功能:锁住读取的记录,防止其它事务读取和更新这些记录。其它事务会一直阻塞,直到这个事务结束。

悲观锁是在使用了数据库的事务隔离功能的基础上,独享占用的资源,以此保证读取数据一致性,避免修改丢失。

悲观锁可以使用Repeatable Read事务,它完全满足悲观锁的要求。

7.3.乐观锁

乐观锁不会锁住任何东西,也就是说,它不依赖数据库的事务机制,乐观锁完全是应用系统层面的东西。

如果使用乐观锁,那么数据库就必须加版本字段,否则就只能比较所有字段,但因为浮点类型不能比较,所以实际上没有版本字段是不可行的。

7.4.悲观离线锁

悲观离线锁是应用程序级别的机制,它是由应用程序实现的,不是数据库实现的。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 死锁
    +关注

    关注

    0

    文章

    26

    浏览量

    8339
  • 并发控制机制

    关注

    0

    文章

    2

    浏览量

    5708
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Java并发编程的“基石”——多线程概念初识

    AI 算力调度底层:Java 并发基石与未来技术融合 当我们在屏幕前流畅地与大语言模型对话,或是看着自动驾驶系统瞬间处理海量视觉数据时,往往只会惊叹于 AI 算法的精妙。然而,在这层绚丽的应用外衣
    发表于 04-16 18:50

    微课-掌握Java并发编程的“基石”,入门并发编程

    未来高并发系统底层逻辑:从入门掌握 Java 并发编程基石 在人类商业文明向数字化全面迁移的宏大进程中,有一条隐秘但铁一般的经济学法则正在被无限放大:在算力、存储和网络带宽构成的基础设施之上,系统
    的头像 发表于 04-14 14:25 233次阅读

    FSC-BW5028MV适配车载多场景方案:WiFi7+蓝牙5.4 让音频与数据并发稳定输出

    了更高要求:既要高吞吐与低时延,也要具备多链路并发能力与稳定的长期运行特性。因此,讨论车载无线方案时,应首先回到技术本身:Wi‑Fi 7负责高带宽数据承载,蓝牙 5.4 负责低功耗控制与音频/外设连接,两者协同构成车内无线基础能
    的头像 发表于 04-09 16:12 170次阅读

    Nginx高并发连接调优实战手册

    Nginx 的高性能源自其事件驱动架构。与 Apache 的"每连接一线程"模型不同,Nginx 使用单线程事件循环处理数千个并发连接。理解这套架构是调优的前提。
    的头像 发表于 03-16 15:28 634次阅读

    Go 语言高并发服务设计与性能调优实战:从万级到百万级并发的演进之路

    在2026年的今天,Go 语言已成为高并发后端服务的首选语言。根据 Stack Overflow 最新开发者调查: 指标 数据 Go 语言采用率 后端服务中占比 42% 平均并发能力 单节点
    发表于 02-18 19:19

    弹性负载均衡:现代 IT 架构的高可用与高并发基石

    前言在数字化浪潮下,互联网服务的访问量呈爆炸式增长,单台服务器早已难以承载海量并发请求。此时,负载均衡(LoadBalancing)技术应运而生,成为优化资源分配、提升系统性能的核心支撑。作为现代
    的头像 发表于 01-20 09:58 404次阅读
    弹性负载均衡:现代 IT 架构的高可用与高<b class='flag-5'>并发</b>基石

    一文说透了如何实现单片机的多任务并发

    在嵌入式系统开发中,多任务并发是非常常见的,对于处理复杂的应用场景、提升系统的并发能力、提高系统的实时性等方面都有很大好处。在单片机中实现多任务并发是非常重要的,本文将为大家介绍如何在单片机中实现
    发表于 01-06 06:46

    华为陈实出席AfricaCom 2025并发表主题演讲

    在AfricaCom 2025展会期间,华为无线网络产品线营销副总裁陈实出席以“推动智能连接,实现商业成功”为主题的MBB峰会,并发表“创新开启非洲移动产业黄金十年”主题演讲,以“新流量、新体验、新商业、新联接、新节能”五大场景化创新,携手产业解锁增长新动能,助力非洲移动通信产业实现高质量发展。
    的头像 发表于 11-12 11:26 1208次阅读

    Swift 的并发系统并行运行多个任务

    ​​前言 Swift 内置并发系统的好处之一是它可以更轻松地并行执行多个异步任务,这反过来又可以使我们显着加快可以分解为单独部分的操作。 在本文中,让我们看一下几种不同的方法,以及这些技术中的每一种
    的头像 发表于 11-11 11:33 627次阅读

    工业物联网数据中台的高并发性有什么作用

    工业物联网数据中台的高并发性是保障其在复杂工业场景下稳定运行的核心能力之一。它的核心作用是确保大量设备同时接入和数据传输时,系统依然能高效处理、不卡顿、不丢失数据,能够在单位时间内高效
    的头像 发表于 10-28 11:28 459次阅读
    工业物联网<b class='flag-5'>数据</b>中台的高<b class='flag-5'>并发</b>性有什么作用

    如何理解工业数据中台的高并发能力

    工业数据中台的高并发能力是指其在同一时间段内高效处理大量设备数据读写、分析请求的能力,这是保障工业数据实时采集、传输、处理与决策响应稳定性和高效性的关键。以下从核心价值、技术实现、应用
    的头像 发表于 10-15 11:49 506次阅读

    创建并发布测试版本(一)

    创建并发布测试版本,并选择您要分发的测试群组。邀请测试最多允许100个版本同时在架,邀请测试和公开测试的总计版本数量不超过100个。 1.在左侧导航栏选择“应用测试>版本列表”,进入
    发表于 09-16 15:21

    Nginx高并发优化方案

    作为一名在生产环境中摸爬滚打多年的运维工程师,我见过太多因为Nginx配置不当导致的性能瓶颈。今天分享一套完整的Nginx高并发优化方案,帮助你的系统从10万QPS突破到百万级别。
    的头像 发表于 08-13 15:51 1369次阅读

    第三届大会回顾第3期 | FFRT并发框架在OpenHarmony中的设计与实践

    ,特别是在多核处理器上,可以显著提高程序的运行速度和整体性能,从而改善用户体验。OpenHarmony的FFRT并发编程模型为开发者提供了构建异步并发任务的能力,以更高效地开发和管理并发
    的头像 发表于 06-21 16:53 1584次阅读
    第三届大会回顾第3期 | FFRT<b class='flag-5'>并发</b>框架在OpenHarmony中的设计与实践

    鸿蒙5开发宝藏案例分享---应用并发设计

    ?** 鸿蒙并发编程实战指南:解锁ArkTS多线程黑科技** 嘿,开发者朋友们! 今天给大家扒一扒鸿蒙官方文档里藏着的并发编程宝藏—— 100+实战场景解决方案 !从金融理财到游戏开发,从折叠屏适配
    发表于 06-12 16:19