在做应用看来发设计以及相关过程的时候,数据库是必不可少的,要想让数据库当中的数据达到应用的要求,必须对它进行控制,主要包括:并发控制、性能优化、数据库完整性约束、安全性控制、数据库备份以及恢复。
主要针对的事务的并发,事务是数据库当中进行操作的基本单位,它定义的是操作的序列,这里面包含了多个动作。根据这个特性,事务本身就具有要么都做,要么都不做的特性。
从数据库环境来看的话,事务是不可分割的逻辑工作单位,一般一个程序是可以包含多个事务的。从数据的角度来看事务就可以理解为一个基本单位了。
事务具有ACID特性,原子性,一致性,隔离性,持续性。
原子性(Atomicity)与操作系统当中原语的概念有些相似:指事务包含的所有操作要么全部成功(成功会以commit的方式提交),要么全部失败回滚(回滚会用rollback表示。回滚数据,回滚状态,回滚加锁解锁)。这些操作是一个整体,不能部分的完成。
一致性(Consistency):指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态(中间过程可能是不一致的)。
隔离性(Isolation):指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的。
持久性(Durability,永久性):指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,无论发生何种故障,都不应对其有任何影响。
数据库的并发过程就是多个事务同时执行的情况,这种同时操作就可能产生并发问题:丢失更新,不可重复读问题,“脏”数据的读出。
第一个事务T1对数据A进行修改写回,而第二个事务T2也对A进行修改写回,他们二者并没有成功提交的情况下,会发现T2更新的数据会对T1数据写回的内容进行覆盖,覆盖之后,就不能够知道T1写的是什么了,也就是T1更新的数据丢失不见了,这个就叫做丢失更新,也叫做丢失修改。
涉及的问题主要体现在二者都有不同的写回,这个写回的过程当中会被覆盖掉。
第一个事务T1读取数据A和B进行修改,验证无误写回,而第二个事务T2对A进行修改写回,他们二者并没有成功提交的情况下,会发现T2更新的数据会对T1数据写回的内容进行覆盖,覆盖之后,就不能够知道T1写的是什么了,也就是T1更新的数据丢失不见了,此时在T1第③步验证A+B=100,两次读的数据不一样,从而产生了T1第二次不能重复读到A+B=70的问题,这个就是不可重复读(即一个事务两次读取,值不同,叫不可重复读)。
读脏数据,对于脏数据的定义是:经常的脏东西,也就是垃圾,不要的东西,脏数据就是不要的数据。什么样的数据是不要的?
这里会涉及到回滚操作,某一个事务T1对数据进行了修改,而修改的数据被另一个事务T2读走了,这个过程当中看起来没问题,但是如果T1进行了回滚,而T2拿到了这个被应当被回滚的垃圾数据(脏数据)70,这个过程就是读取脏数据。
并发产生的问题如何解决?主要涉及的就是添加封锁协议。
封锁协议主要涉及的:
一般提到的封锁过程当中,会涉及到三级封锁协议,一到三层层递进,可以解决越来越复杂的问题。
最后的两段锁协议是在加锁解锁的过程当中,将相应的动作简单的划分的时段,这个时段划分之后,会把加锁的过程当中集中在上面一段,而解锁的行为集中在下面一段,从而形成了两个部分,就叫做两段锁。
目前主要涉及的内容主要是一到三封锁协议的具体过程。
加锁就可能出现死锁的情况,针对死锁而言,可以提前预防,也可以人工手动接解除,目前软考不涉及这方面死锁的考察内容。
一级封锁协议为什么不能解决读脏数据?
因为没有读锁,所以其他事务来读数据的时候,没有任何限制。
二级封锁协议为什么不能解决读脏数据?
因为读完即可释放读锁,并没有等待事务执行完成,避免不了其他事务读取脏数据的。