丢失更新
丢失更新(lost update)是一个经典的数据库问题。实际上,所有多用户计算机环境都存在这个问题。
简单地说,出现下面的情况时(按以下所列的顺序),就会发生丢失更新。
(1)会话session1的一个事务获取(查询)一行数据,放入本地内存,显示给用户User1
(2)会话session2另一个事务也获取这一行,但显示给User2
(3)User1使用应用修改了这个一行并提交。session1的事务已经执行
(4)User2也修改这行并提交。session2的事务也执行。
这个过程称为“丢失更新”,因为第(3)步所做的所有修改都会丢失。
解决这个问题,Oracle有2种解决方案
1)悲观锁定
用户在屏幕上修改值之前,这个锁定方法就要起作用。例如,用户一旦有意对他选择的某个特定的行(屏幕可见)
执行更新,如单击一个按钮,就会放上一个行锁。那这个行锁就会持续到用户修改并提交。
select empno,ename,sal from emp where deptno = 10;
EMPNO ENAME SAL
----- ----- ----
7782 CLARK 2450
7839 KING 5000
7934 MILLER 1300
用户想更新MILLER行。在这个时间点上(即用户还没有在屏幕做任何修改,但这行已经从数据库中读出一段时间了),
应用会绑定用户选择的值,从而查询数据库,并确保数据尚未修改。可以使用一下命令模拟
variable empno number
variable ename varchar2(20)
variable sal number
exec :empno := 7934; :ename := 'MILLER'; :sal := 1300;
下面,除了简单查询值并验证数据尚未修改外,我们用使用FOR UPDATE NOWAIT 锁定这一行。
SELECT EMPNO,ENAME,SAL FROM EMP WHERE EMPNO = :EMPNO AND DECODE(ENAME,:ENAME,1) = 1
AND DECODE(SAL,:SAL,1) = 1 FOR UPDATE NOWAIT.
从而不允许其他会话更新。因此,这种方法称为悲观锁定(pessimistic locking)。
如果底层数据没有改变,就会再次得到MILLER行,而且这一行会被锁定,不允许其他会话更新(但是允许其他会话读)。
如果另一个用户正在更新这一行,我们就会得到一个ORA-00054:resource busy错误。相应地,必须等待更新这一行
的用户执行工作。
在选择数据和指定有意更新之间,如果有人已经修改这一行,我们就会得到0行。这说明,屏幕上的数据是过时的。为了避免
前面所述的丢失更新情况,应用需要重新查询,并在允许在最终用户修改之前锁定数据。
一旦成功地锁定了这一行,应用就会绑定新值,发出命令后执行修改:
UPDATE EMP SET ENAME = :ENAME,SAL = :SAL WHERE EMPNO = :EMPNO;
2)乐观锁定
第二种方法称为乐观锁定,即把所有锁定都延迟到即将执行更新之前才做。换句话说,我们会修改屏幕上的信息而不要锁。
我们很乐观,认为数据不会被其他用户修改。因此,等到最后一刻才知道我们的想法正确与否。
乐观控制的方法有很多种,主要介绍2种方法:
1、使用一个特殊的列,并且这个列由数据库的一个触发器或者应用程序代码来维护,可以告诉我们记录存储现行的版本号。
2、通过原来的数据计算校验和或散列值。
乐观锁定还是悲观锁定
那么哪种方法最好呢?根据我的经验,悲观锁定在Oracle中工作得非常好(但在ita数据库当中可能不是这样),而且与乐观
锁定相比,悲观锁定有很多优点。不过,它需要与数据库有一条有状态的连接,如客户/服务器连接,因为无法跨越连接持有锁。
所以在当前的许多情况下,悲观锁定不太现实。过去的应用可能只有数十个或上百个用户,对于这些应用,悲观锁定是我们的不二
选择。不过对现今大多数应用来说,一般都采用乐观并发控制。
在这些可用的方法中,我使用哪一种呢?推荐使用版本列方法,并增加一个时间戳列。从长远看,这样能为我们提供一个额外
的信息。而且与散列和检验和方法相比,计算的代价不是很昂贵,在处理LONG,LONG RAW,CLOB,BLOB和其他非常大的列时,散列或
检验和方法可能会遇到一些问题,而版本列方法则没有这些问题。
相关推荐
标题中的“day36 10-Hibernate中的事务:解决丢失更新”指的是在使用Hibernate进行数据库操作时,关于事务管理和防止丢失更新的问题。在数据库管理中,事务是确保数据一致性的重要机制,而丢失更新是并发控制中可能...
数据库-丢失更新测试 在数据库管理系统中,丢失更新是一个常见的并发控制问题,它发生在多用户环境中,当两个或更多的事务对同一数据进行修改时,可能导致一个事务的更新被其他事务的更新覆盖,从而丢失了某些更新...
4. **数据分区**:在分布式数据库系统中,如果数据分布在不同的节点,不正确的并行更新策略可能导致部分节点的数据未同步,从而丢失更新。 为了解决这些问题,我们可以采取以下策略: 1. **锁定策略**:通过使用...
如果两个事务同时执行,则其中一个的修改可能会丢失,因为第二个写入的内容并没有包括第一个事务的修改,这种模式发生在各种不同的情况下:增加计数器或更新账户余额(需要
8. **系统还原**:如果之前创建了系统还原点,可以尝试还原到更新前的状态,但同样会丢失更新后的设置和部分数据。 9. **Windows事件查看器**:通过“事件查看器”查看蓝屏时的日志,可以获取更具体的错误信息,有...
* 若一行在读前与更新前的值前后不一致,就说明有其他的事务更新了此列,这样就可以不更新此列,从而防止了丢失更新的情况 3. VB 代码的使用 VB(Visual Basic)是一种通用的基于对象的程序设计语言。它可以用来...
丢失更新是指两个或多个事务选择同一行,然后基于最初选定的值更新该行时,会发生丢失更新问题。每个事务都不知道其他事务的存在。最后的更新将重写由其他事务所做的更新,这将导致数据丢失。 脏读是指第二个事务...
这些协议旨在解决并发操作带来的三种主要数据不一致问题:丢失更新、读过时数据和读“脏”数据。 1. **丢失更新问题**: 这个问题发生在两个事务 T1 和 T2 都读取并修改同一数据。T1 完成修改并提交,但 T2 的修改...
在TIA博途中,有时我们需要更新或修改程序,但在这一过程中,可能会导致数据块(DB)中的参数丢失。为了避免这种问题,TIA博途提供了一个实用的功能——DB快照。DB快照允许用户捕获数据块变量的实际值,并在需要时...
事务并发可能会引发一些问题,如脏读、不可重复读、幻读、第一类丢失更新、第二类丢失更新等。 3.1、脏读 脏读是指一个事务读取了另一个事务未提交的数据。 3.2、不可重复读 不可重复读是指一个事务读取了另一个...
在多用户并发访问数据库的场景下,事务的正确管理变得尤为重要,因为多个事务之间的交互可能会引发一系列问题,如丢失更新、脏读、重复读、第二类丢失更新以及虚读等。 ### 失踪更新(Lost Update) 失踪更新主要...
3. **系统故障**:操作系统崩溃、蓝屏或更新失败可能导致文件丢失。 4. **硬盘物理损坏**:硬盘的磁头损坏、电路板故障或硬盘老化都可能导致数据丢失。 5. **格式化错误**:误操作对硬盘进行格式化,未备份的数据会...
9. **丢失更新和不可重复读**:并发操作可能导致丢失更新(两个事务对同一数据进行修改,后提交的事务覆盖了先提交的事务的更新)、不可重复读(事务在不同时间读取同一数据,结果不一致)和读脏数据(事务读取了...
在多用户数据库系统中,多个事务可能同时对同一数据进行读取和更新,如果没有适当的控制机制,可能会出现丢失更新、脏读和不可重读等现象。 1. **丢失更新**: 丢失更新是指两个事务对同一数据进行修改,其中一个...
丢失更新是指如果两个事务都要更新数据库一个字段 X,x=100 事务 A 和事务 B 都读取 X=100,写入 x=X+100 和写入 x=X+200,最后 x=300,这样事务 A 的更新就被覆盖掉了、丢失了。 不可重复读是指一个事务在自己没有...
Serializable 隔离级别可以避免脏读、不可重复读、虚读和第二类丢失更新等问题,但是它的代价是性能开销较高。 二、Repeatable Read 隔离级别 Repeatable Read 隔离级别是第二高级别的隔离级别,它可以避免脏读和...
* 数据库的并发操作会带来问题:丢失更新问题、脏数据问题、不可重复读问题。 * 解决方法:用封锁机制,包括X锁和S锁。 * X锁:申请X锁操作、释放X锁操作。 * S锁:申请S锁操作、升级和写操作、释放S锁操作。 七、...
丢失更新发生于两个事务同时更新同一数据时,其中一个事务的更新可能会被另一个事务覆盖,导致数据丢失。例如,两个事务分别进行库存增减操作,如果不加以控制,可能导致最终库存计算错误。脏读则是指一个事务读取到...
并发控制的主要目标是在多用户环境下保证数据库的一致性,避免由于并发操作带来的问题,如丢失更新、不可重复读和脏读。 并发控制的常见方式是采用事务的交叉执行,即在单处理器系统中,事务的操作交错进行。这种...
1. 丢失更新:一个事务更新的数据被另一个事务的更新覆盖,导致前者的修改丢失。 2. 脏读:一个事务读取到了另一个事务未提交的临时结果,如果该事务回滚,脏读的数据就无效。 3. 不可重复读:同一个事务在不同时间...