一:首先看异常信息:
============异常信息开始=================================================================================================================
Hibernate: delete from GZK_NR where MLID=?
Hibernate: delete from GZK_LB where LBID=?
Hibernate: delete from GZK_LB where LBID=?
Hibernate: delete from GZK_LB where LBID=?
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.cee.common.AbstractMultiActionFormController.processFormSubmission(AbstractMultiActionFormController.java:121)
at com.cee.common.NbwController.handleRequestInternal(NbwController.java:84)
at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:619)
Caused by: org.hibernate.exception.LockAcquisitionException: could not execute update query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:87)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.hql.ast.exec.BasicExecutor.execute(BasicExecutor.java:87)
at org.hibernate.hql.ast.QueryTranslatorImpl.executeUpdate(QueryTranslatorImpl.java:398)
at org.hibernate.engine.query.HQLQueryPlan.performExecuteUpdate(HQLQueryPlan.java:259)
at org.hibernate.impl.SessionImpl.executeUpdate(SessionImpl.java:1142)
at org.hibernate.impl.QueryImpl.executeUpdate(QueryImpl.java:94)
at com.cee.common.GenericDAO.executeHQL(GenericDAO.java:77)
at com.cee.pwgh.sysExt.dao.GzkLbDAO.deleteGzkLbByLbid(GzkLbDAO.java:59)
at com.cee.pwgh.sysExt.service.GzkLbManager.process(GzkLbManager.java:72)
at com.cee.pwgh.sysExt.service.GzkLbManager$$FastClassByCGLIB$$555d2384.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:700)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635)
at com.cee.pwgh.sysExt.service.GzkLbManager$$EnhancerByCGLIB$$7cb32887.process(<generated>)
at com.cee.pwgh.sysExt.web.action.GzkLbController.process(GzkLbController.java:43)
... 30 more
Caused by: java.sql.SQLException: ORA-00060: 等待资源时检测到死锁
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:219)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:970)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1190)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3370)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3454)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.logicalcobwebs.proxool.ProxyStatement.invoke(ProxyStatement.java:100)
at org.logicalcobwebs.proxool.ProxyStatement.intercept(ProxyStatement.java:57)
at oracle.jdbc.OracleStatement$$EnhancerByProxool$$f4e9fcb7.executeUpdate(<generated>)
at org.hibernate.hql.ast.exec.BasicExecutor.execute(BasicExecutor.java:78)
... 46 more
2011-8-22 18:11:22 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet pwgh threw exception
java.sql.SQLException: ORA-00060: 等待资源时检测到死锁
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:219)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:970)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1190)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3370)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3454)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(
==============异常信息结束===============================================================================================================
二:再看涉及到的两个表结构,
原始建表的sql语句如下:
create table GZK_LB (
LBID VARCHAR2(32) not null,
MC VARCHAR2(60),
PQ VARCHAR2(32),
YEAR VARCHAR2(4) not null,
constraint PK_GZK_LB primary key (LBID)
);
create table GZK_NR (
NRID VARCHAR2(32) not null,
MLID VARCHAR2(32),
GZID VARCHAR2(32),
DYSQL VARCHAR2(100),
DYB VARCHAR2(40),
MS VARCHAR2(100),
MC VARCHAR2(60),
constraint PK_GZK_NR primary key (NRID)
);
alter table GZK_NR add constraint FK_GZK_NR_REFERENCE_GZK_LB foreign key (MLID) references GZK_LB (LBID);
表GZK_NR.MLID上有一个外键引用GZK_LB.LBID。
下面是通过toad拷贝出来的数据库中实际的表结构。
==============表结构开始===============================================================================================================
CREATE TABLE GZK_LB
(
LBID VARCHAR2(32 BYTE) NOT NULL,
MC VARCHAR2(60 BYTE),
PQ VARCHAR2(32 BYTE),
YEAR VARCHAR2(4 BYTE) NOT NULL
)
TABLESPACE PWGH
PCTUSED 0
PCTFREE 10
INITRANS 10
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
BUFFER_POOL DEFAULT
)
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;
CREATE UNIQUE INDEX PK_GZK_LB ON GZK_LB
(LBID)
LOGGING
TABLESPACE PWGH
PCTFREE 10
INITRANS 10
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
BUFFER_POOL DEFAULT
)
NOPARALLEL;
ALTER TABLE GZK_LB ADD (
CONSTRAINT PK_GZK_LB
PRIMARY KEY
(LBID)
USING INDEX
TABLESPACE PWGH
PCTFREE 10
INITRANS 10
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
));
CREATE TABLE GZK_NR
(
NRID VARCHAR2(32 BYTE) NOT NULL,
MLID VARCHAR2(32 BYTE),
GZID VARCHAR2(32 BYTE),
DYSQL VARCHAR2(100 BYTE),
DYB VARCHAR2(40 BYTE),
MS VARCHAR2(100 BYTE),
MC VARCHAR2(60 BYTE)
)
TABLESPACE PWGH
PCTUSED 0
PCTFREE 10
INITRANS 1
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
BUFFER_POOL DEFAULT
)
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;
CREATE INDEX INDEX_GZK_NR_MLID ON GZK_NR
(MLID)
LOGGING
TABLESPACE PWGH
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
BUFFER_POOL DEFAULT
)
NOPARALLEL;
CREATE UNIQUE INDEX PK_GZK_NR ON GZK_NR
(NRID)
LOGGING
TABLESPACE PWGH
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
BUFFER_POOL DEFAULT
)
NOPARALLEL;
ALTER TABLE GZK_NR ADD (
CONSTRAINT PK_GZK_NR
PRIMARY KEY
(NRID)
USING INDEX
TABLESPACE PWGH
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
));
ALTER TABLE GZK_NR ADD (
CONSTRAINT FK_GZK_NR_REFERENCE_GZK_LB
FOREIGN KEY (MLID)
REFERENCES GZK_LB (LBID));
ALTER TABLE GZK_NR ADD (
CONSTRAINT FK_GZK_NR_REFERENCE_GZK_MB
FOREIGN KEY (GZID)
REFERENCES GZK_MB (GZID));
==============表结构结束===============================================================================================================
三:触发异常的原因是因为批量的执行如下的语句:
delete from GZK_NR where MLID=?
delete from GZK_LB where LBID=?
即:先删除字子表GZK_NR的一些记录,然后删除这些记录通过外键对应的表GZK_LB中那条记录。
感觉这么做是没有问题的,但是却引发上述的异常:java.sql.SQLException: ORA-00060: 等待资源时检测到死锁。
似乎是表GZK_LB被锁住,不能及时释放。
四:解决办法:
办法1:禁用外键,
alter table GZK_NR disable constraint FK_GZK_NR_REFERENCE_GZK_LB;
办法2:保留外键,在表GZK_NR的外键列MLID上建立索引,并且需要是asc索引,
create index index_GZK_NR_mlid on GZK_NR(Mlid asc);
如果建立desc索引,
create index index_GZK_NR_mlid on GZK_NR(Mlid DESC);
上述异常仍然存在。
五:结论。
由此看出,如果要删除存在外键的两个表的数据,需要在子表的外键列上建立asc的索引,然后先删除子表数据,
再删除相应父表的记录。
itpub上有网友讨论这个问题的帖子:
http://www.itpub.net/viewthread.php?tid=1259329&extra=&page=1