最近遇到一个场景:
1、系统有一个功能是做入库,批量挺大,一次需要入库上万级的数据(页面一个提交完成)。
2、系统使用的B/S结构。
3、系统表数据已经很庞大,估计上千万级数据了。
4、系统架构主要是Action--->Service 结构,也就是Action用于处理页面的跳转,Service层用于具体的业务处理,
Action和service是1对多的关系,其中一个service层方法作为一个事务。
5、系统同时使用一个功能,一组数据的情况比较少。
用户的一种操作是这样的,在页面上提交数据,但是发现一段时间没执行出来,于是重新进入系统重新保存,导致系统几乎同时出现一模一样的两个事务处理,并都执行成功,结果数据重复。
另外一种是多个用户同时操作同一批设备,同时做入库。
我们都知道事务具有,1、一致性,2、原子性,3、隔离性,4、持久性。根据其特点,结合系统的架构我们不难分析出出现问题的原因。A事务在执行,还没提交之前,B事务继续提交,此时两个事务是相互隔离的,并且两个事务的最终提交时间也具有不确定性。
出现以上情况,大概总结了几种解决方案。
1、对于处于同一个会话的两次提交,可以使用token机制来判断是否是同时两次提交。strtus有实现,
protected String generateToken(HttpServletRequest request) 创建一个令牌.
protected boolean isTokenValid(HttpServletRequest request) 检查令牌是否有效
protected boolean isTokenValid(HttpServletRequest request,Boolean reset) 检查令牌是否有效,并且重置令牌(如果reset 是true)
protected void resetToken(HttpServletRequest request) 重置令牌
protected void saveToken(HttpServletRequest request) 添加令牌
基本原理
服务器端在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,
看是否匹配。在处理完该请求后,且在答复发送给客户端之前,将会产生一个新的令牌,该令牌除传给
客户端以外,也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次
提交的话,客户端传过来的令牌就和服务器端的令牌不一致,从而有效地防止了重复提交的发生。
2、对于不同会话之间的重复提交。 这边也有几种解决方案,各有利弊:
(1) 数据分步提交,即执行比如1000个数据后,提交事务。这样根据两个事务具有时间差 来判断数据的重复性是可行的。 但是一旦其中一个提交发生了异常中断,那么已经建档的数据得不到有效回滚操作。导致部分数据会重复提交。目前这边主要的解决办法是判断异常,然后处理数据回滚。
(2)数据不分步提交,数据全部一次提交,两个事务具有时间差 来判断数据的重复性是理论上也是可行的。但是如果数据量太大,事务数据量太大,最终会前台session超时500错误,用户也是等不起这个执行时间的。但是对于小批量的效果很好,也不用考虑并发提交的异常情况。
(3)从数据库的表结构上进行优化,比如表中有唯一键业务字段,那么建立唯一键。但是很多场景其实都不具备这个条件,因为大部分这个情况都是新数据的录入。
3、其他方面做优化,让用户等得住。
对于长时间的处理的时候,如果只是单纯的滚动条,或者按钮灰掉等处理,用户肯定不耐烦,这边也提出几个解决办法供探讨。
(1) 将后台执行数据在前台实时显示,同时屏蔽其他可操作入口。
(2) 前台提供进度条,显示进度百分比,同时屏蔽其他可操作入口
等待完成后恢复可操作入口。
以下是实现实时展示后台执行数据的思路:
将执行某一个元操作后的数据保存到成员变量中,然后前台页面提供一个隐藏页面轮询该变量值,并将改值返回给前台模态窗口。
分享到:
相关推荐
首先,批量提交数据可以显著提高数据插入或更新的效率,因为每次数据库事务处理的数据量更大,减少了网络传输的次数,降低了与数据库的交互成本。在C#中,可以使用ADO.NET的SqlCommand对象配合SqlBulkCopy类实现批量...
### Sqlserver大数据量插入速度慢或丢失数据的解决方法 #### 概述 在处理大量数据插入SQL Server数据库的过程中,可能会遇到插入速度慢或者数据丢失的问题。这种情况通常出现在需要批量插入数千甚至上万条记录的...
在Java开发中,处理大数据量的数据导出是一个常见的挑战,特别是在CSV格式的文件处理上。CSV(Comma Separated Values)是一种广泛使用的数据交换格式,因其简单性和通用性而受到青睐。然而,当数据量达到千万级别时...
在C#编程环境中,处理大数据量的导入任务时,效率是非常关键的一环。"C# Access 大数据量 批量 效率 快速 导入"这个主题聚焦于如何利用C#语言高效地将大量数据批量导入到Access数据库中。Access作为一个小型数据库...
6. **并发处理**:如果数据量非常大,可以考虑多线程并行处理不同的部分,进一步提高效率。但需要注意线程安全问题,防止数据冲突。 7. **资源释放**:在完成读取和写入后,务必正确关闭和释放所有资源,包括文件流...
4. **数据传输**:在连接建立后,客户端和服务器之间可以通过ReadFile和WriteFile函数(或其异步版本)进行数据交换,这些操作的结果会被提交到完成端口,等待线程池中的线程处理。 5. **错误处理和资源释放**:在...
2. **读已提交**(Read Committed):事务只能看到已经提交的更改,避免了脏读,但在并发情况下可能导致不可重复读。 3. **可重复读**(Repeatable Read):在一个事务内,多次读取同一数据时,结果相同,即使其他...
在处理大数据量的会员信息时,使用临时表可以避免对主表的频繁操作,减少锁竞争,提高并发性能。临时表有两种类型:本地临时表(Local Temporary Table)和全局临时表(Global Temporary Table)。本地临时表只对...
7. **日志记录与审计**:数据提交过程的记录有助于追踪和审计,工具应保存每次提交的详细日志,包括时间戳、提交者、数据量和结果状态。 8. **集成能力**:优秀的数据提交工具应能无缝集成到现有的工作流程中,例如...
多版本并发控制允许旧版本的数据在事务结束前保持存在,这样并发事务就可以读取到一致的数据视图,而不会互相阻塞。 4. **并发测试工具与方法**:为了测试SQL Server的并发性能,可以使用各种工具和方法。例如,...
在IT行业中,网络编程是至关重要的领域,尤其是在服务器开发中,高性能、大容量的Socket并发处理能力是衡量系统性能的关键指标。本实例源码“C#高性能大容量SOCKET并发完成端口例子完整实例源码”是针对C#开发者设计...
在编程领域,尤其是在开发多用户在线应用时,处理多用户更新数据并发问题是一个至关重要的环节。这涉及到数据库的事务管理、锁机制、并发控制策略等多个方面。本实例以C++.NET为开发环境,通过源代码的方式,展示了...
在处理大数据量时,优化代码至关重要,尤其是对于涉及大量数据读取、验证和存储的任务。在这个案例中,原始场景是客户端上传一个包含手机号码的文本文件,服务端接收并进行有效性验证,然后将数据存入数据库。问题...
Delphi的异步I/O模型也允许开发者以类似的方式处理并发Socket通信,通过`PostQueuedCompletionStatus`和`GetQueuedCompletionStatus`函数来实现I/O操作的提交和接收。 此实例源码中的C#客户端可能包括以下组件:...
C#中的`ThreadPool`类提供线程池服务,通过`QueueUserWorkItem`方法提交任务到线程池,适合执行大量短生命周期的任务。 七、异常处理与死锁防范 在并发环境中,异常处理和死锁预防尤为重要。C#提供了try-catch-...
3. **上传下载**:基于IOCP的上传和下载功能实现,可以通过异步I/O处理大量并发的读写请求,确保数据传输的高效性和稳定性。 4. **SQL查询**:结合数据库操作,IOCP可用于处理大量并发的SQL查询请求,提高数据库访问...
【标题】"无限提交数据-软件版"涉及的是一个软件工具,它允许用户无限制地提交数据,这在某些情况下可能被滥用进行恶意活动。这个软件的特性在于其连续不断地发送数据的能力,尤其是在网络留言板块,可以实现无限制...