`
qtlkw
  • 浏览: 307164 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

利用悲观锁解决数据库死锁

    博客分类:
  • JAVA
 
阅读更多
Reference: http://hi.baidu.com/chenlinping/item/6613c0e9b8fa1ce3fa42ba43

【IT168技术文档】

  这边讲述的数据库死锁是由于查询条件顺序不对而造成的一类,主要是两个线程在同时对一个数据库表进行操作时,出现了下列情况,假设一个数据库表 内有5行数据,线程1需要对1-4行数据进行update操作,而线程2需要对2-5行数据进行update操作,但是由于操作的顺序调整的不正确,线程 1是对数据行1,2,3,4这样的顺序操作,并且加入batch的,而线程2是对数据行5,4,3,2这样的顺序操作的,并且加入batch,于是锁就这 样产生了:当线程1的executeBatch进行批量update时,锁住了123行数据,开始操第4行数据时,此时线程二的executeBatch 正当操作完第4行数据,准备操作第3行数据,而此时线程2则拿着4,5行数据的锁,并且不会释放。于是线程1发现第4行数据的锁已经被占用,便开始等待这 个锁的释放,对于batch操作来说,在没有完成整个事务时,线程1不会释放对1,2,3行数据的锁的拥有权,同样2号线程也在等待1线程释放3号数据的 锁,同样等待,这个相互等待的过程将不会结束,直到数据库有额外的机制来回滚一个操作。当然,这就意味着这两个操作里面有一个就失败了。当然,最好的解决 办法就是调整操作顺序使其(操作顺序)一致,但是当这个里面有错总复杂的问题的时候,比如有时多个线程之间对同一个表操作,或者多个线程操作多个表时,理 起来就会变得麻烦。这边还有一个方案,对于oracle或者sql server这类支持主观加载悲观锁的数据库,可以利用这个特性来手动实现数据库批量操作的事务锁。针对oracle,可以用select ... for update来加载悲观锁,比如需要对于某个字段进行update,则可以用select语句在末尾加上for update把这个字段锁住,然后进行batch的操作。这边需要注意的是:

  1.对于开始使用select ... for update前,必须将autoCommit设置成false;

  2.完成一个update后,必须commit这个事务以便释放这批锁。

  3.操作时要保证数据库表没有其他死锁,否则也会引起一些问题(sqlplus操作需要commit掉)用这个方法,对于锁的控制主权更多,一 旦出问题时,调试更加简便,缺点是效率还是一个大问题,毕竟对于大规模数据来说,还是调整执行顺序是首选,我这个只能算是个旁门左道,嘿嘿。

ExecutorService executor = Executors.newFixedThreadPool(pool_size);
			for (StringBuilder requestParameter : fetcherParams) {
				StringBuilder sb = new StringBuilder(requestParameter.toString());
				String lastCharacter = sb.substring(sb.length()-1, sb.length());
				if("&".equals(lastCharacter)){
					sb.delete(sb.length()-1, sb.length());
				}
				fetcher.setRequestParameter(sb.toString());
				OSA_Worker worker = new OSA_Worker();
				worker.setAppCode(appCode);
				worker.setJobCode(jobCode);
				worker.setJobId(jobId);
				worker.setUserId(userId);
				worker.setColumnCount(columnCount);
				worker.setDataIndex(dataIndex);

				worker.setFetcher((OSADataFetcher) fetcher.clone());
				worker.setInsertSQL(insertSQL);

				executor.execute(worker);
			}
			
			executor.shutdown();

			while (!executor.isTerminated()) {
				Thread.sleep(1000);
			}


private static final Object objLock = new Object();
...
appConn.setAutoCommit(false);
cs = appConn.prepareCall("{" + insertSQL + "}");
...

synchronized(objLock){
				cs.executeBatch();
				cs.clearBatch();
				appConn.commit();
			}
分享到:
评论

相关推荐

    数据库死锁案例

    5. **并发控制**:利用悲观锁和乐观锁等并发控制技术,减少资源的竞争。 总之,理解和掌握数据库死锁的原理及其预防方法对于确保数据库系统的稳定运行至关重要。通过合理的设计和有效的管理,可以最大限度地减少...

    oracle解决死锁![参考].pdf

    4. 序列化访问:对于易产生竞争的资源,可以考虑使用序列化访问或悲观锁策略。 5. 死锁检测:启用Oracle的死锁检测功能,以便系统自动检测并解决死锁。 总之,解决Oracle数据库的死锁问题需要综合运用多种技术和...

    在分布式事务中实现基于Oracle PLSQL UL LOCK的悲观离线锁

    虽然悲观锁能有效防止数据冲突,但它可能导致高并发环境下的性能问题和死锁。死锁是两个或更多事务因互相等待对方释放资源而无法继续执行的情况。在Oracle中,可以通过设置事务隔离级别和使用死锁检测机制来避免...

    CS平台数据库多操作模式

    常见的并发控制技术有锁定机制(如共享锁、排他锁)、乐观锁和悲观锁、多版本并发控制(MVCC)等。 2. **事务**:事务是数据库操作的基本单位,它确保一组数据库操作要么全部成功,要么全部失败,从而维护了数据库...

    hibernate锁实验,以及解决方案

    - 使用悲观锁时注意避免死锁,使用乐观锁时注意版本冲突处理。 通过以上知识点,我们可以更好地理解和解决在使用Hibernate时可能出现的锁相关问题,确保应用程序的稳定性和数据一致性。在实际开发中,应根据具体...

    数据库之事务调优

    悲观锁则在操作前就获取锁,防止其他事务修改数据。根据业务场景选择合适的并发控制策略。 7. **事务回滚日志管理**:事务回滚日志(Redo/Undo Logs)用于在事务失败时恢复数据。优化日志管理,如合理设置日志文件...

    云数据库使用十大经典案例

    教程可能讲解了乐观锁、悲观锁、行级锁、页级锁和表级锁的应用场景,以及死锁的预防和解决策略。 4. **CPU管理**:CPU资源是数据库性能的重要因素。内容可能包含如何监控和分析CPU利用率,调整SQL查询以降低CPU负载...

    天津大学数据库原理上机实验.zip

    此外,可能会探讨乐观锁和悲观锁的区别,以及多版本并发控制(MVCC)的概念。 通过这四个实验,学生不仅能够巩固理论知识,还能掌握数据库的实际应用技能,为未来在数据库管理系统开发、数据分析、数据库管理等领域...

    直击面试~分布式锁解决并发安全问题

    理解如何选择合适的分布式锁实现、何时使用乐观锁或悲观锁,以及如何处理锁的公平性、可重入性、超时和解锁等问题,都是面试官可能关注的焦点。 总结来说,分布式锁是解决并发安全问题的有效手段,通过使用如...

    数据库系统概论课件

    例如,乐观锁和悲观锁是两种基本的并发控制方法,前者在写入时检查冲突,后者在读取时就锁定资源。 2. **数据恢复**: 数据恢复是数据库系统的一个重要特性,它确保即使在系统故障或硬件崩溃后,数据也能被准确...

    [数据库] Navicat for MySQL换种思维解决插入同时更新数据1

    乐观锁通过版本号或其他方式检查冲突,悲观锁则在操作前获取锁定,确保独占资源。 5. **设计模式调整**:在数据库设计阶段,考虑使用更合适的数据模型或者冗余数据来减少这种同时插入和更新的需求。 举一个具体的...

    数据库系统工程师模拟试题

    这需要了解事务的概念、ACID属性、锁机制(如行级锁、表级锁、读写锁)以及乐观锁和悲观锁的区别。 6. **事务处理**:事务是数据库操作的基本单位,你需要理解事务的开始、提交、回滚以及事务隔离级别(读未提交、...

    分布式锁的三种实现方式.zip

    数据库锁是一种常见的分布式锁实现方式,通常使用乐观锁或悲观锁机制。在SpringBoot中,可以通过JDBC或MyBatis等持久层框架来操作数据库实现锁。乐观锁通过版本号或时间戳检查来防止并发冲突,而悲观锁则是在读取...

    数据库管理系统原理与设计(第3版)

    - **锁机制**:包括悲观锁和乐观锁。 - **死锁处理**:如何检测和解决死锁问题。 2. **安全性**: - **用户认证**:确保只有合法用户才能访问数据库。 - **权限管理**:设置不同的访问级别。 - **审计日志**:...

    数据库的代码

    3. **并发控制**:乐观锁和悲观锁是两种常见的并发控制策略。乐观锁假设冲突很少,只有在提交时才检查是否发生冲突;悲观锁则在操作开始时就获取锁,防止其他线程修改数据。 4. **线程同步**:Java中的`...

    ORACLE深入浅出-中级篇.pptx

    Oracle提供`FOR UPDATE NOWAIT`来实现悲观锁,而乐观锁可以通过增加版本号字段或利用ORA_ROWSCN机制实现。 最后,阻塞和死锁是并发环境下可能出现的问题。当两个或多个事务互相等待对方释放资源时,就会发生死锁。...

    数据库管理系统原理与设计++(第3版)

    - **锁机制**:是解决并发问题的主要手段,分为悲观锁和乐观锁两种策略。 - **多版本并发控制(MVCC)**:通过保留数据的历史版本来实现并发控制,避免了锁机制带来的性能问题。 ### 恢复技术 - **故障类型**:包括...

    数据库优化

    例如,减少事务的粒度,使用乐观锁或悲观锁,以及适当的死锁检测和处理机制。 九、数据库设计 良好的数据库设计是优化的基础。通过合理设计数据模型,减少数据冗余,降低数据一致性冲突,可以使数据库运行更加高效...

    分布式锁三种实现方式及对比

    - **悲观锁**:使用`SELECT ... WHERE ... FOR UPDATE`语句实现,可以实现行级锁定,确保同一时刻只有一个事务能修改特定数据。但需要注意,`WHERE`条件中的字段必须有索引,否则可能导致全表锁,影响性能。 - *...

Global site tag (gtag.js) - Google Analytics