oracle锁bug

一、问题描述
两任务并发访问同一数据库表中的记录,出现死锁,如下是其中一个任务的代码:
Connection dbConn = DAMContext.getConnection();   String userAccountSql = createAccountSql(exportDate);   List accountList = new ArrayList();   try {       PreparedStatement pstm = dbConn.prepareStatement(userAccountSql,           ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);       ResultSet result = pstm.executeQuery();       while (result.next()) {           UserAccount account = new UserAccount();           //omited           accountList.add(account);       }          String updateSql = createExpireSql(exportDate);       PreparedStatement updatePs = dbConn.prepareStatement(updateSql,              ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); 
    //ResultSet.CONCUR_READ_ONLY 表示sql语句不会做更新处理,       //这就意味者在操作这批记录时,不会首先获取这批记录的"页锁",别人仍旧可以同时对这批数据进行并发的update操作。          ResultSet updateResult = updatePs.executeQuery();       //执行update操作       //在dbConn.prepareStatement()中指定的是不做update处理,而实际上却执行了update操作       //导致更新这批记录时:更新到某条记录时,才获取这条记录的"独占行锁"。       //这就留下了发生死锁的隐患:在执行过程中,一部分已更新的记录集(A)获取了锁;另一部分还没有更新的记录集(B)没有获取锁       //如果此时,有另一线程已经update了记录集(B)中的记录,并且未释放锁;同时又等待记录集(A)中记录的锁来进行update操作,这样死锁就发生了。   }   catch (Exception e) {       e.printStackTrace();       try {           dbConn.rollback();       }       catch (SQLException _ex) {           _ex.printStackTrace();       }   }   finally {       try {           dbConn.setAutoCommit(true);       }       catch (SQLException _ex) {           _ex.printStackTrace();       }       finally {           DAMContext.freeConnection(dbConn);       }   }  

二、解决方案一
确保两个线程访问同一个数据库表的记录的顺序都是一致的。
因为:假设线程(一)目前处理的状况是已更新的为数据集A,剩下未更新的为数据集B;由于两线程访问数据库表的顺序是一致的,故必须是先访问数据集A中的记录,然后再访问数据集B中的记录,因此线程(二)肯定是先访问数据集A中的记录,而此时必须等待,直至线程(一)commit或rollback释放全部的“行锁”。

三、解决方案二
PreparedStatement updatePs = dbConn.prepareStatement(updateSql,          ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);  
修改为:
PreparedStatement updatePs = dbConn.prepareStatement(updateSql,          ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);  

ResultSet.CONCUR_UPDATABLE 表示sql语句是要做更新操作,那么在更新这批记录集前,就会先拿到"页锁";如果这批记录集的部分记录的“行锁”未释放,则等待这批记录的“行锁”全部释放,获取“页锁”。在“页锁”释放掉之前,别人不可能拿到这批记录集中的任何一条记录的“行锁”,也就不可能发生死锁。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在本地自己的操作系统上,完全模拟生产环境,让学员跟着视频一步一步搭建一套在RHEL7操作系统上面的oracle19c的rac环境。同时学员还会学会DNS服务器,DNS客户端,NTP服务器,NTP客户端等操作系统知识。让学员在短时间内,oracle和操作系统知识,有一定的提升。让学员可以独自轻松安装一套oracle rac环境。一课程主题 模拟生产环境,用多路径共享存储,用虚拟软件安装一套RHEL7.5+oracle19c+rac+打补丁二课程特色 完成模拟生产环境,用openfiler软件模拟生产惠普的3par存储,用2个虚拟网卡模拟数据库服务器的2个HBA卡。课程以实践为主,从头到尾一步一步教学员怎样操作,实践性强模拟生产需求,完全可以把这套环境拿到生产环境安装三课程内容 1.课程结束成果演示    1.1 用workstation,安装一套rhel7+oracle19c+rac+multipath+共享存储+DNS服务器+DNS客户端+NTP服务器+NTP客户端的生产环境    1.2 怎样打oracle19c的rac补丁(包括GI补丁,oracle补丁,数据库补丁,OJVM补丁,bug补丁)2.安装openfiler软件,模拟共享存储+配置多路径访问    2.1安装openfiler软件   2.2配置openfiler软件(配置2个虚拟网卡,模拟服务器的2个HBA卡)   2.3创建ocr磁盘   2.4创建mgmt磁盘   2.5创建数据文件磁盘   2.6创建归档日志磁盘3.安装2台数据库服务器    3.1安装2台数据库服务器RHEL7.5   3.2配置服务器双网卡绑定+配置服务器心跳线4.安装多路径软件识别共享存储中的磁盘     4.1安装服务器本地yum源    4.2安装iscsi软件,配置多路径配置文件,识别共享存储中的磁盘    4.3识别ocr磁盘    4.4识别mgmt磁盘    4.5识别数据文件磁盘    4.6识别归档日志磁盘5.oracle19c的rac环境系统参数官方说明     5.1如何配置oracle19c的rac的系统参数(我们参考官方说明)    5.2oracle19c+rac环境Best Practices 官方说明文档6.安装oracle19c+rac之前的准备工作     6.1修改/etc/hosts文件    6.2配置DNS服务器+DNS客户端+NTP服务器+NTP客户端    6.3创建用户和组    6.4创建目录    6.5修改用户环境变量    6.6安装相关软件包    6.7配置ssh互信    6.9禁用服务器透明大页7.安装oracle+19c+rac软件    7.1安装GI软件   7.2创建ASM磁盘,主要是数据文件磁盘和归档日志磁盘   7.3安装数据库软件   7.4创建数据库实例   7.5日常常用维护集群命令(启停数据库,启停集群,查看监听,教同学们怎样不死记命令,而且命令还正确)8.打补丁   8.1打GI和ORACLE的操作系统补丁  8.2打OJVM补丁  8.3打ORA600的bug补丁9.课程总结和成果演示  9.1课程总结和成果演示 四学习必要工具 安装workstation软件  官网下载openfiler,rhel7.5软件下载oracle软件(包括19.3的rac安装包,19.4的补丁)以上软件我都已经在视频里面做了下载地址说明五课程纠错1)rac的私有ip应该是不同的网段,我在视频中设置错误。Ensure all private Ethernet interfaces are set to different subnets on each node. If different subnets are not used and connectivity is lost, this can cause a node reboot within the cluster2)配置好multipath,以及多路径的别名后,还要增加如下配置文件。[root@hellorac1 rules.d]# cat /etc/udev/rules.d/99-persistent.rulesENV==data, OWNER:=grid, GROUP:=asmadmin, MODE:=660上面的配置文件增加成功后,运行如下命令:#udevadm control --reload-rules#/sbin/udevadm trigger --type=devices --action=change执行完成之后,会发现/dev/dm*相应的磁盘权限变成grid.asmadmin. 视频中只运行了udevadm control --reload-rules。3)安装GI部分1和部分2,先看部分2,再看部分1.特此纠正上面的3个错误。谢谢大家的支持和厚爱。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值