系统的许多交互并不是在一个数据库事物中完成的。这就要求在跨事物的数据处理中管理好并发问题,称为离线并发,
其含义是多数据库事物中数据操作的并发控制。
无论什么时候用多线程火多进程操作同一数据的时候,都会遇到并发问题,
更新丢失------
例如:A编辑了一个文件,对其中的checkConcurrency方法进行了修改,这个操作可能要花费几分钟的时间,与此同时,
B对相同文件的update方法也 进行了修改,B很快开始并完成他的修改,虽然他在A之后开始,但是却在A之前完成,很不幸,
A读的文件没有包括B的更新,因此当A写入文件时,就会覆盖B更新过的那个版本,B的更新就永远丢失了。
不一致读----------
发生在读取俩份各自正确的数据而他们却在同一时间互相矛盾时,例如:
M希望知道并发包中有多少个类,而该并发包有俩个子包,一个是加锁的,一个是多步提交的,M查了一下加锁包,有7个类,
这是,M接到ROY打来的电话,他们关于一些深奥的问题谈了很长时间,当M接电话的时候,D修改了四步锁代码中那个恼人
的错误,并在加锁包中加了俩个类并来只有5个类的多步提交包里多加了3个类,等到M接完电话再回去查多步提交包里有
多少个类的时候,她看到有8个类,总的加起来就是15个类。
以上这俩个问题都会导致正确性的失败,从而产生错误的行为。
隔离与不变性--------------------
并发问题由来已久,人们提出了各种不同的解决方案,对于企业应用来说,有俩个非常重要的解决方案,一个是隔离,一个是不变性。
并发问题发生在多个执行单元(例如进程或线程)同时访问同一片数据的时候,一个解决的办法就是隔离,划分数据,使得每一个
数据都只能被一个执行单元访问,操作系统为每个进程单独分配一片内存。并且只有这个进程可以对这片内存进行读或写操作。
只有在共享数据可以修改的情况下,并发问题才会发现,所以,一个避免并发冲突的方法是识别哪些是不变的数据。另一个观点是
把那些只读数据的程序分开来,让她们只使用拷贝的数据源,这样就可以放松所有的并发控制。
乐观锁并发控制与悲观锁并发控制-----------------------
当有一些数据无法隔离时,我们可以使用俩种形式的并发控制策略,乐观锁和悲观锁。
假设M和D同时都要编辑customer文件,如果使用乐观锁策略,她们俩个都可能得到一个文件的拷贝,并且可以自由编辑文件,假设D第一个完成
了工作,那么他可以毫无困难的更新他的修改,但是当M要提交他的修改的时候,并发控制策略就会开始作用,源代码控制系统会检测到在M修改
与D的修改之间存在着冲突,因而拒绝M的提交,并由M负责指出怎么样处理这种情况,
如果使用悲观锁,只要有人先取出文件,其他人就不能对该文件进行编辑,因此,假如M先取出文件,那么D就只能在M完成任务并提交之后才能对
该文件进行操作。
如果把乐观锁看做是关于冲突检测的,那么悲观锁就是关于冲突避免的。现实中大部分使用乐观锁。
在乐观锁和悲观锁之间进行选择的标准是:冲突的频率与严重性,如果冲突很少,或者冲突的后果不会很严重,那么通常情况下应该选择乐观锁,
因为它能得到更好的并发性,而且更容易实现,但是,如果冲突的结果对于用户来说很痛苦,那么就需要使用悲观锁策略。
避免不一致读-----------------
悲观锁策略可以通过读加锁和写加锁来处理不一致读,读数据的时候要一个读锁(read lock),写数据的时候,需要一个写锁(write lock)或者叫排他锁,
对于读锁,可以一次多个人对同一份数据加锁,但是只要有人得到了一个读锁,其他人都无法在得到一个写锁,另外一种情况,一旦有人得到一个写锁,
其他人就不能再得到这俩种锁的任何一种,在这类系统中可以使用悲观锁策略来避免不一致读问题。
乐观锁策略通常将冲突检测建立在数据的某种版本标记上,可能是时间戳,也可能是顺序计数器,为了检测到更新丢失,系统核对将要更新数据的版本标记
和共享数据的版本标记,如果俩者一样,系统允许更新数据并更新共享数据的版本标记。
死锁-----------------------
对于悲观锁技术有一个很特别的问题就是死锁,假设M开始编辑customer文件,而D开始编辑order文件,当D意识到如果要完成任务的话也需要编辑customer文件,
但是这时M已经对这个customer文件加锁了,所以D只好等待,然后M也意识到自己必须编辑order文件,同样D也已经对这个order文件加锁,现在他们之间出现了死锁,
除非有一个完成了,否则谁也无法继续,。
有许多不同的技术可以用来处理死锁,一种是使用软件来检测死锁的发生,在这种情况下,需要选择一个牺牲者,放弃他的工作和它所加的锁,一遍其他人可以继续,
另一种类似的方法就是给每一个锁都加上一个时间限制,一旦到达时间限制,所加的锁就会失效,但是会出现一个问题,在实际上没有死锁的情况下,有人会因为
持锁时间过长而成为牺牲者。
事物---------------------
在企业应用中处理并发最主要的工具就是事务,transaction
事务是一个有边界的工作序列,开始和结束都有明确定义,其次,所有相关资源在事务开始和结束时都保持一致,而且,每个事务都必须保证妖魔全部完成,要么什么都不做,
ACID
软件事务中经常使用ACID的属性来描述
原子性(A)在一个事务里,动作序列的每一个步骤都必须是要么全部成功,要么所有的工作都将回滚。
一致性(C)在事务开始和完成的时候,系统的资源都必须处于一致的,没有被破坏的状态。
隔离性(i) 一个事务,直到他被成功提交之后,他的结果对于任何其他的事务才是可见的。
持久性(D)一个已提交事务的任何结果都必须是永远性的,