多用户同时处理同一条数据解决办法_后台 不同的用户抢占同一数据怎么处理-程序员宅基地

技术标签: informix  delphi  exception  insert  服务器  数据库  

事务处理(多用户同时操作一条信息时是用-并发)

在c/s或多层中,如果两个用户同时打开一条记录,修改后提交会产生更新冲突;
据说办法有二:1。打开同时锁定表的记录 2。浦获错误,撤消其中一个用户的修改,但是很少见到具体实现的代码;请大家告诉具体的代码怎么写:
1。打开时如何锁定一条记录?
2。如何扑获更新错误?在delphi中调试时会报“该记录读出后已经被再次修改”,而在运行时如何判定错误为更新冲突?因为更新时其他的错误如输入不合法等也可能报错,如何把更新冲突和其他的分开?

=====================================================================

http://hi.baidu.com/nboy/blog/item/8d61c93d8ab3dec19f3d6288.html

首先,这个问题只有在特殊情况下才算是问题,大多数情况下可以不作考虑。

然后,这是问题很难描述清楚,解决方案有多种,下面提供一种较方便易用的方式

场景(问题)描述如下:

0,用户A、B同时打开一个页面,页面显示,客户表T_CUSTOMER字段(C_NAME、C_AGE)

姓名:张三,年龄:25

1,A 将姓名“张三”改为“张三1”,然后保存

2,B 将年龄“25”改为“30”,然后保存

这样A的操作就被覆盖了,姓名又变回“张三”了,大家一般怎么处处这种情况?

这里给出一个较易用的解决方案

给表添加一字段:LAST_UPDATE,即最后更新时间

回放场景

0,用户A、B同时打开一页面,面页显示:

姓名:张三,年龄:25,LAST_UPDATE:2008-10-17 13:45:00

1,A 将姓名“张三”改为“张三1”,然后保存

重点在这里:更新数据时WHERE条件里多一条件:AND LAST_UPDATE = '2008-10-17 13:45:00'

更新成功,此时触发器会将当前时间“2008-10-17 13:46:00”赋值给LAST_UPDATE

2,B 将将年龄“25”改为“30”,然后保存

B更新数据时WHERE条件里也有这个条件:AND LAST_UPDATE = '2008-10-17 13:45:00',但此时LAST_UPDATE的值已经在A修改记录时变成2008-10-17 13:46:00

下面要做的就是给出提示了:喔哟,此信息在你发呆这段时间已被人改过啦,所以你需要返工。

触发器代码如下:
===================================================
CREATE OR REPLACE TRIGGER T_CUSTOMER
BEFORE UPDATE ON T_CUSTOMER
FOR EACH ROW
/*
记录最后修改时间
*/
BEGIN
:NEW.LAST_UPDATE := SYSDATE;
END;
===================================================

如果触发器不熟悉或者只是不喜欢用触发器,完全可以修改记录时同时给LAST_UPDATE字段赋值,以此替代触发器的作用。

----------------------------------------------------------------------------------------------------------------

http://blog.csdn.net/onemetre/archive/2010/11/06/5991658.aspx

【并发操作】多用户并发操作的解决方案

【问题】在以前的系统开发中,经常遇到一个同样问题,就是多个用户同时并发操作一条记录,这次在交易系统开发过程中,又出现了这样问题。比如交易商A提交单子,由审核人员B审核,此时A正在修改单位,B也正在查看这条记录,A先修改保存后B再审核保存,导致B审核通过的记录不是他所看到的。

【分析】仔细考虑问题,大概分析了三个方法, 并确定了一个可行的方案,可能还有不完善的地方,但解决现有问题还是绰绰有余的。

最先想的是在交易业务代码中用lock对修改方法加锁,运行时注入单例,并且对方法加同步锁,保证了业务数据的正确性, 但是效率低下,用户在使用中不方便,背离了系统可以并发操作的原则。

然后考虑使用悲观锁,这次运行时注入原型,并发操作效率提高, 但是,在同步处理数据库表时又造成锁表,这样并发效率依旧很低。

最后考虑乐观锁, 只是一种数据版本校验机制,它不做数据库层次上的锁定,需要在要并发操作的主表中加入一个"VERSION"字段或者“LASTUPDATETIME”,如果研究过oracle的SCN应该有异曲同工之妙,它的原理是这样:运行时注入原型,这时数据表并不锁住,只是每次update或insert时将VERSION更新, 当下次update,insert时,会校验VERSION,如果不一致,此时提示信息已经修改过了,并且在事务控制下rollback,这样,保证了数据的正确性,并且也不影响并发操作的效率。但是出现的问题是:如果A读了数据,未来及更新,B先更新了数据, 那么他将提交不上数据,因为VERSION已经失效,这样就造成了A重新读取数据,重新填写单据信息。 这也是乐观锁一个缺点,可以在更新前临时保存A填写的数据,再在跳转页中加载这些数据,保证了交易商不用麻烦再次输入这些数据,更新成功则清空这些临时数据

【结果】

乐观锁在并发操作问题上,保证了业务效率和数据的正确性,基本可以采用这种方案解决交易中并发问题。

●悲观锁:指在应用程序中显式地为数据资源加锁。悲观锁假定当前事务操

纵数据资源时,肯定还会有其他事务同时访问该数据资源,为了避免当前

事务的操作受到干扰,先锁定资源。尽管悲观锁能够防止丢失更新和不可

重复读这类并发问题,但是它会影响并发性能,因此应该很谨慎地使用悲

观锁。

●乐观锁:乐观锁假定当前事务操纵数据资源时,不会有其他事务同时访问

该数据资源,因此完全依靠数据库的隔离级别来自动管理锁的工作。应用

程序采用版本控制手段来避免可能出现的并发问题。

----------------------------------------------------------------------------

http://blog.163.com/lqc-rabbit/blog/static/7594799320081131113720281/

.Net中的事务处理(多用户同时操作一条信息时是用-并发) [Web Applicaion in C#]
SqlConnection myConnection = new SqlConnection("Data Source=localhost;Initial Catalog=Northwind;Integrated Security=SSPI;");
myConnection.Open();

SqlTransaction myTrans = myConnection.BeginTransaction(); //使用New新生成一个事务
SqlCommand myCommand = new SqlCommand();
myCommand.Transaction = myTrans;

try
{
myCommand.CommandText = "Update Address set location='23 rain street' where userid='0001'";
myCommand.ExecuteNonQuery();
myTrans.Commit();
Console.WriteLine("Record is udated.");
}
catch(Exception e)
{
myTrans.Rollback();
Console.WriteLine(e.ToString());
Console.WriteLine("Sorry, Record can not be updated.");
}
finally
{
myConnection.Close();
}

需要注意的是,如果使用OleDb类而不是Sqlclient类来定义SQL命令和连接,我们就必须使用OleTransation来定义事务。


数据库系统程序员需要比一般应用软件程序员懂得更多。一般程序员对事务处理的理解不够全面。事务处理的关键是在提交事务或者取消事务时,万一系统崩溃了,数据库在再次启动时,仍然需要保持数据可逻辑一致性。

最简单的事务处理过程如下:

1. 开始一个事务。进入“事务待命”状态。
2. 在“事务待命”状态,记录事务中改变的数据库记录。此改变不能直接改变数据库中的值,必须先用一个顺序的“事务日志”记录在一边。同时,对于要改变的原始记录加锁,让其它用户无法读和写。(考虑银行取款问题,可以发现如果此时两个用户都在对同一帐号取数,然后减去一定金额,在先后写回数据库,银行就亏钱了)。如果记录已经被其它事务加锁,则报错;同一事务中却可以重复加锁。
3. 在“事务待命”,如果用户给出commit transaction命令,则进入“事务拷贝”状态,拷贝所有加锁的记录成备份。
4. 上面3执行完,则进入“事务更新”状态,用“事务日志”中记录一一更新实际的数据库记录。
5. 上面4执行完,则进入“事务结束”状态,释放所有的记录锁,然后抛弃“事务日志”和备份的原数据库记录。
6. 上面5做完后,事务被删除。

但是,最为关键的是,事务系统必须执行以下过程:一但数据库由于软件、硬件问题发生故障,重启动后,一旦有事务没正常删除,则:

7. 如果在“事务待命”、“事务结束”状态,则重新从5中结束事务的动作开始执行。
8. 如果在“事务更新”状态,则重新从4开始更新记录,并继续想下执行。结果,虽然系统崩溃过,但事务仍然能正常提交。

Informix、Oracle、DB2等数据库的实际事务处理流程更复杂,目的是具有更好的抵抗系统错误性质,因为事务保护是业务系统安全稳定的最后一道防线(比用2个CPU、热备份等更重要。因为那些方法对已经混乱错误的数据照样保护,结果经常造成更多问题)。由于事务处理的流程比一般程序想像得复杂,因此可能会感到用起来比较繁琐。但是了解事务在保护数据库方面的良苦用心,就可以更好地设计出更灵活的业务流程。

如果“一个完整的事务可能包括a,b,c,d四个小事务”就比较奇怪。既然是个过程构成一个事务,没必要中间在划分为4个小事务,问为中间任何操作出错都需要整个“回滚”到a之前。在执行完a后用一个if语句判断要不要再执行“b,c,d”就行,end if之后提交事务。

应用中包含的事务应当尽量让它“瞬间”完成,避免在比较忙时造成用户进程的互锁。事务比较频繁的系统,一秒钟有几个用户互锁就可能造成严重问题,因为事务是以一个稳定的频率来的,而服务器上互锁的进程越积越多,几个小时后,可能有上百台机器都死掉了,只能一台一台地重新开机,花费很多时间、金钱,还会被用户骂死!

但是并不是说事务之间就不能有用户交互。可以在用户3分钟还没确认后,就自动报告错误,并且取消事务。不过我从不冒这个险,而是使用下面方法。

将事务拆分成两段,需要非常深入地研究用户业务流程,研究用户在发现业务数据不一致时是如何纠正的,并且继承用户手工操作流程。这样,软件分析的工作量相应加大了。有时,这是必然的,应当说服用户接受这种现象,并且与开发者一起逐步解决。

比如,卖彩票的交易,用户输入彩票号码,此时在POS机打印彩票并且记账。这并不需要在卖彩票时与后台服务器实时联网,只要每隔10分钟上传一次数据就行了。只有这样,才能在现有的硬件和网络条件下使得彩票销售开展起来。如果开发者固守者彩票号码录入、服务器记账、前台打印合并为一个事务的天真想法,其产品一定会在激烈的市场中败阵。

当然,随着硬件、软件、网络的不断变化,如何灵活应用事务的方法会不断变化,没有一定的规矩,关键要看软件的效果。虽然大的事务可能不断拆分成小的事务,中间用业务流程联系起来;同时,合并一些小的事务或者由计算机自动处理业务数据不一致问题,从而给用户提供网络上的“傻瓜相机”一样的易用、稳定的产品仍然是今天最有挑战意义的软件工程目标。 --------------------------------------------------------------------------------------

这个问题不是C#处理的,而是你调用的存储过程或批查询需要处理的,如果你用C#执行一系列的更新语句的话,你可以使用ADO .NET SqlClient的事务来控制并发时的数据完整性!

SqlConnection conn=new SqlConnection(connectionstr);

SqlTransaction mytran=conn.BeginTransaction();

SqlCommand cmd=new SqlCommand();

cmd.Connection=conn;

cmd.Transaction=mytran;

cmd.CommandText=.....;

int rc=cmd.ExecuteNoQuery();

mytran.Commit();

....

你可以通过错误处理机制来控制事务提交还是会滚...

-------------------------------------------------------------------------------------------- 我在程序中使用一种原始的方法处理需要锁定的内容。
比如我的表中存储有订单的行项目,每次只允许一个用户对行项目进行编辑。
建立“锁定表”,每当用户编辑订单时,在"锁定表"中加入订单号。当加入失败时则说明已有用户在编辑订单,当用户退出订单或锁定时间超过一个阈值时则删除锁定记录,允许其他用户编辑并锁定订单。
这样处理适合锁定多行的订单类数据,锁定表中可以保存其他附加信息。
还有一种方法在数据库中使用事务。使用事务更新数据库,这样可以保证同一时间只有一个用户可以对行更新。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/baimin7657/article/details/8062939

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf

推荐文章

热门文章

相关标签