精华内容
下载资源
问答
  • 并发控制机构的功能
    2019-10-03 13:57:37

    并发的结构(模型)由控制结构确定

    转载于:https://www.cnblogs.com/feng9exe/p/10778106.html

    更多相关内容
  • Splashtop为全球的跨国企业和中小型企业、教育机构、托管服务供应商(MSP)和个人提供安全且易于管理的远程控制和远程支持软件及服务。经过17年的发展,Splashtop现在拥有3000万全球用户、20万企业用户,支持会话...

    如何选择一块真正“好用的、性能高”的远程控制软件

    无论是开发人员、运维人员、测试人员,还是非从事互联网工作的其他人员,在工作中肯定会存在需要远程控制其他电脑的需求。

    比如下面几个经常会遇到的场景:

    • 例如今天开会使用的报表是昨日在家中加班完成的,但是忘记拷贝到U盘,马上就要开会了,文件却不在手里,从而影响工作。
    • 当平台出现了故障,而运维却不在工位,也不在家中,手里没有电脑办公。
    • 开发人员在公司、家写了某个功能的代码, 但是没有把代码传到正在使用的电脑上。
    • 远程办公,家里有电脑,公司的电脑不想带回去,太麻烦。
    • 我们都是知识类博主,当粉丝按照我们写的文章学习时,遇到了问题需要我们的支持。

    基于以上这些场景,我们可以实现准备有一款好用的远程控制软件,只要双方电脑都能上网,无论在何时何地,都可以轻松的连接被控端,根据需要去操作电脑。

    在选择一款远程工具时,需要从一些几个方面去考虑:

    • 远程速度
    • 使用过程中是否卡顿
    • 清晰度是否高
    • 延迟速度如何

    远程软件随着市场的发展,产品越来越多,且都有手机客户端,可以保证我们随时随地都能远程控制,例如常见的向日葵,好几年前就有了,之前我也使用向日葵,但是近2年体验过程中,发现非常卡顿,几乎操作不了被控端,久而久之换成了todesk,但是todesk的app客户端使用起来较为别扭。

    绕了这么一圈,就不卖关子了,今天就是要给大家推荐一款**“好用且性能高”**的远程控制软件,它就是Splashtop ,一款非常好用的远程控制软件,性能方面非常强悍。用户评价画风基本是:“画面清晰,延迟很低,价格合理。”影视、游戏、设计行业远程办公,对于远程画面的清晰度和流畅度要求很高,就特别喜欢 Splashtop。

    Splashtop远程控制软件的特性

    • Splashtop远程软件的数据传输由 AES-256 和 TLS 加密;具备双因素验证、单点登录、设备认证等安全功能;符合 SOC2、GDPR、CCPA、HIPAA、PCI 等行业标准或法规要求。

    • Splashtop远程软件支持跨平台、跨设备、跨系统远程互联,随心所欲;支持 Windows、Mac、Linux、iOS、安卓等主流平台进行远程控制。

    • Splashtop远程软件的画面清晰、快速流畅,画质高达4K 60帧,低延迟、不卡顿。高性能引擎让用户可以流畅运行视频编辑、图形设计、动画、编码等专业软件。在低带宽的网络环境下,也能维持稳定连接。

    无论是运维、开发、传输文件、远程控制玩游戏,Splashtop软件绝对是最强的体现,极高的画质,流畅的运行,在远程控制过程中也会大大提升我们的效率,节约部分时间。

    Splashtop远程控制软件与其他主流远程软件的区别

    主要与Teamviewer、向日葵进行对比。

    一、产品对比

    Teamviewer 来自德国,成立于2005年,在全球各大洲都有分部,客户遍及全球。用户3.2亿,妥妥的行业龙头。特点是性能好,价格贵,企业用户比较多。

    Splashtop 来自美国,成立于2006年,在全球各大洲都有分部,客户遍及全球。用户量3000万,在欧美日很流行,国内知名度相对低一点。特点是性能好,价格不贵,经常会被作为 Teamviewer 的平替。

    向日葵来自中国,成立于2006年,主要在中国范围经营。客户量5000万,号称国货之光,在国内耕耘的比较好。特点是免费个人版比较好用,操作方便;很多个人用户都是向日葵和 Teamviewer 换着用。

    在这里插入图片描述

    二、性能对比

    性能这块,Teamviewer 和 Splashtop 都很强,画面清晰度、流畅度都很好。巧的是它们的某些核心算法也比较接近,用了一个比较讨巧的算法,节省带宽提高流畅度,因此在远程办公、远程运维的场景下很给力。向日葵在性能方面算是弱项,在网上被诟病的也比较多。

    三、安全性对比

    这三个都是行业里面的老品牌、大品牌,整体上还是值得信赖的。Teamviewer、向日葵都曾爆出过安全漏洞,Splashtop 目前新闻上没怎么看到过安全漏洞。Splashtop 在安全方面做的比较好,数据传输由 AES-256 和 TLS 加密;具备双因素验证、单点登录、设备认证等安全功能。Splashtop 控制端和被控端都是独立软件,连接需要设备验证、两步验证,虽然麻烦了点,但是安全性更有保障。

    Splashtop远程软件的最后说明

    Splashtop远程控制软件可以用于企业使用,官网地址:https://www.splashtop.cn/cn/。

    Splashtop Inc. 成立于2006年,总部位于硅谷,在杭州、台北、东京、新加坡、阿姆斯特丹等地设有分支机构。Splashtop 为全球的跨国企业和中小型企业、教育机构、托管服务供应商(MSP)和个人提供安全且易于管理的远程控制和远程支持软件及服务。经过17年的发展,Splashtop 现在拥有3000万全球用户、20万企业用户,支持会话超过8亿次。浪桥科技(杭州)有限公司成立于2007年,是 Splashtop Inc. 在中国的全资子公司。
    请添加图片描述

    展开全文
  • 数据库的并发控制技术

    千次阅读 2011-05-10 15:53:00
    数据库的基本概念总结 1. 数据库定义:数据库是长期储存在计算机内、有组织的、...主要功能:1,数据定义功能。2,数据组织、存储和管理。3,数据操纵功能。4,数据库的事务管理和运行管理。5,数据库的建立和维护功能
    数据库的基本概念总结 1. 数据库定义:数据库是长期储存在计算机内、有组织的、可共享的大量数据的集合。数据库中的数据按一定的数据模型组织、描述和储存,具有较小的冗余度、较高的数据独立性和易扩展性,并可为各种用户共享。 2. 数据库管理技术发展的三个阶段:人工管理阶段,文件系统阶段,数据库系统阶段。 3. DBMS(数据库管理系统)是位于用户与操作系统之间的一层数据管理软件。主要功能:1,数据定义功能。2,数据组织、存储和管理。3,数据操纵功能。4,数据库的事务管理和运行管理。5,数据库的建立和维护功能。6,其他功能。 4. 什么是数据模型及其要素? (设计题): 数据模型是数据库中用来对现实世界进行抽象的工具,是数据库中用于提供信息表示和操作手段的形式构架。一般地讲,数据模型是严格定义的概念的集合。这些概 念精确地描述系统的静态特性、动态特性和完整性约束条件。因此数据模型通常由数据结构、数据操作和完整性约束三部分组成。 (1)数据结构:是所研究的对象类型的集合,是对系统的静态特性的描述。 (2)数据操作:是指对数据库中各种对象(型)的实例(值)允许进行的操作的集合,包括操作及有关的操作规则,是对系统动态特性的描述。 (3)数据的约束条件:是完整性规则的集合,完整性规则是给定的数据模型中数据及其联系所具有的制约和依存规则,用以限定符合数据模型的数据库状态以及状态的变化,以保证数据的正确、有效、相容。 最常用的数据模型:层次模型,网状模型,关系模型,面积对象模型,对象关系模型。 5.常用的数据模型有哪些(逻辑模型是主要的),各有什么特征,数据结构是什么样的。 答:数据模型可分为两类: 第一类是概念模型,也称信息模型,它是按用户的观点来地数据和信息建模,主要用于数据库设计。 第二类是逻辑模型和物理模型。 其中逻辑模型主要包括层次模型、层次模型、关系模型、面向对象模型和对象关系模型等。它是按计算机系统的观点对数据建模,主要用于DBMS的实现。 物理模型是对数据最低层的抽象,它描述数据在系统内部的表示方式和存取方法,在磁盘或磁带上的存储方式和存取方法,是面向计算机系统的。物理模型是具体实现是DBMS的任务,数据库设计人员要了解和选择物理醋,一般用户则不必考虑物理级的细节。 层次数据模型的数据结构特点:一是:有且只有一个结点没有双亲结点,这个结点称为根结点。二是:根 以外的其他结点有且只有一个双亲结点。优点是:1.层次 数据结构比较简单清晰。2.层次数据库的查询效率高。3.层次数据模型提供了良好的完整性支持。缺点主要有:1.现实世界中很多联系是非层次性的,如结点之间具有多对多联系。2.一个结点具有多个双亲等 ,层次模型表示这类联系的方法很笨拙,只能通过引入冗余数据或创建非自然的数据结构来解决。对插入和删除操作的限制比较多,因此应用程序的编写比较复杂。3.查询子女结点必须通过双亲结点。4.由于结构严密,层次命令趋于程序化。可见用层次模型对具有一对多的层次联系的部门描述非常自然,直观容易理解,这是层次数据库的突出优点。 网状模型:特点:1.允许一个以上的结点无双亲2.一个结点可以有多于一个的双亲。网状数据模型的优点主要有:1.能够更为直接地描述现实世界,如一个结点可以有多个双亲。结点 之间可以有多种上联第。2.具有良好的性能,存取效率较高。缺点主要有:1.结构比较复杂,而且随着应用环境的扩大,数据库的结构就变得越来越复杂,不利于最终 用户掌握。2.网状模型的DDL,DML复杂,并且要嵌入某一种高级语言中,用户不容易掌握,不容易使用。 关系数据模型具有下列优点:1.关系模型与非关系模型不同,它是建立在严格的数学概念的基础上的。2.关系模型的概念单一。。3.关系模型的存取路径对用户透明,从而具有更高的数据独立性,更好的安全保密性,也简化了程序员的工作和数据库开发的建立 的工作。。主要的缺点是:由于存取路径房租明,查询效率往往不如非关系数据模型。因此为了提高性能,DBMS必须对用户的查询请求进行优化。因此增加 了开发DBMS的难度,不过用户不必考虑这些系统内部的优化技术细节。 6.三级体系结构,外模式,模式 ,内模式定义是什么? 模式也称逻辑模式,是数据库中全体数据的逻辑结构和牲的描述,是所有用户的公共数据视图。 外模式也称子模式或用户模式,它是数据库用户能够看见和使用的局部数据的逻辑结构和特征的描述,是数据库用户的数据视图是与某一应用有关的数据的逻辑表示。 内模式也称存储模式 ,是一个数据库只有一个内模式。它是数据物理结构和存储方式的描述,是数据在数据库内部的表示方式。 7.两级映像和两级独立性,为什么叫物理独立性和逻辑独立性。 当模式改变时由数据库管理员对各个外模式、模式的映像亻相应改变,可以使外模式保持不变。应用程序是依据数据的外模式编写的,从而应用程序不必修改,保证了数据与程序的逻辑独立生,简称数据的逻辑独立性。 当数据库的存储结构改变了,由数据库管理员对模式、内模式映像作 相应改变,可以使模式保持不变,从而应用程序也不必改变。保证了数据与程序的物理独立性,简称数据的物理独立性。 8.数据库系统一般由数据库、数据库管理系统 (及其开发工具)、应用系统和数据库管理员构成。 9.关系的完整性(实体完整性、参照完整性、和用户定义的完整性)三部分内容,其中前二者是系统自动支持的,DBMS完整性控制子系统的三个主要功能?:提供定义完整性约束条件的机制,提供完整性检查的方法,违约处理。 16.SQL的定义;即结构化查询语言,是关系数据库的标准语言,是一个通用的、功能极强的关系数据库语言。分类(交互式和嵌入式)17.group by 和having子句的作用 20.视图的概念:视图是从一个或几个基本表导出的表。及相关操作:定义视图,查询视图,更新视图。视图更新有什么操作:插入,删除,和修改。 22.数据库规范化的方法函数依赖的定义什么叫1NF2NF3NF BCNF定义:关系数据库中的关系是要满足一定要求的,满足不同程度要求的为不同范式。满足最低要求的叫第一范式,简称1NF。在第一范式中满足进一步要求的为第二范式,其余以此类推。各种范式之间的联系有:5NF(4NF(BCNF(3NF(2NF(1NF。 25.数据库设计的几个阶段,每个阶段常用的方法和简要的内容:六个阶段:需求分析、概念结构设计、罗织结构设计、物理设计、数据库实施、数据库运行和维护。 28.事务的概念?事务有哪些基本属性commit roll back含义:事务:是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的单位。四个特性:原子性,一致性,隔离性,持续性。Commit(提交:提交事务的所有操作) rollback(回滚:在事务运行的过程中发生了某种故障,事务不能继续执行,系统将事务中对数据库的所有已完成的操作全部撤销,回滚到事务开始时的状态。 29.什么叫数据库系统的可恢复性?:数据库管理系统具有把数据库从错误状态恢复到某一已知的正确状态的功能,这就是数据库系统的可恢复性。数据库故障的种类:事务内部的故障,系统故障(软故障),介质故障(硬故障),计算机病毒。 30.不进行并发控制可能产生的问题?:多个事务对数据库并发操作可能造成事务ACID特点遭到在破坏。如何解决(三个):1,丢失修改 2,不可重复读 3,读“脏”数据。 31.三级封锁协议?能解决什么问题?:一级封锁协议:事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。事务结束包括正常结束(COMMIT)和非正常结束(ROLLBACK)。一级封锁协议中,如果是读数据不修改,是不需要加锁的,可防止丢失修改。二级封锁协议:在一级封锁协议基础上,加上事务T在读数据R之前必须先对其加上S锁,读完后即可释放S锁。在二级封锁协议中,由于读完数据后即可释放S锁,所以它不能保证可重复读。三级封锁协议:一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。三级封锁协议除了防止了丢失修改和不读“脏”数据外,还进一步防止了不可重复读。 上述三级协议的主要区别在于:什么操作需要申请封锁,以及何时释放锁。 一般采取哪三种措施?插入呢?删除呢?:1,拒绝执行(不允许该操作执行),2,级连操作(当删除或修改被参照表的一个元组造成了与参照表的不一致,则删除或修改参照表中的所有造成不一致的元组),3,设置为空值(当删除或修改被参照表的一个元组时造成了不一致,则将参照表中的所有不造成不一致的元组的对应属性设置为空值)。 38.视图对数据库安全性的作用?:1,视图能够简化用户的操作,2,视力使用户能以多种角度看待同一数据,3,视图对重构数据库提供了一定程度的逻辑独立性,4,视图能够对机密数据提供安全保护,5,适当的利用视图可以更清晰的表达查询。 数据库:储存在计算机内,永久存储、有组织、有共享的大量数据的集合。 数据管理技术的发展阶段:1.人工管理阶段:数据不保存,应用程序管理数据,数据不共享,数据不具有独立性。2.文件系统阶段:数据可以长期保存,由文件系统管理数据;数据共享性太差,冗余度大,数据独立性差。3.数据库系统阶段:出现数据库管理系统。 数据库系统的特点:数据结构化(本质区别);数据共享性高、冗余度低、易扩充;数据独立性高;数据有DBMS统一管理和控制。 数据库管理系统:1.定义:DBMS,是位于用户与操作系统之间的一层数据管理软件。2.功能:数据定义功能;数据组织、存储和管理;数据操纵功能;数据库的事务管理和运行管理;数据库的建立和维护功能;通信功能、数据转换功能、互访和互操作功能。 数据库系统:1.概念:DBS,是指在计算机系统中引入数据库后的系统。2.组成:一般由数据库、数据库管理系统、应用系统、数据库管理员构成。3.分类:集中式,C/S式,并行式,分布式。 数据模型:1.定义:现实世界数据特征的抽象。2.组成,三要素:数据结构、数据操作、数据的完整性约束。两类数据模型为1)概念模型2)逻辑模型和物理模型。 数据结构:描述数据库的组成对象以及对象之间的联系,主要描述与对象的类型、内容、性质有关的对象和与数据之间联系有关的对象。 常用的数据模型:1.层次模型,用树形结构表示各类实体以及实体间的联系。2.网状模型,允许一个以上的结点无双亲,允许一个结点可以有多于一个的双亲。3.关系模型,包含单一数据结构 数据库的并发控制技术 数据库是一个共享资源,可以供许多用户使用。各个用户程序(通常为一个事务)可以一个一个地串行执行,即每个时刻只有一个用户程序运行,执行数据库的存取操作,其它用户程序必须等到这个用户程序结束后方能对数据库存取。但是,由于用户程序在执行过程中随着时间的不同需要不同的资源,有时需要CPU,有时需要访问磁盘,有时需要I/O,有时需要通讯等,如果只让一个用户程序运行,而其它用户闲置等待,则导致许多系统资源在大部分时间内处于闲置状态。 因此,为了充分利用系统资源,发挥数据库共享资源的特点,应该允许各个用户并行地存取数据。但这样就会产生多个用户程序并发存取同一数据的情况。若对并发操作不加控制就可能导致存取和存储不正确的数据,从而破坏数据库的一致性。 所以DBMS必须提供并发控制机制,且并发控制机制的好坏是衡量一个DBMS性能的重要指标之一。 一.事务及其特性 DBMS的并发控制是以事务(transaction)为单位进行的,因此,本节先介绍事务的概念及其特性。 在多用户环境中用户程序不断访问数据库中的数据,构成了若干操作序列,在这些操作序列中,有些操作必须作为一个整体来执行,这些作为一个整体来执行的操作序列称为一个事务(Transaction)。即事务是用户定义的一组操作序列的集合,是数据恢复和并发控制的基本单位。数据库系统在执行事务时,要么执行事务中全部操作,要么一个操作都不执行。一个应用程序往往由若干个独立的事务组成。在应用程序中,事务的开始与结束可以由用户显示地控制。如果用户没有显示地定义事务,则由DBMS自动地按照缺省方式划分事务。在SQL中,用户显示定义事务的语句有如下3条: 1、BEGIN TRANSACTION,该语句显示地定义一个事务的开始。 2、COMMIT,该语句显示地提交一个事务,并表示该事务已正常结束。 3、ROLLBACK,该语句显示地回滚一个事务,且表示事务因执行失败而结束。 所谓提交事务,就是将该事务对数据库的所有更新操作结果永久地保存到磁盘上的物理数据库中去。 所谓回滚事务,就是撤消该事务对数据库的所有更新操作,使数据库恢复到该事务开始时的状态。 由以上可知,用户若要显示地定义事务,必须以BEGIN TRANSATION开始,而以COMMIT 或 ROLLBACK结束。 事务具有四个特性,即原子性、一致性、隔离性和持续性,又常简称为ACID特性: 1、原子性 :即一个事务是不可分割的数据库逻辑工作单位。 2、一致性 :事务的执行结果必须使数据库从一个一致性状态变到另一个一致性状态。 3、隔离性 :一个事务的执行不能被其它事务干扰。 4、持续性 :持续性也称为永久性,指一个事务一旦提交,它对数据库中数据的改变应该是永久性的,其它操作或故障不对其产生任何影响。 二.数据库的并发控制 DBMS的并发控制是以事务为单位进行的。数据库在执行事务时,要么执行事务中的全部操作,要么一个操作都不执行。 当有多个事务对数据库进行操作时,如果对数据库进行操作的各个事务按顺序执行,即一个事务执行完全结束后,另一个事务才开始,则称这种执行方式为串行访问(Serial access)。 如果DBMS可以同时接纳多个事务,事务可以在时间上重叠执行,则称这种执行方式为并发访问(Concurrent access)。 在单CPU系统中,同一时间只能有一个事务占用CPU,若各个事务交叉使用CPU,则称这种并发方式为交叉并发。 在多CPU系统中,可以允许多个事务同时占用CPU,这种并发方式称为同时并发。 三.并发的目的 在数据库管理系统中对事务采用并发机制的主要目的有两个: 1、改善系统的资源利用率 对于一个事务来讲,在不同的执行阶段需要的资源不同,有时需要CPU,有时需要访问磁盘,有时需要I/O、有时需要通信如果事务串行执行,有些资源可能会空闲;如果事务并发执行,则可以交叉利用这些资源,有利于提高系统资源的利用率 2、改善短事务的响应时间 设有两个事务T1 和T2,其中T1是长事务,交付系统在先;T2是短事务,交付系统比T1稍后。如果串行执行,则须等T1执行完毕后才能执行T2。而T2的响应时间会很长。一个长事务的响应时间长一些还可以得到用户的理解,而一个短事务的响应时间过长,用户一般难以接受。 如果T1 和T2并发执行,则T2可以和T1重叠执行,可以较快地结束,明显地改善其响应时间。 四.并发所引起的问题 数据库中的数据是共享的,即多个用户可以同时使用数据库中的数据,这就是并发操作。 但是当多个用户存取同一组数据时,由于相互的干扰和影响,并发操作可能引发错误的结果,从而导致数据的不一致性问题我们将用下面的例子予以说明。 例5.5 设有一个飞机机票订票系统,考虑如下售票活动的并发操作问题: 1、售票员A通过网络在数据库中读出某航班的机票余额为y张,设y=15; 2、售票员B通过网络在数据库中读出某航班的机票余额为y张,设y=15; 3、售票员A卖出一张机票,然后修改余额为y=y?1,此时,y=14,将14写会数据库; 4、售票员B卖出一张机票,然后修改余额为y=y?1,此时,y=14,将14写会数据库; 这个售票活动并发操作的结果是:实际已经卖出2张机票,但在数据库中机票余额仅减少1,从而导致错误。这就是著名的飞机机票订票系统问题。 这个问题之所以会产生错误,其根本原因在于两个用户反复交叉地使用同一个数据库的结果。 如果事务不加控制地并发执行,会产生以下几个问题: 1、丢失修改(Lost update) 2、脏读(Dirty read)。 3、不能重读(Unrepeatable read) 五.并发控制方法 实现现数据库并发控制的方法有多种,常用的有封锁技术、时标技术和版本更新技术等,而封锁技术在商品化数据库管理系统中使用得最为普遍。 本节中介绍: (1)封锁技术 (2)时标技术 1.封锁技术 封锁的定义 锁是为了防止其它事务访问指定资源的一种手段。封锁(locking)是实现并发控制的一个非常重要的技术。 所谓封锁即是在一段时间内禁止某些用户对数据对象做某些操作,以避免产生数据的不一致性问题。即事务T在对某个数据对象,如表、元组等进行操作之前,先向系统发出请求,并对其加锁。加锁成功后,事务T就对数据对象有了一定的控制权,在事务T释放它的锁之前,其它的事务就不能更新此数据对象。 封锁的类型 基本的封锁一般有排它锁和共享锁两种类型。 (1)排它锁:又称X锁,如果某事务T对某数据建立了排它锁,则该事务能对该数据对象进行读、修改、插入和删除等操作,而其它事务则不能。 (2)共享锁:又称S锁,如果某事务对某数据建立了共享锁,则此时该事务能对该数据对象进行读操作,但不能进行修改等更新操作;而其它事务只能对该数据对象加S锁,而不能加X锁,即其它事务只能对该数据对象进行读操作。 封锁粒度 所谓封锁的粒度,即是被封锁数据对象的大小。在关系数据库中,封锁的粒度有如下几种:属性值、属性值集、元组、关系、索引项、整个索引或整个数据库。还可以是一些物理单元:页(数据页或索引页)、块等等。 封锁的粒度与系统的并发度和并发控制的开销密切相关。封锁粒度越大,系统中能够被封锁的对象就越少,并发度也就越小,但同时系统开销也越少;封锁粒度越小,并发度越高,但系统开销也就越大。因此,如果在一个系统中能同时存在不同大小的封锁粒度对象供不同的事务选择使用,是比较理想的。 封锁协议 封锁的目的是为了保证能够正确地调度和控制并发操作。为此,在运用X锁和S锁这两种基本锁对一定粒度的数据对象加锁时,还需约定一些规则。 例如,一个事务何时该申请X锁或S锁、事务持锁时间的长短如何控制、何时释放所获得的锁等等。我们称这些规则为封锁协议 (Locking protocol)。 下面介绍三级封锁协议: 1、一级封锁协议:某事务T若要修改某个数据对象,则必须先对该数据对象加X锁,直到事务结束才释放。此种封锁协议可防止“丢失修改”所产生的数据不一致性问题。 2、二级封锁协议:一级封锁协议加上某事务T若要读取某个数据对象之前,则必须先对该数据对象加S锁,读完后即可释放S锁,这样可进一步防止“读脏数据”的问题。 3、三级封锁协议:一级封锁协议加上某事务T若要读取某个数据对象之前,则必须先对该数据对象加S锁,且知道该事务结束后才可释放S锁,这样可进一步防止数据“不可重复读”的问题。 死锁和活锁 活锁:如果事务T1封锁了数据对象R后,事务T2也请求封锁R,于是T2等待。接着T3也请求封锁R。当T1释放了加在R上的锁后,系统首先批准了T3的请求,T2只得继续等待。接着T4也请求封锁R,T3释放R上的锁后,系统又批准了T4的请求,……,因此,事务T2就有可能这样永远地等待下去。以上这种情况就称为活锁。 避免活锁的简单办法是采用先来先服务的策略。当多个事务请求封锁同一数据对象时,封锁子系统按封锁请求的先后次序对这些事务排队,该数据对象上的锁一旦释放,首先批准申请队列中的第一个事务获得锁。 死锁:如果事务T1封锁了数据对象A,T2封锁了数据对象B之后,T1又申请封锁数据对象B,且T2又申请封锁数据对象A。因T2已封锁了B,于是T1等待T2释放加在B上的锁。因T1已封锁了A,T2也只能等待T1释放加在A上的锁。这样就形成了T1在等待T2结束,而T2又在等待T1结束的局面。T1和T2这两个事务永远不能结束,这就是死锁问题。 死锁的另一情况是数据库系统有若干个长时间运行的事务在执行并行的操作,当查询分析器处理一种非常复杂的连接查询时,由于不能控制处理的顺序,有可能发生死锁现象。 目前,解决死锁问题的方法主要有两类: 预防法: 此类方法中常用的又有: (1)一次封锁法 (2)顺序封锁法 诊断解除法 2.时标技术 (1).时标的定义 (2).时标的原理 (3).基于时标技术的并发控制方法所采用的协议 (4).基于时标技术的并发调度实例 (5).时标技术与封锁技术的基本区别 (6).时标技术的优缺点 数据库 并发调度技术 四种问题 三级封锁协议 数据库是一个共享资源,可以提供多个用户使用。这些用户程序可以一个一个地串行执行,每个时刻只有一个用户程序运行,执行对数据库的存取,其他用户程序必须等到这个用户程序结束以后方能对数据库存取。但是如果一个用户程序涉及大量数据的输入/输出交换,则数据库系统的大部分时间处于闲置状态。因此,为了充分利用数据库资源,发挥数据库共享资源的特点,应该允许多个用户并行地存取数据库。但这样就会产生多个用户程序并发存取同一数据的情况,若对并发操作不加控制就可能会存取和存储不正确的数据,破坏数据库的一致性,所以数据库管理系统必须提供并发控制机制。并发控制机制的好坏是衡量一个数据库管理系统性能的重要标志之一。 DM用封锁机制来解决并发问题。它可以保证任何时候都可以有多个正在运行的用户程序,但是所有用户程序都在彼此完全隔离的环境中运行。 一、 并发控制的预备知识 (一) 并发控制概述 并发控制是以事务(transaction)为单位进行的。 1. 并发控制的单位――事务 事务是数据库的逻辑工作单位,它是用户定义的一组操作序列。一个事务可以是一组SQL语句、一条SQL语句或整个程序。 事务的开始和结束都可以由用户显示的控制,如果用户没有显式地定义事务,则由数据库系统按缺省规定自动划分事务。 事务应该具有4种属性:原子性、一致性、隔离性和持久性。 (1)原子性 事务的原子性保证事务包含的一组更新操作是原子不可分的,也就是说这些操作是一个整体,对数据库而言全做或者全不做,不能部分的完成。这一性质即使在系统崩溃之后仍能得到保证,在系统崩溃之后将进行数据库恢复,用来恢复和撤销系统崩溃处于活动状态的事务对数据库的影响,从而保证事务的原子性。系统对磁盘上的任何实际数据的修改之前都会将修改操作信息本身的信息记录到磁盘上。当发生崩溃时,系统能根据这些操作记录当时该事务处于何种状态,以此确定是撤销该事务所做出的所有修改操作,还是将修改的操作重新执行。 (2)一致性 一致性要求事务执行完成后,将数据库从一个一致状态转变到另一个一致状态。它是一种以一致性规则为基础的逻辑属性,例如在转账的操作中,各账户金额必须平衡,这一条规则对于程序员而言是一个强制的规定,由此可见,一致性与原子性是密切相关的。事务的一致性属性要求事务在并发执行的情况下事务的一致性仍然满足。它在逻辑上不是独立的,它由事务的隔离性来表示。 (3) 隔离性 隔离性意味着一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。它要求即使有多个事务并发执行,看上去每个成功事务按串行调度执行一样。这一性质的另一种称法为可串行性,也就是说系统允许的任何交错操作调度等价于一个串行调度。串行调度的意思是每次调度一个事务,在一个事务的所有操作没有结束之前,另外的事务操作不能开始。由于性能原因,我们需要进行交错操作的调度,但我们也希望这些交错操作的调度的效果和某一个串行调度是一致的。 DM实现该机制是通过对事务的数据访问对象加适当的锁,从而排斥其他的事务对同一数据库对象的并发操作。 (4)持久性 系统提供的持久性保证要求一旦事务提交,那么对数据库所做的修改将是持久的,无论发生何种机器和系统故障都不应该对其有任何影响。例如,自动柜员机( ATM)在向客户支付一笔钱时,就不用担心丢失客户的取款记录。事务的持久性保证事务对数据库的影响是持久的,即使系统崩溃。正如在讲原子性时所提到的那样,系统通过做记录来提供这一保证。 DM没有提供显式定义事务开始的语句,第一个可执行的SQL语句(除CONNECT语句外)隐含事务的开始,但事务的结束可以由用户显式的控制。在DM中以下几种情况都结束 (正常,非正常)某一事务: (1)当某一连接的属性设置为自动提交,每执行一条语句都会提交; (2)遇到COMMIT/ROLLBACK语句,便提交/回滚一事务; (3)当系统的 DDL自动提交开关打开时(缺省为打开),遇到DDL语句则自动提交该DDL语句和以前的DML和DDL操作; (4)事务所在的程序正常结束和用户退出; (5)系统非正常终止时; 说明:DM在配置文件中提供了DDL语句的自动提交开关DDL_AUTO_COMMIT。 当此配置项的值为 1(缺省情况)时,所有DDL语句自动提交;当此配置项的值为0时,除CREATEDATABASE、ALTERDATABASE和CREATESCHEMA语句外的所有DDL语句都不自动提交。 DM中的一致性是以事务为基础的。DM通过提交和回滚分别用于将对数据库的修改永久化和废除,但是无论是提交和回滚,DM保证数据库在每个事务开始前、结束后是一致的。为了提高事务管理的灵活性,DM提供了设置保存点(SAVEPOINT)语句和回滚到保存点语句。保存点提供了一种灵活的回滚,事务在执行中可以回滚到某个保存点,在该保存点以前的操作有效,而以后的操作被回滚掉。 DM中的事务同样具有上述4个属性:原子性、一致性、隔离性和持久性。 2. 并发操作与数据的不一致性 如果没有锁定且多个用户同时访问一个数据库,则当他们的事务同时使用相同的数据时可能会发生问题,导致数据库中的数据的不一致性。 一个最常见的并发操作的例子是火车/飞机订票系统中的订票操作。例如,在该系统中的一个活动序列: ① 甲售票员读出某航班的机票张数余额A,设A=16; ② 乙售票员读出同一航班的机票张数余额A,也是16; ③ 甲售票员卖出一张机票,修改机票张数余额A=A-1=15,把A写回数据库; ④ 乙售票员也卖出一张机票,修改机票张数余额A=A-1=15,把A写回数据库。 结果明明卖出两张机票,数据库中机票余额只减少1。 这种情况称为数据库的不一致性。这种不一致性是由甲、乙两个售票员并发操作引起的。在并发操作情况下,对甲、乙两个事务操作序列的调度是随机的。若按上面的调度序列行,甲事务的修改就被丢失。这是由于第4步中乙事务修改A并写回覆盖了甲事务的修改。 并发操作带来的数据库不一致性可以分为四类:丢失或覆盖更新、脏读、不可重复读和幻像读,上例只是并发问题的一种。 (1) 丢失或覆盖更新(lost update) 当两个或多个事务选择同一数据,并且基于最初选定的值更新该数据时,会发生丢失更新问题。每个事务都不知道其它事务的存在。最后的更新将重写由其它事务所做的更新,这将导致数据丢失。上面预定飞机票的例子就属于这种并发问题。事务1与事务2先后读入同一数据A=16,事务1执行A-1,并将结果A=15写回,事务2执行A-1,并将结果A=15写回。事务2提交的结果覆盖了事务1对数据库的修改,从而使事务1对数据库的修改丢失了。 (2) 脏读 一个事务读取了另一个未提交的并行事务写的数据。当第二个事务选择其它事务正在更新的行时,会发生未确认的相关性问题。第二个事务正在读取的数据还没有确认并且可能由更新此行的事务所更改。换句话说,当事务1修改某一数据,并将其写回磁盘,事务2读取同一数据后,事务1由于某种原因被撤销,这时事务1已修改过的数据恢复原值,事务2读到的数据就与数据库中的数据不一致,是不正确的数据,称为脏读。 例如,在下图中,事务1将C值修改为200,事务2读到C为200,而事务1由于某种原因撤销,其修改作废,C恢复原值100,这时事务2读到的就是不正确的“脏“数据了。 (3) 不可重复读(nonrepeatable read) 一个事务重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务修改过。即事务1读取某一数据后,事务2对其做了修改,当事务1再次读数据时,得到的与第一次不同的值。 例如,在下图中,事务1读取B=100进行运算,事务2读取同一数据B,对其进行修改后将B=200写回数据库。事务1为了对读取值校对重读B,B已为200,与第一次读取值不一致。 (4) 幻像读 如果一个事务在提交查询结果之前,另一个事务可以更改该结果,就会发生这种情况。这句话也可以这样解释,事务1按一定条件从数据库中读取某些数据记录后未提交查询结果,事务2删除了其中部分记录,事务1再次按相同条件读取数据时,发现某些记录神秘地消失了;或者事务1按一定条件从数据库中读取某些数据记录后未提交查询结果,事务2插入了一些记录,当事务1再次按相同条件读取数据时,发现多了一些记录。 产生上述四类数据不一致性的主要原因是并发操作破坏了事务的隔离性。并发控制就是要用正确的方式调度并发操作,使一个用户事务的执行不受其他事务的干扰,从而避免造成数据的不一致性。 3. 并发场景列举 结合SQL语句,列举各种并发情况(包括可能导致数据不一致性和对数据一致性不产生影响的情况)。A表示某一条数据,b和c都表示满足某一个标准的两条或多条数据,^表示“非”的意思,∈表示属于或包含于的意思,1表示第一个事务,2表示第二个事务。 (二) 并发操作的调度 计算机系统对并行事务中并行操作的调度是随机的,而不同的调度可能会产生不同的结果,那么哪个结果是正确的,哪个是不正确的呢? 如果一个事务运行过程中没有其他事务在同时运行,也就是说没有受到其他事务的干扰,那么就可能认为该事务的运行结果是正常的或者预想的,因此将所有事务串行起来的调度策略是正确的调度策略。虽然以不同的顺序串行执行事务也可能会产生不同的结果,但由于不会将数据库置于不一致状态,所以都可以认为是正确的。由此可以得到如下结论:几个事务的并行执行是正确的,当且仅当其结果与按某一次序串行地执行它们的结果相同。我们称这种并行调度策略为可串行化(serializable)的调度。可串行性(serializability)是并行事务正确性的唯一准则。 例如,现在有两个事务,分别包含下列操作: 事务1:读B;A=B+1;写回A; 事务2:读A;B=A+1;写回B; 假设A的初值为10,B的初值为2。下图给出了对这两个事务的三种不同的调度策略,(a)和(b)为两种不同的串行调度策略,虽然执行结果不同,但他们都是正确的调度。(c)中两个事务是交错执行的,由于执行结果与(a)、(b)的结果都不同,所以是错误的调度。(d)中的两个事务也是交错执行的,由于执行结果与串行调度1(图(a))的执行结果相同,所以是正确的调度。 为了保证并行操作的正确性,DBMS的并行控制机制必须提供一定的手段来保证调度是可串行化的。 从理论上讲,在某一事务执行时禁止其他事务执行的调度策略一定是可串行化的调度,这也是最简单的调度策略,但这种方法实际上是不可行的,因为它使用户不能充分共享数据库资源。 目前DBMS普遍采用封锁方法(悲观方法,DM采用的就是这种方法,SQL Server也是采用的这种方法)来保证调度的正确性;即保证并行操作调度的可串行性。除此之外还有其他一些方法,如时标方法、乐观方法等。 ? 悲观并发控制 锁定系统阻止用户以影响其它用户的方式修改数据。如果用户执行的操作导致应用了某个锁,则直到这个锁的所有者释放该锁,其它用户才能执行与该锁冲突的操作。该方法主要用在数据争夺激烈的环境中,以及出现并发冲突时用锁保护数据的成本比回滚事务的成本低的环境中,因此称该方法为悲观并发控制。 ? 乐观并发控制 在乐观并发控制中,用户读数据时不锁定数据。在执行更新时,系统进行检查,查看另一个用户读过数据后是否更改了数据。如果另一个用户更新了数据,将产生一个错误。一般情况下,接收错误信息的用户将回滚事务并重新开始。该方法主要用在数据争夺少的环境内,以及偶尔回滚事务的成本超过读数据时锁定数据的成本的环境内,因此称该方法为乐观并发控制。 ? 时标并发控制 时标和封锁技术之间的基本区别是封锁是使一组事务的并发执行(即交叉执行)同步,使用它等价于这些事务的某一串行操作;时标法也是使用一组事务的交叉执行同步,但是使它等价于这些事务的一个特定的串行执行,即由时标的时序所确定的一个执行。如果发生冲突,是通过撤销并重新启动一个事务解决的。事务重新启动,则赋予新的时标。 (三) 封锁 封锁是事项并发控制的一个非常重要的技术。所谓封锁就是事务T在对某个数据对象,例如,在标、记录等操作之前,先向系统发出请求,对其加锁。加锁后事务T就对数据库对象有了一定的控制,在事务T释放它的锁之前,其他事务不能更新此数据对象。 1. 封锁类型 DBMS通常提供了多种数据类型的封锁。一个事务对某个数据对象加锁后究竟拥有什么样的控制是由封锁类型决定的。基本的封锁类型有两种:排他锁(exclusive lock,简记为X锁)和共享锁(share lock简记为S锁) 排他锁又称为写锁。若事务T对数据对象A加上X锁,则只允许T读取和修改A,其他任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。这就保证了其他事务在T释放A上的锁之前不能再读取和修改A。 共享锁又称为读锁。若事务T对数据对象A加上S锁,则其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的锁。这就保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。 排他锁与共享锁的控制方式可以用下图的相容矩阵来表示。 在下图的封锁类型相容矩阵中,最左边一列表示事务T1已经获得的数据对象上的锁的类型,其中横线表示没有加锁。最上面一行表示另一事务T2对同一数据对象发出的封锁请求。T2的封锁请求能否被满足用Y和N表示,其中Y表示事务T2的封锁要求与T1已持有的锁相容,封锁请求可以满足。N表示T2的封锁请求与T1已持有的锁冲突,T2请求被拒绝。 2. 封锁粒度 X锁和S锁都是加在某一个数据对象上的。封锁的对象可以是逻辑单元,也可以是物理单元。例如,在关系数据库中,封锁对象可以是属性值、属性值集合、元组、关系、索引项、整个索引、整个数据库等逻辑单元;也可以是页(数据页或索引页)、块等物理单元。封锁对象可以很大,比如对整个数据库加锁,也可以很小,比如只对某个属性值加锁。封锁对象的大小称为封锁的粒度(granularity)。 封锁粒度与系统的并发度和并发控制的开销密切相关。封锁的粒度越大,系统中能够被封锁的对象就越小,并发度也就越小,但同时系统开销也越小;相反,封锁的粒度越小,并发度越高,但系统开销也就越大。 因此,如果在一个系统中同时存在不同大小的封锁单元供不同的事务选择使用是比较理想的。而选择封锁粒度时必须同时考虑封锁机构和并发度两个因素,对系统开销与并发度进行权衡,以求得最优的效果。一般说来,需要处理大量元组的用户事务可以以关系为封锁单元;需要处理多个关系的大量元组的用户事务可以以数据库为封锁单位;而对于一个处理少量元组的用户事务,可以以元组为封锁单位以提高并发度。 3. 封锁协议 封锁的目的是为了保证能够正确地调度并发操作。为此,在运用X锁和S锁这两种基本封锁,对一定粒度的数据对象加锁时,还需要约定一些规则,例如,应何时申请X锁或S锁、持锁时间、何时释放等。我们称这些规则为封锁协议(locking protocol)。对封锁方式规定不同的规则,就形成了各种不同的封锁协议,它们分别在不同的程度上为并发操作的正确调度提供一定的保证。本节介绍保证数据一致性的三级封锁协议和保证并行调度可串行性的两段锁协议,下一节将介绍避免死锁的封锁协议。 (5) 保证数据一致性的封锁协议――三级封锁协议 对并发操作的不正确调度可能会带来四种数据不一致性:丢失或覆盖更新、脏读、不可重复读和幻想读。三级封锁协议分别在不同程度上解决了这一问题。 ① 1级封锁协议 1级封锁协议的内容是:事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。事务结束包括正常结束(commit)和非正常结束(rollback)。 1级封锁协议可以防止丢失或覆盖更新,并保证事务T是可以恢复的。例如,下图使用1级封锁协议解决了定飞机票例子的丢失更新问题。 上图中,事务1在读A进行修改之前先对A加X锁,当事务2再请求对A加X锁时被拒绝,只能等事务1释放A上的锁。事务1修改值A=15写回磁盘,释放A上的X锁后,事务2获得对A的X锁,这时他读到的A已经是事务1更新过的值15,再按此新的A值进行运算,并将结果值A=14回到磁盘。这样就避免了丢失事务1的更新。 在1级封锁协议中,如果仅仅是读数据不对其进行修改,是不需要加锁的,所以它不能保证可重复读和脏读。 ② 2级封锁协议 2级封锁协议的内容是:1级封锁协议加上事务T在读取数据R之前必须先对其加S锁,读完后即可释放S锁。 2级封锁协议除防止了丢失或覆盖更新,还可进一步防止脏读。例如,下图使用2级封锁协议解决了脏读的问题。 | 下图中,事务1在对C进行修改之前,先对C加X锁,修改其值后写回磁盘。这时事务2请求C加上S锁,因T1已在C上加了X锁,事务2只能等待事务1释放它。之后事务1因某种原因被撤销,C恢复为原值100,并释放C上的X锁。事务2获得C上的S锁,读C=100。这就避免了事务2脏读数据。 在2级封锁协议中,由于读完数据后即可释放S锁,所以它不能保证可重复读。 ③ 3级封锁协议 3级封锁协议的内容是:1级封锁协议加上事务T在读取数据之前必须先对其加S锁,直到事务结束才释放。 3级封锁协议除防止丢失或覆盖更新和不脏读数据外,还进一步防止了不可重复读和幻想读。例如下图,使用3级封锁协议解决了不可重复读和幻像读问题。 上图中,事务1在读A,B之前,先对A,B加S锁,这样其他事务只能再对A,B加S锁,而不能加X锁,即其他事务只能读A,B,而不能修改它们。所以当事务2为修改B而申请对B的X锁时被拒绝,使其他无法执行修改操作,只能等待事务1释放B上的锁。接着事务1为验算再读A,B,这时读出的B仍是100,求和结果仍为150,即可重复读。 上述三级协议的主要区别在于什么操作需要申请封锁以及何时释放锁(即持锁时间)。三级封锁协议可以总结为下表。 (6) 保证并行调度可串行性的封锁协议――两段封锁协议 可串行性是并行调度正确性的唯一准则,两段锁(two-phase locking,简称2PL)协议是为保证并行调度可串行性而提供的封锁协议。 两段封锁协议规定: ①在对任何数据进行读、写操作之前,事务首先要获得对该数据的封锁,而且②在释放一个封锁之后,事务不再获得任何其他封锁。 所谓“两段”锁的含义是,事务分为两个阶段,第一阶段是获得封锁,也称为扩展阶段,第二阶段是释放封锁,也称为收缩阶段。 例如,事务1的封锁序列是: Slock A... Slock B… Xlock C… Unlock B… Unlock A… Unlock C; 事务2的封锁序列是: Slock A... Unlock A… Slock B… Xlock C… Unlock C… Unlock B; 则事务1遵守两段封锁协议,而事务2不遵守两段封锁协议。 可以证明,若并行执行的所有事务均遵守两段锁协议,则对这些事务的所有并行调度策略都是可串行化的。因此我们得出如下结论:所有遵守两段锁协议的事务,其并行的结果一定是正确的。 需要说明的是,事务遵守两段锁协议是可串行化调度的充分条件,而不是必要条件。即可串行化的调度中,不一定所有事务都必须符合两段封锁协议。例如,在下图中,(a)和(b)都是可串行化的调度,但(a)遵守两段锁协议,(b)不遵守两段锁协议。 4. 死锁和活锁 封锁技术可以有效地解决并行操作的一致性问题,但也带来一些新的问题,即死锁和活锁的问题。 (1) 活锁 如果事务T1封锁了数据对象R后,事务T2也请求封锁R,于是T2等待。接着T3也请求封锁R。T1释放R上的锁后,系统首先批准了T3的请求,T2只得继续等待。接着T4也请求封锁R,T3释放R上的锁后,系统又批准了T4的请求……,T2有可能就这样永远等待下去。这就是活锁的情形,如下图所示。 避免活锁的简单方法是采用先来先服务的策略。当多个事务请求封锁同一数据对象时,封锁子系统按请求封锁的先后次序对这些事务排队,该数据对象上的锁一旦释放,首先批准申请队列中第一个事务获得锁。 (2) 死锁 如果事务T1封锁了数据A,事务T2封锁了数据B。之后T1又申请封锁数据B,因T2已封锁了B,于是T1等待T2释放B上的锁。接着T2又申请封锁A,因T1已封锁了A,T2也只能等待T1释放A上的锁。这样就出现了T1在等待T2,而T2又在等待T1的局面,T1和T2两个事务永远不能结束,形成死锁。如下图所示。 死锁问题在操作系统和一般并行处理中已做了深入研究,但数据库系统有其自己的特点,操作系统中解决死锁的方法并不一定合适数据库系统。 目前在数据库中解决死锁问题主要有两类方法,一类方法是采取一定措施来预防死锁的发生,另一类方法是允许发生死锁,采用一定手段定期诊断系统中有无死锁,若有则解除之。 ① 死锁的预防 在数据库系统中,产生死锁的原因是两个或多个事务都已封锁了一些数据对象,然后又都请求对已为其他事务封锁的数据对象加锁,从而出现死锁等待。防止死锁的发生其实就是要破坏产生死锁的条件。预防死锁通常有两种方法。 ◆ 一次封锁法 一次封锁法要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行。例如,在上图的例子中,如果事务T1将数据对象A和B一次加锁,T1就可以执行下去,而T2等待。T1执行完后释放A,B上的锁,T2继续执行。这样就不会发生死锁。 一次封锁法虽然可以有效地防止死锁的发生,但也存在问题。第一,一次就将以后要用到的全部数据加锁,势必扩大了封锁的范围,从而降低了系统的并发度。第二,数据库中数据是不断变化的,原来不要求封锁的数据,在执行过程中可能会变成封锁对象,所以很难实现精确地确定每个事务所要封锁的数据对象,只能采取扩大封锁范围,将事务在执行过程中可能要封锁的数据对象全部加锁,这就进一步降低了并发度。 ◆ 顺序封锁法 顺序封锁法是预先对数据对象规定一个封锁顺序,所有事务都按这个顺序执行封锁。在上例中,我们规定封锁顺是A,B,T1和T2都按此顺序封锁,即T2也必须先封锁A。当T2请求A的封锁时,由于T1已经封锁住A,T2就只能等待。T1释放A,B上的锁后,T2继续运行。这样就不会发生死锁。 顺序封锁法同样可以有效地防止死锁,但也同样存在问题。第一,数据库系统中可封锁的数据对象及其众多,并且随数据的插入、删除等操作而不断地变化,要维护这样极多而且变化的资源的封锁顺序非常困难,成本很高。 第二,事务的封锁请求可以随着事务的执行而动态地决定,很难事先确定每一个事务要封锁哪些对象,因此也就很难按规定的顺序取施加封锁。例如,规定数据对象的封锁顺序为A,B,C,D,E。事务T3起初要求封锁数据对象B,C,E,但当它封锁B,C后,才发现还需要封锁A,这样就破坏了封锁顺序。 可见,在操作系统中广为采用的预防死锁的策略并不很适合数据库的特点,因此DBMS在解决死锁的问题上更普遍采用的是诊断并解除死锁的方法。 ② 死锁的诊断与解除 数据库系统中诊断死锁的方法与操作系统类似,即使用一个事务等待图,它动态地反映所有事务的等待状况。并发控制子系统周期性地(比如每隔1分钟)检测事务等待图,如果发现图中存在回路,则表示系统中出现了死锁。关于诊断死锁的详细讨论请参阅操作系统的有关书籍。 DBMS的并发控制子系统一旦检测到系统中存在死锁,就要设法解除。通常采用的方法是选择一个处理死锁代价最小的事务,将其撤销,释放此事务持有的所有的锁,使其他事务能继续运行下去。 二、 DM的并发控制 (一) 事务隔离级 事务的隔离级描述了给定事务的行为对其它并发执行事务的暴露程度。 SQL-92共规定了四种隔离级别,通过选择四个隔离级中的一个,用户能增加对其它未提交事务的暴露程度,获得更高的并发度。隔离级别是一个事务必须与其它事务进行隔离的程度。 SQL-92的四种隔离级别如下所示,DM支持所有这些隔离级别: (1)脏读(READ UNCOMMITTED):事务隔离的最低级别,事务可能查询到其它事务未提交的数据, 仅可保证不读取物理损坏的数据)。 (2)读提交(READ COMMITTED):DM默认级别,保证不读脏数据。 (3)可重复读(REPEATABLE READ):保证不可重复读,但有可能读入幻像数据。 (4)可串行化(SERIALIZABLE):事务隔离的最高级别,事务之间完全隔离。 DM允许用户改变未启动的事务的隔离级和读写特性 ,而且设置的选项将一直对那个连接保持有效,直到显式更改该选项为止。设置事务隔离级别虽然使程序员承担了某些完整性问题所带来的风险,但可以换取对数据更大的并发访问权。与以前的隔离级别相比,每个隔离级别都提供了更大的隔离性,但这是通过在更长的时间内占用更多限制锁换来的。DM还提供设置事务只读属性的语句,使用该语句后该事务只能做查询操作,不能更新数据库。 需要注意的是,事务的隔离级别并不影响事务查看本身对数据的修改,也就是说,事务总可以查看自己对数据的修改。事务的隔离级别需要根据实际需要设定,较低的隔离级别可以增加并发,但代价是降低数据的正确性。相反,较高的隔离级别可以确保数据的正确性,但可能对并发产生负面影响。应用程序要求的隔离级别确定了DM使用的锁定行为。 下表中列出四种隔离级别允许不同类型的现象 注意:丢失或覆盖更新在所有的标准SQL隔离级中都是禁止的。 (二) 并发处理 1. 数据锁定机制 DM用数据锁定机制来解决并发问题。它可以保证任何时候都可以有多个正在运行的事务,但是所有事务都在彼此完全隔离的环境中运行。 DM的封锁对象为表和元组。封锁的实施有自动和手动两种,即隐式上锁和显式上锁。隐式封锁动作的封锁根据事务的隔离级有所不同。同时, DM提供给用户4种手动上锁语句,用以适应用户定义的应用系统。 一般而言, DM的隐式封锁足以保证数据的一致性,但用户可以根据自己的需要改变对表的封锁。 DM提供给用户四种表锁:意向共享锁(IS:INTENSIVE SHARE)、共享锁(S:SHARE)、意向排它锁(IX:INTENSIVE EXCLUSIVE)和排它锁(X:EXCLUSIVE)。例如,在读提交隔离级下,系统缺省的表锁是 IS或IX ,在这两种表锁下,在访问元组前还需对元组进行封锁,为了提高系统的效率,用户可以手动对表进行 X封锁,这样,就不需对访问元组封锁。 封锁机制要达到以下目的: (1)一致性:保证用户正在查看时,改变的数据并未从根本上发生变化。 (2)完整性:保证数据库的基本结构以正确的顺序,准确地反映对它们的所有改变。 一个“ 锁定” 可以认为是当某一进程需要防止其它进程做某事时获得的某种东西,当该进程不再关心此事时就 “释放 ”此锁定,通常一个锁定是加在某个 “资源 ”(某些客体,如表 )上的。 DM的内部锁定是自动完成的。当某一进程要查看一个客体但不允许其他人修改它时,就获得一个共享方式的锁定。当某一进程要修改一客体,并且防止任何其它进程修改它时,就获得更新方式的锁定。当某一进程要修改一客体,并且防止任何其它进程修改它或以共享方式封锁它时,就获得独占方式的锁定。 2. 锁定类型 DM中的锁有三种,表锁、行锁和键范围锁。 ◆ 表锁 表锁用来封锁表对象,在对表进行检索和更新时,DM会对表对象进行封锁,但是DM为用户提供手动的表锁语句,用户可以根据自己的需要改变对表的封锁类型。表锁的模式:意向共享锁 IS,意向排它锁 IX,共享锁 S,排它锁 X,共四种,其相容矩阵可定义如下表。 ◆ 行锁 行锁封锁元组,在存取元组和更新元组前, DM会对元组上行锁,系统不提供手动的行封锁语句。行锁有两种模式:共享锁(S)、排它锁(X),其相容矩阵定义如下表。 ◆ 键范围锁 键范围锁用在可串行事务上,主要解决了幻像读并发问题。键范围锁覆盖单个记录以及记录之间的范围,可以防止对事务访问的记录集进行幻像插入或删除。键范围锁仅用于在可串行隔离级别上操作的事务。 可串行性要求,如果任意一个查询在一个事务中后面的某一时刻再次执行,其所获取的行集应与该查询在同一事务中以前执行时所获得的行集相同。如果本查询试图提取的行不存在,则在试图访问该行的事务完成之前,其它事务不能插入该行。如果允许另一个事务插入该行,则它将以幻像出现。 如果另一个事务试图插入驻留在锁定数据页上的行,页级锁定可以防止添加幻像行,并维护可串行性。但是,如果该行要添加到未被第一个事务锁定的数据页,应设定锁定机制防止添加该行。 键范围锁通过覆盖索引行和索引行之间的范围来工作(而不是锁定整个基础表的行)。因为第二个事务在该范围内进行任何行插入、更新或删除操作时均需要修改索引,而键范围锁覆盖了索引项,所以在第一个事务完成之前会阻塞第二个事务的进行。 键范围锁由系统自行执行,执行的条件是: (1) 事务隔离级为可串行化级; (2) 查询结果通过某个索引得出。 用户上锁成功后锁将一直有效,直到当前事务结束时,该锁被系统自动解除。 3. 锁定类型比较 4. SQL语句锁定分析 DM对各种 DDL和GRANT 等非DML 语句都分解为增、删、改。下表为DM对各种DML语句和查询语句的封锁策略。 表:SQL语句封锁策略 注:S* 表示瞬时锁,在语句结束后释放;Range表示键范围锁。 上表只是系统在一般情况下的处理,当系统检测到有锁升级的可能,则会升级锁。一般而言,IS锁升级为 S锁,IX锁升级为 X锁,同时,不再进行行封锁。 5. 自定义锁定提高系统效率 DM也提供了两个函数 SET_TABLE_OPTION([db.][sch.]tablename, option, value) 、SET_INDEX_OPTION([db.]indexname, option, value)(具体语法参见《 DM_SQL语言使用手册》第 8 章)供用户自行定义锁定类型,以增强系统并发度,提高系统效率。这两个函数是为那些清楚地知道特定类型的锁适用于何种情况的专家级用户提供的。 函数SET_TABLE_OPTION() 用于禁用指定表上的页级锁、行级锁或同时禁用二者,这一设置对该表上的所有索引都生效。函数 SET_INDEX_OPTION() 则用于禁用某一索引上的页级锁、行级锁或同时禁用二者。 例如,当用户只需要修改索引中某定长字段时,修改操作不会造成 B 树的分裂与合并,此时就可以禁用该索引的页级锁。又如,当所有的用户都只做插入操作时,用户之间并不会对同一元组进行操作,此时就可以禁用行级锁。当用户能保证不对表进行增、删、改,而只是进行查询时,则可以同时禁用该表上的页级锁和行级锁,此时并发度最高。 6. 死锁处理 解决死锁问题的三种方法:预防死锁、检测死锁及避免死锁。死锁预防要求用户进程事先申报所需的资源或按严格的规程申请资源,而死锁检测原则上应允许死锁发生,在适当的时机检查,若发生死锁,则设法排除之。与预防死锁相比,后者过于放手,致使死锁频繁。而避免死锁则以事务撤消为前提,当不能获得资源批准时,立刻进行死锁检测。它既不象预防死锁那样过于保守,也不象死锁检测那样过于放开,由于检测及时,由归纳法可知,在已获准等待的事务中,不可能存在死锁,所以检测算法比较简单。 DM4系统采用的是避免死锁方法。每当一个事务所申请占有的资源不能被立即获得时,便进行死锁检测,不存在死锁,则该事务入等待队列。否则,DM4视为产生运行时错误,将当前语句回滚。采用这种机制,从用户的角度看,DM4不存在解锁问题。 7. 加索引和不加索引的封锁区别 加索引和不加索引的情况下,DM的封锁机制会影响到实际的封锁范围。索引的作用就在于,可以在查询中减少对无关数据的扫描。而在一般的隔离级中,总是要对扫描到的数据进行封锁。所以,利用索引可以减少封锁的数量,冲突的可能性也会大大减少。
    展开全文
  • 多线程与高并发

    千次阅读 2019-05-13 18:18:57
    在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战。如果Web系统不做针对性的优化,会轻而易举地陷入到异常状态。我们现在一起来讨论下,优化的思路和方法哈。...

    关键词:

    线程,同步,单例,高并发,高访问,死锁

    一、大规模并发带来的挑战
    在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战。如果Web系统不做针对性的优化,会轻而易举地陷入到异常状态。我们现在一起来讨论下,优化的思路和方法哈。

    1. 请求接口的合理设计
    一个秒杀或者抢购页面,通常分为2个部分,一个是静态的HTML等内容,另一个就是参与秒杀的Web后台请求接口。

    通常静态HTML等内容,是通过CDN的部署,一般压力不大,核心瓶颈实际上在后台请求接口上。这个后端接口,必须能够支持高并发请求,同时,非常重要的一点,必须尽可能“快”,在最短的时间里返回用户的请求结果。为了实现尽可能快这一点,接口的后端存储使用内存级别的操作会更好一点。仍然直接面向 MySQL之类的存储是不合适的,如果有这种复杂业务的需求,都建议采用异步写入。

    当然,也有一些秒杀和抢购采用“滞后反馈”,就是说秒杀当下不知道结果,一段时间后才可以从页面中看到用户是否秒杀成功。但是,这种属于“偷懒”行为,同时给用户的体验也不好,容易被用户认为是“暗箱操作”。

    2. 高并发的挑战:一定要“快”
    我们通常衡量一个Web系统的吞吐率的指标是QPS(Query Per Second,每秒处理请求数),解决每秒数万次的高并发场景,这个指标非常关键。举个例子,我们假设处理一个业务请求平均响应时间为100ms,同时, 系统内有20台Apache的Web服务器,配置MaxClients为500个(表示Apache的最大连接数目)。

    那么,我们的Web系统的理论峰值QPS为(理想化的计算方式):

    20*500/0.1 = 100000 (10万QPS)

    咦?我们的系统似乎很强大,1秒钟可以处理完10万的请求,5w/s的秒杀似乎是“纸老虎”哈。实际情况,当然没有这么理想。在高并发的实际场景下,机器都处于高负载的状态,在这个时候平均响应时间会被大大增加。

    就Web服务器而言,Apache打开了越多的连接进程,CPU需要处理的上下文切换也越多,额外增加了CPU的消耗,然后就直接导致平均响应时间 增加。因此上述的MaxClient数目,要根据CPU、内存等硬件因素综合考虑,绝对不是越多越好。可以通过Apache自带的abench来测试一 下,取一个合适的值。然后,我们选择内存操作级别的存储的Redis,在高并发的状态下,存储的响应时间至关重要。网络带宽虽然也是一个因素,不过,这种 请求数据包一般比较小,一般很少成为请求的瓶颈。负载均衡成为系统瓶颈的情况比较少,在这里不做讨论哈。

    那么问题来了,假设我们的系统,在5w/s的高并发状态下,平均响应时间从100ms变为250ms(实际情况,甚至更多):

    20*500/0.25 = 40000 (4万QPS)

    于是,我们的系统剩下了4w的QPS,面对5w每秒的请求,中间相差了1w。

    然后,这才是真正的恶梦开始。举个例子,高速路口,1秒钟来5部车,每秒通过5部车,高速路口运作正常。突然,这个路口1秒钟只能通过4部车,车流量仍然依旧,结果必定出现大塞车。(5条车道忽然变成4条车道的感觉)

    同理,某一个秒内,20*500个可用连接进程都在满负荷工作中,却仍然有1万个新来请求,没有连接进程可用,系统陷入到异常状态也是预期之内。

    其实在正常的非高并发的业务场景中,也有类似的情况出现,某个业务请求接口出现问题,响应时间极慢,将整个Web请求响应时间拉得很长,逐渐将Web服务器的可用连接数占满,其他正常的业务请求,无连接进程可用。

    更可怕的问题是,是用户的行为特点,系统越是不可用,用户的点击越频繁,恶性循环最终导致“雪崩”(其中一台Web机器挂了,导致流量分散到其他正常工作的机器上,再导致正常的机器也挂,然后恶性循环),将整个Web系统拖垮。

    3. 重启与过载保护
    如果系统发生“雪崩”,贸然重启服务,是无法解决问题的。最常见的现象是,启动起来后,立刻挂掉。这个时候,最好在入口层将流量拒绝,然后再将重启。如果是redis/memcache这种服务也挂了,重启的时候需要注意“预热”,并且很可能需要比较长的时间。

    秒杀和抢购的场景,流量往往是超乎我们系统的准备和想象的。这个时候,过载保护是必要的。如果检测到系统满负载状态,拒绝请求也是一种保护措施。在前端设置过滤是最简单的方式,但是,这种做法是被用户“千夫所指”的行为。更合适一点的是,将过载保护设置在CGI入口层,快速将客户的直接请求返回。

     

    二、作弊的手段:进攻与防守
    秒杀和抢购收到了“海量”的请求,实际上里面的水分是很大的。不少用户,为了“抢“到商品,会使用“刷票工具”等类型的辅助工具,帮助他们发送尽可 能多的请求到服务器。还有一部分高级用户,制作强大的自动请求脚本。这种做法的理由也很简单,就是在参与秒杀和抢购的请求中,自己的请求数目占比越多,成功的概率越高。

    这些都是属于“作弊的手段”,不过,有“进攻”就有“防守”,这是一场没有硝烟的战斗哈。

    1. 同一个账号,一次性发出多个请求
    部分用户通过浏览器的插件或者其他工具,在秒杀开始的时间里,以自己的账号,一次发送上百甚至更多的请求。实际上,这样的用户破坏了秒杀和抢购的公平性。

    这种请求在某些没有做数据安全处理的系统里,也可能造成另外一种破坏,导致某些判断条件被绕过。例如一个简单的领取逻辑,先判断用户是否有参与记 录,如果没有则领取成功,最后写入到参与记录中。这是个非常简单的逻辑,但是,在高并发的场景下,存在深深的漏洞。多个并发请求通过负载均衡服务器,分配到内网的多台Web服务器,它们首先向存储发送查询请求,然后,在某个请求成功写入参与记录的时间差内,其他的请求获查询到的结果都是“没有参与记录”。 这里,就存在逻辑判断被绕过的风险。

    应对方案:

    在程序入口处,一个账号只允许接受1个请求,其他请求过滤。不仅解决了同一个账号,发送N个请求的问题,还保证了后续的逻辑流程的安全。实现方案, 可以通过Redis这种内存缓存服务,写入一个标志位(只允许1个请求写成功,结合watch的乐观锁的特性),成功写入的则可以继续参加。

    或者,自己实现一个服务,将同一个账号的请求放入一个队列中,处理完一个,再处理下一个。

    2. 多个账号,一次性发送多个请求
    很多公司的账号注册功能,在发展早期几乎是没有限制的,很容易就可以注册很多个账号。因此,也导致了出现了一些特殊的工作室,通过编写自动注册脚 本,积累了一大批“僵尸账号”,数量庞大,几万甚至几十万的账号不等,专门做各种刷的行为(这就是微博中的“僵尸粉“的来源)。举个例子,例如微博中有转 发抽奖的活动,如果我们使用几万个“僵尸号”去混进去转发,这样就可以大大提升我们中奖的概率。

    这种账号,使用在秒杀和抢购里,也是同一个道理。例如,iPhone官网的抢购,火车票黄牛党。

    应对方案:

    这种场景,可以通过检测指定机器IP请求频率就可以解决,如果发现某个IP请求频率很高,可以给它弹出一个验证码或者直接禁止它的请求:

    弹出验证码,最核心的追求,就是分辨出真实用户。因此,大家可能经常发现,网站弹出的验证码,有些是“鬼神乱舞”的样子, 有时让我们根本无法看清。他们这样做的原因,其实也是为了让验证码的图片不被轻易识别,因为强大的“自动脚本”可以通过图片识别里面的字符,然后让脚本自 动填写验证码。实际上,有一些非常创新的验证码,效果会比较好,例如给你一个简单问题让你回答,或者让你完成某些简单操作(例如百度贴吧的验证码)。
    直接禁止IP,实际上是有些粗暴的,因为有些真实用户的网络场景恰好是同一出口IP的,可能会有“误伤“。但是这一个做法简单高效,根据实际场景使用可以获得很好的效果。
    3. 多个账号,不同IP发送不同请求
    所谓道高一尺,魔高一丈。有进攻,就会有防守,永不休止。这些“工作室”,发现你对单机IP请求频率有控制之后,他们也针对这种场景,想出了他们的“新进攻方案”,就是不断改变IP。

    有同学会好奇,这些随机IP服务怎么来的。有一些是某些机构自己占据一批独立IP,然后做成一个随机代理IP的服务,有偿提供给这些“工作 室”使用。还有一些更为黑暗一点的,就是通过木马黑掉普通用户的电脑,这个木马也不破坏用户电脑的正常运作,只做一件事情,就是转发IP包,普通用户的电 脑被变成了IP代理出口。通过这种做法,黑客就拿到了大量的独立IP,然后搭建为随机IP服务,就是为了挣钱。

    应对方案:

    说实话,这种场景下的请求,和真实用户的行为,已经基本相同了,想做分辨很困难。再做进一步的限制很容易“误伤“真实用户,这个时候,通常只能通过设置业务门槛高来限制这种请求了,或者通过账号行为的”数据挖掘“来提前清理掉它们。

    僵尸账号也还是有一些共同特征的,例如账号很可能属于同一个号码段甚至是连号的,活跃度不高,等级低,资料不全等等。根据这些特点,适当设置参与门槛,例如限制参与秒杀的账号等级。通过这些业务手段,也是可以过滤掉一些僵尸号。

    4. 火车票的抢购
    看到这里,同学们是否明白你为什么抢不到火车票?如果你只是老老实实地去抢票,真的很难。通过多账号的方式,火车票的黄牛将很多车票的名额占据,部分强大的黄牛,在处理验证码方面,更是“技高一筹“。

    高级的黄牛刷票时,在识别验证码的时候使用真实的人,中间搭建一个展示验证码图片的中转软件服务,真人浏览图片并填写下真实验证码,返回给中转软件。对于这种方式,验证码的保护限制作用被废除了,目前也没有很好的解决方案。

    因为火车票是根据身份证实名制的,这里还有一个火车票的转让操作方式。大致的操作方式,是先用买家的身份证开启一个抢票工具,持续发送请 求,黄牛账号选择退票,然后黄牛买家成功通过自己的身份证购票成功。当一列车厢没有票了的时候,是没有很多人盯着看的,况且黄牛们的抢票工具也很强大,即 使让我们看见有退票,我们也不一定能抢得过他们哈。

    最终,黄牛顺利将火车票转移到买家的身份证下。

    解决方案:

    并没有很好的解决方案,唯一可以动心思的也许是对账号数据进行“数据挖掘”,这些黄牛账号也是有一些共同特征的,例如经常抢票和退票,节假日异常活跃等等。将它们分析出来,再做进一步处理和甄别。

     

    三、高并发下的数据安全
    我们知道在多线程写入同一个文件的时候,会存现“线程安全”的问题(多个线程同时运行同一段代码,如果每次运行结果和单线程运行的结果是一 样的,结果和预期相同,就是线程安全的)。如果是MySQL数据库,可以使用它自带的锁机制很好的解决问题,但是,在大规模并发的场景中,是不推荐使用 MySQL的。秒杀和抢购的场景中,还有另外一个问题,就是“超发”,如果在这方面控制不慎,会产生发送过多的情况。我们也曾经听说过,某些电商搞抢购活动,买家成功拍下后,商家却不承认订单有效,拒绝发货。这里的问题,也许并不一定是商家奸诈,而是系统技术层面存在超发风险导致的。

    1. 超发的原因
    假设某个抢购场景中,我们一共只有100个商品,在最后一刻,我们已经消耗了99个商品,仅剩最后一个。这个时候,系统发来多个并发请求,这批请求读取到的商品余量都是99个,然后都通过了这一个余量判断,最终导致超发。(同文章前面说的场景)

    在上面的这个图中,就导致了并发用户B也“抢购成功”,多让一个人获得了商品。这种场景,在高并发的情况下非常容易出现。

    2. 悲观锁思路
    解决线程安全的思路很多,可以从“悲观锁”的方向开始讨论。

    悲观锁,也就是在修改数据的时候,采用锁定状态,排斥外部请求的修改。遇到加锁的状态,就必须等待。

    虽然上述的方案的确解决了线程安全的问题,但是,别忘记,我们的场景是“高并发”。也就是说,会很多这样的修改请求,每个请求都需要等待 “锁”,某些线程可能永远都没有机会抢到这个“锁”,这种请求就会死在那里。同时,这种请求会很多,瞬间增大系统的平均响应时间,结果是可用连接数被耗 尽,系统陷入异常。

    3. FIFO队列思路
    那好,那么我们稍微修改一下上面的场景,我们直接将请求放入队列中的,采用FIFO(First Input First Output,先进先出),这样的话,我们就不会导致某些请求永远获取不到锁。看到这里,是不是有点强行将多线程变成单线程的感觉哈。

    然后,我们现在解决了锁的问题,全部请求采用“先进先出”的队列方式来处理。那么新的问题来了,高并发的场景下,因为请求很多,很可能一瞬 间将队列内存“撑爆”,然后系统又陷入到了异常状态。或者设计一个极大的内存队列,也是一种方案,但是,系统处理完一个队列内请求的速度根本无法和疯狂涌 入队列中的数目相比。也就是说,队列内的请求会越积累越多,最终Web系统平均响应时候还是会大幅下降,系统还是陷入异常。

    4. 乐观锁思路
    这个时候,我们就可以讨论一下“乐观锁”的思路了。乐观锁,是相对于“悲观锁”采用更为宽松的加锁机制,大都是采用带版本号 (Version)更新。实现就是,这个数据所有请求都有资格去修改,但会获得一个该数据的版本号,只有版本号符合的才能更新成功,其他的返回抢购失败。 这样的话,我们就不需要考虑队列的问题,不过,它会增大CPU的计算开销。但是,综合来说,这是一个比较好的解决方案。

    有很多软件和服务都“乐观锁”功能的支持,例如Redis中的watch就是其中之一。通过这个实现,我们保证了数据的安全。

     

    四、小结
    互联网正在高速发展,使用互联网服务的用户越多,高并发的场景也变得越来越多。电商秒杀和抢购,是两个比较典型的互联网高并发场景。虽然我们解决问题的具体技术方案可能千差万别,但是遇到的挑战却是相似的,因此解决问题的思路也异曲同工。


     

    五、关于并发

    通过上面的抢购和秒杀的例子来探讨并发的出现场景及处理高并发的相应技术。

    关于多线程和并发的知识:

    1、    什么是并发?

    在互联网时代,所讲的并发、高并发,通常是指并发访问。也就是在某个时间点,有多少个访问同时到来。(PV(page view)即页面浏览量。)

    一台服务器在单位时间里能处理的请求越多,服务器的能力越高,也就是服务器并发处理能力越强。服务器的本质工作就是,争取以最快的速度将内核缓冲区中的用户请求数据一个不剩地都拿出来,然后尽快处理,再将响应数据放到一块又能够与发送数据的缓冲区中,接着处理下一拨请求。

    2、    衡量服务器并发处理能力?

    高并发相关常用的一些指标有响应时间(Response Time),吞吐量(Throughput),每秒查询率QPS(Query Per Second),并发用户数等。

    响应时间:系统对请求做出响应的时间。例如系统处理一个HTTP请求需要200ms,这个200ms就是系统的响应时间。

    吞吐量:单位时间内处理的请求数量。

    QPS:每秒响应请求数。在互联网领域,这个指标和吞吐量区分的没有这么明显。

    并发用户数:同时承载正常使用系统功能的用户数量。例如一个即时通讯系统,同时在线量一定程度上代表了系统的并发用户数。

    3、    如何提高服务器的并发处理能力?

    有两种方式:第一种就是提高单机的性能;

    第二种就是互联网的分布式开发架构,增加机器的数量。

    其实还可以通过减少无用请求来降低服务器的压力。例如微博的僵尸粉,购票的黄牛。

    【1】提高CPU并发计算能力

    (1)多进程&多线程

    (2)减少进程切换,使用线程,考虑进程绑定CPU

    (3)减少使用不必要的锁,考虑无锁编程

    (4)考虑进程优先级

    (5)关注系统负载

    (6)关注CPU使用率,除了用户空间和内核空间的CPU使用率以外,还要关注I/O wait

    【2】减少系统调用

    【3】考虑减少内存分配和释放

    (1)改善数据结构和算法复制度

    (2)使用内存池

    (3)考虑使用共享内存

    【4】考虑使用持久连接

    【5】改进I/O模型

    (1)DMA技术

    (2)异步I/O

    (3)改进多路I/O就绪通知策略,epoll

    (4)Sendfile

    (5)内存映射

    (6)直接I/O

    【6】改进服务器并发策略

    (1)一个进程处理一个连接,非阻塞I/O,使用长连接

    (2)一个进程处理多个连接,异步I/O,使用长连接

    【7】改进硬件环境

    4、    总结

    高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。

    提高系统并发能力的方式,方法论上主要有两种:垂直扩展(Scale Up)与水平扩展(Scale Out)。前者垂直扩展可以通过提升单机硬件性能,或者提升单机架构性能,来提高并发性,但单机性能总是有极限的,互联网分布式架构设计高并发终极解决方案还是后者:水平扩展。

    互联网分层架构中,各层次水平扩展的实践又有所不同:

    (1)反向代理层可以通过“DNS轮询”的方式来进行水平扩展;

    (2)站点层可以通过nginx来进行水平扩展;

    (3)服务层可以通过服务连接池来进行水平扩展;

    (4)数据库可以按照数据范围,或者数据哈希的方式来进行水平扩展;

    各层实施水平扩展后,能够通过增加服务器数量的方式来提升系统的性能,做到理论上的性能无限。

    5、    多线程和并发有什么关系?

    【1】多线程

    (1)java本身就是多线程的;

    (2)java的多线程是一种编程思想,一个程序执行之后就成为一个进程,所谓的多线程就是在一个进程中有多个线程存在,在宏观上是多个线程同时运行,可以使进程同时完成多件事,微观上是cpu在多个线程之间切换,在某一时刻还是执行一个线程。

    【2】并发

    (3)并发一般指 "并发访问", 如若干应用程序从不同的客户端同时访问同一个服务器端的数据库,服务器应用一定的承受能力处理并发的请求,并发请求被进程或是进程里面的线程处理,并发访问用并发编程处理其实最好的解决办法就是多线程。

    (4)并发编程是多线程编程的一种应用。

    (5)无论你是做web开发,还是数据库开发,还是桌面开发,都会用到多线程的。

    (6)因为有并发的这个实际的需求,所以出现了多线程。

    【3】

    (1)高并发不是JAVA的专有的东西,是语言无关的广义的,为提供更好互联网服务而提出的概念。举个极端的例子,就是100个人,1人分配1台web服务器,那么服务器资源是他们独占的,他们不需要抢占服务器资源,100个请求被100台服务器并行处理,速度必定很快,这就是高并发。当然这是不可能的,但是,我们总是努力去做,让少量的服务器也能达到近似的能力。这就需要服务器的HTML画面,后台业务逻辑,db数据存取等等细节上的处理都达到一个并行的极致,以此来实现整个服务器对所有请求的高并行。这是战略上的并行。多线程只是为了达到高并发目的,在某个细节点上,为实现某并发功能而采用的一种具体的实现方法,这种功能也可以由多进程实现,当然,也可以由多进程,多线程一起实现。这是战术上的并行。那么可以说,高并发是目的,多线程是某种手段(不是唯一的),高并发可以由多线程实现,但是多线程不代表就是高并发。

    (2)并发与多线程之间的关系就是目的与手段之间的关系。并发(Concurrent)的反面是串行。串行好比多个车辆行驶在一股车道上,它们只能“鱼贯而行”。而并发好比多个车辆行驶在多股车道上,它们可以“并驾齐驱”。并发的极致就是并行(Parallel)。多线程就是将原本可能是串行的计算“改为”并发(并行)的一种手段、途径或者模型。因此,有时我们也称多线程编程为并发编程。当然,目的与手段之间常常是一对多的关系。并发编程还有其他的实现途径,例如函数式(Functional programming)编程。多线程编程往往是其他并发编程模型的基础,所以多线程编程的重要性不言而喻。

    综合上面几点可以看出:并发,就是服务器同时处理多个请求的能力,而处理并发的最好的办法,就是采用多线程。cpu快速调用不同的就绪队列,看起来好像是同步进行,实际还是一个线程一个线程的处理的,但这样,就大大提高了服务器的效率,减少了线程的等待时间。

    即可以这么理解:多线程是处理高并发的一种编程方法。即并发需要用多线程实现。

    当有海量的请求时,服务器没有连接的进程可用,系统就会产生异常。

     

    6、    在具体项目中,什么情况下用到了多线程?

    【1】如果做 java web方面开发的话几乎用不到多线程!因为有多线程的地方 servlet 容器或者其他开发框架都已经实现掉了!一般在网络应用程序中使用多线程的地方非常多!另外,拷贝文件使用多线程,是没有用的!以多线程来提高效率的场景一般在 CPU 计算型,而不是在 IO 读写型。CPU 可以会有多个核心并行处理计算,但是磁盘 IO 就没这功能了,磁头只有一个,根本不可能靠多线程提高效率!一般来说,磁盘 IO 的并发能力为 0,也就是说无法支持并发!网络 IO 的话由于带宽的限制的,使用多线程处理最多也只能达到带宽的极值。对于磁盘 IO 来说,多线程可以用于一个线程专门用于读写文件,其他的线程用于对读取数据进行处理,这样才有可能更好地利用 CPU 资源。如果仅仅是单纯的文件复制,使用多线程操作的话,会使用磁头在磁盘上不停地进行寻道操作,使得效率更为低下!

    【2】压力测试时,会用到多线程。

    【3】服务器编程时,会用到多线程。

    【4】使用监听器时,可能会用到多线程。

    【5】跑JOB时,可能会用到多线程。

    【6】还有一种极为普遍的使用多线程的场景是UI编程,一般UI界面绘制于主线程,为了不阻塞主线程让用户体验更流畅,需要创建单独的线程处理耗时操作,处理完了再更新主界面,典型的案例就是android应用开发。

    【7】一些C/S模式比如说网络游戏(基于socket协议)一般在服务器那边处理的时候一个客户端,一个线程;还有就是一些银行软件,用到了线程同步等等。

    7、    高并发事件的出现的场景

    (1)     服务器在每秒内处理请求数是一定,当访问量太大时,没有多余的进程来处理这些请求,就会造成系统的瘫痪。系统崩溃,例如前段时间微博的瘫痪,就是短时间内流量太大了,导致系统处于异常状态,页面无法显示,用户无法登陆等;电商中抢购,秒杀中出现超发的情况,多个用户同时购买同一物品,访问修改同一数据等情况。

    (2)     由于购票、查询和浏览的数量激增,12306网站每天访问量比平时增长数十倍,经常出现登录难的现象,近日甚至出现了付款不出票、系统干脆瘫痪的情况。网络订票原本是一项便民利民的措施,却由于铁道部未正确预估网站并发情况、技术支持不足而导致相反的结果。IT业界人士纷纷指出,12306网站瘫痪最大的原因是“技术之罪”。并针对高并发网站引发的技术考验,纷纷献技献策、展开讨论,提出了很多具指导意义的技术解决方案。

    (3)     此次12306网站难登录并瘫痪是系统架构规划的问题,导致不能有效支持大并发量集中访问。同时,12306在IT管理上也有问题,未能进行有效的压力测试和运行模拟。

    8、    高并发下出现的超发问题的解决方案

    项目中:

    【1】在点击购物车的提交订单按钮时,会判断库存是否足够,不足,会拒绝提交订单。

    【2】当库存只有一件时,两个客户,或多个客户经过在购物车提交订单判断,在订单页面进行支付时判断,同时都满足了购买一件产品的需求,那么,让谁购买成功?岂不是多个用户同时都支付了这同一件商品?这种情况就是超发,下面将解决高并发下的这种超发的问题。

    【3】假设 个,B客户购买6个:

    (1)在点击提交订单时,两这同时判断库存满足,进入到订单界面;(2)然后 A先支付完成,在支付时,减少库存(此时做判断,如果库存足够,支付成功,否则支付失败)---》PS:跟12306购票系统相似。(3)然后B慢一步也进入到支付,判断,此时库存只有5个,不让支付,支付失败。(4)如果两者同时进行支付呢?怎么改变库存,让谁购买成功?这就涉及到了加锁,同步的问题。下面就讨论这个问题 的解决方案。、

    【4】涉及到的知识点技术

    (1)    悲观锁:解决线程安全的思路很多,可以从“悲观锁”的方向开始讨论。悲观锁,也就是在修改数据的时候,采用锁定状态,排斥外部请求的修改。遇到加锁的状态,就必须等待。虽然上述的方案的确解决了线程安全的问题,但是,别忘记,我们的场景是“高并发”。也就是说,会很多这样的修改请求,每个请求都需要等待“锁”,某些线程可能永远都没有机会抢到这个“锁”,这种请求就会死在那里。同时,这种请求会很多,瞬间增大系统的平均响应时间,结果是可用连接数被耗尽,系统陷入异常。

    自己理解:悲观锁就是给要修改的数据加上锁,同步。其他请求需要等待。把数据锁住。

    怎么实现?具体怎么在代码中写。需要了解的。

    一般意义上的加锁指两个层面:代码层次,如java中的同步锁,典型的就是同步关键字synchronized ;数据库层次,如悲观锁(物理锁)和乐观锁。

    悲观锁:通过数据库的forupdate字段实现加锁。

    for update要放到mysql的事务中,即begin和commit中,否者则不起作用。

    (2)FIFO队列思路

    那好,那么我们稍微修改一下上面的场景,我们直接将请求放入队列中的,采用FIFO(First Input FirstOutput,先进先出),这样的话,我们就不会导致某些请求永远获取不到锁。看到这里,是不是有点强行将多线程变成单线程的感觉哈。

    然后,我们现在解决了锁的问题,全部请求采用“先进先出”的队列方式来处理。那么新的问题来了,高并发的场景下,因为请求很多,很可能一瞬间将队列内存“撑爆”,然后系统又陷入到了异常状态。或者设计一个极大的内存队列,也是一种方案,但是,系统处理完一个队列内请求的速度根本无法和疯狂涌 入队列中的数目相比。也就是说,队列内的请求会越积累越多,最终Web系统平均响应时候还是会大幅下降,系统还是陷入异常。(3)乐观锁思路

    这个时候,我们就可以讨论一下“乐观锁”的思路了。乐观锁,是相对于“悲观锁”采用更为宽松的加锁机制,大都是采用带版本号(Version)更新。实现就是,这个数据所有请求都有资格去修改,但会获得一个该数据的版本号,只有版本号符合的才能更新成功,其他的返回抢购失败。这样的话,我们就不需要考虑队列的问题,不过,它会增大CPU的计算开销。但是,综合来说,这是一个比较好的解决方案。有很多软件和服务都“乐观锁”功能的支持,例如Redis中的watch就是其中之一。通过这个实现,我们保证了数据的安全。

    自己理解:修改版本号,version。

    假设数据库中帐户信息表中有一个 version字段,当前值为 1 ;而当前帐户余额字段( balance )为 $100 。 操作员 A 此时将其读出( version=1 ),并从其帐户余额中扣除 $50( $100-$50 )。 2 在操作员 A 操作的过程中,操作员 B 也读入此用户信息( version=1 ),并 从其帐户余额中扣除 $20 ( $100-$20 )。 3 操作员 A完成了修改工作,将数据版本号加一( version=2 ),连同帐户扣 除后余额( balance=$50 ),提交至数据库更新,此时由于提交数据版本大 于数据库记录当前版本,数据被更新,数据库记录 version 更新为 2 。 4 操作员 B 完成了操作,也将版本号加一( version=2 )试图向数据库提交数据( balance=$80 ),但此时比对数据库记录版本时发现,操作员 B提交的 数据版本号为 2 ,数据库记录当前版本也为 2 ,不满足“ 提交版本必须大于记 录当前版本才能执行更新 “ 的乐观锁策略,因此,操作员 B 的提交被驳回。 这样,就避免了操作员 B 用基于

     

    version=1 的旧数据修改的结果覆盖操作员 A 的操作结果的可能。 从上面的例子可以看出,乐观锁机制避免了长事务中的数据库加锁开销(操作员 A和操作员 B 操作过程中,都没有对数据库数据加锁),大大提升了大并发量下的系统整体性能表现。

    (4)Mysql的数据库的锁机制

        锁

    (5)关于事务和脏数据

    脏数据,不可重复读,幻读

    解决:

    9、    我对多线程及高并发的了解

    我对线程和并发的了解可能比较浅显,理论化,基础化,因为我接触的项目中,并没有深入的处理过并发和多线程的处理,我对于并发的处理只是在分布式开发和负载均衡中提高项目的并发处理能力。多线程的了解就是对同步(就是加锁)和servlet的单例多线程有一定的了解。

    谈到高并发,就是服务器端同时处理海量请求的能力。当出现高并发时,可能会出现超发的情况:(详细介绍,结合自己项目中遇到的超发问题)

    当请求超过服务器的承受限制,还可能会使服务器崩溃。此时,我们可以通过分布式开发的架构,将业务细化为多个子业务,这样既可以增加了后台服务器对高访问的业务的请求处理能力,同时还便于后期的升级维护,各个子业务之间的维护升级更加简单,通过远程调用来实现各个子业务之间的联系。此外,还可以通过集群,来提高服务器的并发能力。这种提高服务器的并发能力的方式也成为水平提高服务器的并发能力,这也是未来发展的趋势。

    此外,就是通过单机,通过提高cpu等单个物理机器的性能,来提高服务器的并发能力。

    PS:web服务器都是已经实现了多线程的。

    所以我要了解的就是怎么处理超发的问题,在处理超发的前提下,我要对什么是高并发,高并发和多线程有什么关系搞清楚。

    关于实际中编码中我所接触到的对于多线程,和并发访问有四点:

    【1】在讲多线程时,关于火车票的简单代码和同步代码块,了解了多线程的底层代码。

    public class SaleTicket3 implements Runnable{
        private int ticket=5;
    
        @override
        public void run(){
            for(int i=0;i<100;i++){
                sale();
            }
        }
        public synchronized void sale(){
            if(ticket>0){
                try(){
                    Thread.sleep(300);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"卖第"+(ticket--)+"");
            }
        }
    }

    【2】在讲servlet时的单例多线程。

    双重检验,为什么要用多线程?就是为了提高cpu的利用率,(提高并发能力)如果同步方法,跟单线程的区别并不大,所以,同步共同的资源对象,缩小锁定的范围,故用双重检验。

       

    【3】在讲解电商项目时,分布式开发和Nginx的负载均衡的集群建立。

    【4】Web服务器都是实现了多线程的,现阶段不需要编写多线程。
     

    展开全文
  • 2w字 + 40张图带你参透并发编程!

    千次阅读 多人点赞 2020-08-19 07:28:16
    并发历史 在计算机最早期的时候,没有操作系统,执行程序只需要一种方式,那就是从头到尾依次执行。任何资源都会为这个程序服务,在计算机使用某些资源时,其他资源就会空闲,就会存在 浪费资源 的情况。 这里说的...
  • 说白了就是,很有必要去理解一般ETL工具必备的特性和功能,这样才更好的掌握Kettle的使用。今天主要先描述ETL工具的通用功能。 一、连接 任何ETL工具都应该有能力连接到类型广泛的数据源和数据格式。对于最...
  • Java高并发解决方案

    万次阅读 多人点赞 2019-03-03 22:23:50
    电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。...在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个W...
  • 在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战。如果Web系统不做针对性的优化,会轻而易举地陷入到异常状态。我们现在一起来讨论下,优化的思路和方法哈。...
  • 在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战。如果Web系统不做针对性的优化,会轻而易举地陷入到异常状态。我们现在一起来讨论下,优化的思路和方法哈。...
  • 1.传统的OS中应具有处理机管理、存储器管理、设备管理和文件管理等基本功能。 其中处理机管理功能:在传统的多道程序系统中,处理机的分配和运行都是...在多道程序环境下为使作业能并发执行,必须为每道作业创建一个或
  • Java 高并发解决方案(电商的秒杀和抢购)

    万次阅读 多人点赞 2018-07-25 14:08:08
    电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。当一个Web系统,在...在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整...
  • 需要进行大量的培训考试的大集团,员工人数也会上千以前,那么这时我们要看在线考试系统的并发性,选择并发控制比较好的系统。 并发性概括 所谓并发性,是指在相同的时间间隔内,有两个或两个以上的...
  • 并发支付场景分析及设计

    千次阅读 2018-12-04 23:46:09
    一、专题分享-高并发支付场景分析及设计1.1 背景 大家好,我是20XX年加入永乐票务,之前一直负责公司票务系统的整体规划、实现、优化及改造。目前主要负责公司的基础平台、支付平台、消息平台、云平台、运维平台、...
  • Web系统大规模并发处理

    千次阅读 2017-01-23 22:11:57
    面对5w每秒的高并发秒杀功能,如果Web系统不做针对性的优化,会轻而易举地陷入到异常状态。我们现在一起来讨论下,优化的思路和方法哈。  1. 请求接口的合理设计 一个秒杀或者抢购页面,通常分为2个部分,...
  • tomcat7 性能优化,提高并发

    万次阅读 多人点赞 2018-01-25 18:07:54
    通过优化tomcat提高网站的并发能力。当我们今天我们将这个优化讲完之前 优化完成后看能达到什么层次。     2. 服务器资源 服务器所能提供CPU、内存、硬盘的性能对处理能力有决定性影响。硬件我们不...
  • Java Web应用高并发性能优化方案汇总

    千次阅读 2019-02-22 18:35:43
    公司开发的一个门户系统运行几年了,最近因为客户的组织机构调整,要大幅增加用户数,于是开始了一场对系统并发性能进行调优的艰难之旅。 本文记录一个传统Java Web系统性能调优过程的方方面面,希望将来能成为...
  • 并发情况

    千次阅读 2017-06-28 15:54:39
    电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。当一个Web系统,在...在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个W
  • #0 系列目录#秒杀系统架构秒杀系统架构分析与实战#1 秒杀业务分析#正常电子商务流程(1)查询商品;...#2 秒杀技术挑战# 假设某网站秒杀活动只推出一件商品,预计会吸引1万人参加活动,也就说最大并发请求数是1000...
  • 超硬核!操作系统学霸笔记,考试复习面试全靠它

    万次阅读 多人点赞 2021-03-22 18:43:49
    基本知识 进程控制是进程管理中最基本的功能,主要包括进程的创建,进程的终止和运行中的进程的状态转换等功能。进程控制一般是由OS的内核中的原语来实现的。 2.进程的创建 进程的层次结构 进程图 引起进程创建的...
  • 数据库的基本概念总结 1. 数据库定义:数据库是长期储存在计算机内、有组织的、可共享的大量数据的集合。...主要功能:1,数据定义功能。2,数据组织、存储和管理。3,数据操纵功能。4,数据库的事务管理和
  • 9管理信息系统.doc

    2022-06-17 10:43:44
    【 】数据库的并发控制功能可以防止多个用户同时修改数据。 10. 【 】TCP/IP是一套为电子邮件能够正常发送与接收的协议。 11. 【 】企业信息系统的对信息的处理大部分不随业务的改变而变化。 12. 【 】可以用姓名...
  • 电商中常见的高并发设计

    千次阅读 2018-07-02 15:22:46
    一、大规模并发带来的挑战在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战。如果Web系统不做针对性的优化,会轻而易举地陷入到异常状态。我们现在一起来讨论...
  • 什么是服务器的高并发

    千次阅读 2018-03-02 11:18:04
    在网上购物,秒抢某个商品,比如说小米...1、大规模并发带来的挑战比如说5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战。如果Web系统不做针对性的优化,会轻而易举地陷入到异常状态。...
  • 电商实例、业务并发、网站并发及解决方法 一、怎么防止多用户同一时间抢购同一商品,防止高并发同时下单同一商品  最近在做抢购系统,但头疼的是,在多用户高并发的情况下经常会库存出现问题。排查到,在同一...
  • 数据库的安全控制

    千次阅读 2019-12-11 12:29:43
    (2)物理控制方面的问题。 (3)政策反面的问题。 (4)运行方面的问题。 (5)硬件方面的问题。 (6)操作系统安全性方面的问题. (7)数据库系统本身的安全性方面的问题。 2.安全性控制的一般发方法 ...
  • Python并发编程之进程的玩法

    千次阅读 多人点赞 2021-06-13 22:59:28
    当用于轧钢、石化等工业生产过程控制时,也要求计算机能及时处理由各类传感器送来的数据,然后控制相应的执行机构。 (2)实时信息处理系统。当用于预定飞机票、查询有关航班、航线、票价等事宜时,或当用于银行系统...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,843
精华内容 10,337
热门标签
关键字:

并发控制机构的功能