今天想写一些关于事务并发问题,当初在学习DB2的时候,就一直想弄明白,可是当时是为了应试,老师也没有讲得太明白,所以一直决心要总结一下,后来呢,就一直拖到了今天...闲话少讲了,开始正题吧!
在并发的环境之中,一个数据库系统会同时为各种各样的客户端提供服务,对于同时运行的多个事务,当这些事务访问数据库中相同的数据时如果没有采取必要的隔离机制,就会出现各种并发问题,可以把这些问题归纳为一下五种:
----- 第一类丢失更新:撤销一个事务时,把其他事务已提交的更新数据覆盖。
----- 脏读:一个事务读到了另一个事务未提交的更新数据。
----- 虚读:一个事务读到了另一个事务已经提交的新插入的数据。
----- 不可重复读:一个事务读到另一个事务已提交的更新数据。
----- 第二类丢失更新:一个事务覆盖另一个事务已提交的更新数据,这时不可重复读的一个特例。
这样的定义实在太过死板,而且让人也很难理解,还是通过一个例子来仔细的分析一下每一种并发问题,以下引用孙卫琴老师的《精通Hibernate:JAVA对象持久化技术详解》里面的例子,个人认为这个例子很不错。
假设现在一所银行有一个取款事务和一个支票转账事务操作同一个银行账户的情形,首先我们假设两个事务顺序执行,而不是并发执行,那麽整个的步骤如下:
----- 银行客户在银行前台请求取款100元,出纳员先查询账户信息,得知存款余额为1000元。
----- 出纳员判断存款余额大于取款额,支付给客户100元,并将账户上的存款余额改为900元。
----- 出纳员处理一张转账支票,该支票向此账户汇入100元,出纳员先查询账户信息,得知存款余额为900元。
----- 出纳员将存款余额改为1000元。
可以很清楚的看到,如果顺序的执行这两个事务,不会出现任何问题,可是现实之中并非如此简单,如果两个事务分别由两个出纳员同时执行那麽可能就会出现并发的问题,下面我们分别来介绍:
1.第一类丢失更新
时 间 取款事务 转账事务
-------------------------------------------------------------------------------------------------
T1 开始事务
T2 开始事务
T3 查询账户余额为1000元
T4 查询账户余额为1000元
T5 汇入100元,把余额改为1100元
T6 提交事务
T7 取出100元,把余额改为900元
T8 撤销事务,余额恢复为1000元
--------------------------------------------------------------------------------------------------
如果按照以上的时间次序并发执行的话,由于支票转账事务对存款余额所做的更新被取款事务的撤销所覆盖,所以客户会损失100元。
2.脏 读
时 间 取款事务 转账事务
---------------------------------------------------------------------------------------------------
T1 开始事务
T2 开始事务
T3 查询账户余额为1000元
T4
T5 取出100元,把余额改为900元
T6 查询账户余额为900元(脏读)
T7 撤销事务,余额恢复为1000元
T8 汇入100元,把余额改为1000元
T9 提交事务
--------------------------------------------------------------------------------------------------
由于支票转账事务查询了取款事务未提交的更新数据,并且在这个查询结果的基础上进行了更新操作,如果取款事务最后被撤销 ,会导致银行客户损失100元。
3.虚 读
下面我们另举一个例子来看看什么是虚读。
时 间 注册事务 统计事务
-----------------------------------------------------------------------------------------
T1 开始事务
T2 开始事务
T3 统计注册客户总数为10000人
T4 注册一个新用户
T5 提交事务
T6 统计注册客户总数为10001人
T7 到底哪一个统计数据有效?
-----------------------------------------------------------------------------------------
统计事务无法相信查询的结果,因为查询结果是不确定的,随时可能被其他事务改变。
对于实际应用,在一个事务中不会对相同的数据查询两次,假定统计事务在T3时刻统计注册客户的总数,执行SELECT语句,在T6时刻不再查询数据库,而是直接打印统计结果为10000,这个统计结果与数据库当中数据是有所出入的,确切的说,它反映的是T3时刻的数据状态,而不是当前的数据状态。应该根据实际需要来决定是否允许虚读。以上面的统计事务为例,如果仅仅想大致了解一下注册客户总数,那麽可以允许虚读;如果在一个事务中,会依据查询结果来做出精确的决策,那麽就必须采取必要的事务隔离措施,避免虚读。
4.不可重复读
时 间 取款事务 转账事务
-----------------------------------------------------------------------------------------------------
T1 开始事务
T2 开始事务
T3 查询账户余额为1000元
T4 查询账户余额为1000元
T5 取出100元,把余额改为900元
T6 提交事务
T7 查询账户余额为900元
T8 余额到底是1000元还是900元?
-----------------------------------------------------------------------------------------------------
如上面所示,如果支票转账事务两次查询账户的存款余额,但得到了不同的查询结果,这使得银行出纳员无法相信查询结果,因为查询结果是不确定的,随时可能被其他事务改变。
5.第二类丢失更新
时 间 取款事务 转账事务
----------------------------------------------------------------------------------------------------
T1 开始事务
T2 开始事务
T3 查询账户余额为1000元
T4 查询账户余额为1000元
T5 取出100元,把余额改为900元
T6 提交事务
T7
T8 汇入100元,把余额改为1100元
T9 提交事务
----------------------------------------------------------------------------------------------------
每个事务都不知道其他事务的存在,最后一个事务对记录所做的更新将覆盖由其他事务对记录所做的已提交的更新。上面的例子里由于支票转账事务覆盖了取款事务对存款余额所做的更新,导致银行最后损失了100元,哈哈,你是不是开始喜欢第二类丢失更新了呢?
怎样才能消除这些并发问题呢?请听下回......
分享到:
相关推荐
- 对于多个操作需要一起成功或一起失败的情况,可以使用数据库事务来确保数据一致性。 10. 性能优化: - 通过合理设计数据库结构、索引和查询语句,以及适当使用缓存和批处理,可以提高应用程序的性能。 综上所...
Oracle数据库工作备忘录 Oracle数据库是全球广泛使用的大型企业级关系型数据库管理系统,由甲骨文公司(Oracle Corporation)开发。它以其高效、稳定和强大的功能著称,被广泛应用于金融、电信、政府和各类企业的...
本文将详细讲解如何实现“android 备忘录 数据库存储到本地 定时提醒”的核心知识点。 首先,我们关注的是数据存储。在Android中,本地数据存储通常有多种方式,如Shared Preferences、Internal Storage、External ...
《C#备忘录源码解析与数据库应用》 C#是一种面向对象的编程语言,由微软公司开发,广泛应用于Windows平台的软件开发。在这个“C# 备忘录源码(含数据库)”项目中,我们将深入探讨如何利用C#实现一个功能完备的备忘...
对于增、删、改、查操作,我们需要使用SQLite数据库来存储备忘录数据。SQLite是一个轻量级的关系型数据库,适用于移动设备。在Android中,我们通过SQLiteOpenHelper的子类来创建和升级数据库,然后使用SQL语句来执行...
7. 数据库事务: SQLite支持事务处理,可以确保数据的一致性和完整性。`BEGIN`, `COMMIT` 和 `ROLLBACK` 语句用于控制事务。例如,当执行一系列操作时,可以包裹在事务中,以确保它们要么全部成功,要么全部回滚: ...
这个系统的主要目标是提供一套便捷的工具,让用户能够轻松地管理他们的日常事务,包括创建、编辑、查找和删除备忘录。同时,系统还集成了对Windows系统内建小工具如记事本和计算器的访问,以增强用户体验。 首先,...
在Android平台上开发备忘录小程序是一项常见的任务,它能够帮助用户方便地记录和管理日常事务。这个压缩包提供的工程实现了这样一个功能丰富的备忘录应用,包括侧滑删除、置顶操作以及图文并茂的记录方式。 1. **...
本文将详细介绍一款由C#语言编写的Winform安装程序,它是一个功能完备的备忘录应用,能够帮助用户轻松管理日常事务,设定提醒,确保重要事项不会被遗漏。 C#,全称CSharp,是微软公司推出的一种面向对象的编程语言...
该备忘录程序是一款简洁实用的应用,旨在帮助用户高效记录和管理日常事务。用户可以轻松创建、编辑和删除备忘录,支持设置提醒功能,以确保不会错过重要事项。应用界面直观,操作流畅,用户可以通过标签和分类功能对...
【手机备忘录程序】是一种常见且实用的智能手机应用程序,主要功能是帮助用户记录日常生活、工作中的重要事项或想法,确保不会遗忘待办任务。它通常具有简洁的用户界面和高效的提醒机制,使得用户可以方便地创建、...
6. **SQLite数据库**: 对于支持多个备忘录,开发者可能需要建立一个本地SQLite数据库来存储各个备忘录条目,便于快速检索和编辑。 7. **UI设计与交互**: 设计简洁易用的备忘录小部件界面至关重要。这包括字体、颜色...
【备忘录系统】是一个由个人开发的软件应用,它提供了创建、管理和删除备忘录的基本功能,旨在帮助用户方便地记录和跟踪日常事务。这个系统可能是用VC(Visual C++)作为编程语言,结合SQL(Structured Query ...
例如,在Python中,可以使用`sqlite3.connect('备忘录.db')`来创建或打开名为“备忘录”的数据库文件。 2. 创建表:备忘录应用的核心是一个“备忘录”表,我们需要用SQL语句创建它。表结构可能包括ID(主键)、标题...
《企业备忘录管理系统》是基于Visual C++编程语言和SQL Server数据库技术开发的一款实用工具,旨在提升企业的信息管理效率。这款系统集成了多种功能,为企业的日常事务处理提供了便捷的解决方案。 首先,Visual C++...
【标题】:“一个简单的备忘录” 在移动设备上,备忘录应用程序是日常生活中非常实用的工具,用于记录各种待办事项、想法或者提醒。本项目提供了一个详细的安卓备忘录源码实现,涵盖了核心功能如添加、删除、修改...
【个人备忘录源码】是一个专为个人设计的备忘录应用程序的源代码,它提供了记录、管理和检索日常事务的功能。源码的编写语言可能是Delphi,这是一款基于Object Pascal的集成开发环境,以其高效的编译器和丰富的组件...
在信息技术高度发展的今天,公司备忘录系统已经成为企业管理日常事务、提升工作效率的重要工具。本文将深入探讨如何利用Microsoft的编程语言VC++和数据库管理系统SQL Server,构建一套高效、实用的公司备忘录系统。 ...
在Android应用开发中,备忘录(Memo)通常是指一种帮助用户记录、管理和检索日常事务的应用。本资源包提供了一套完整的Android备忘录应用的源代码,这为开发者提供了学习和参考的宝贵材料。以下将详细介绍备忘录应用...