遇到的BUG:
2017-06-21 18:37:02,808 ERROR ProcessCredence2TransferJob.java 69 - Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.account.comm.dataset.Credence#632]
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.account.comm.dataset.Credence#632]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2479)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3189)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3087)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3416)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:140)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:276)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
at com.account.comm.dao.HibernateHelper.commitAndCloseSession(HibernateHelper.java:76)
at com.account.comm.dao.DataSetProxy.after(DataSetProxy.java:58)
at com.account.comm.dao.DataSetProxy.invoke(DataSetProxy.java:48)
at com.sun.proxy.$Proxy9.queryWithPage(Unknown Source)
at com.account.job.charge.ProcessCredence2TransferJob.getUntransferCredenceList(ProcessCredence2TransferJob.java:78)
at com.account.job.charge.ProcessCredence2TransferJob.execute(ProcessCredence2TransferJob.java:35)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)`这里写代码片`
产生原因 :
Hibernate乐观锁机制造成的。 当多个事务同时对数据库表中的同一条数据操作时,如果没有加锁机制的话,就会产生脏数据(duty data)。Hibernate有2种机制可以解决这个问题:乐观锁和悲观锁。Hibernate乐观锁,能自动检测多个事务对同一条数据进行的操作,并根据先胜原则,提交第一个事务,其他的事务提交时则抛出org.hibernate.StaleObjectStateException异常。
解决方法:
建议先执行下列SQL:(PS:我用的是MySQL~)
select * from information_schema.`PROCESSLIST`;
SELECT * FROM information_schema.INNODB_TRX;
第一个SQL查询:
在网上找了半天也没有找到中文版的解释,中文版只停留在mysql5.1版本;没办法只能去看英文版的了。
mysql官方参考手册对processlist介绍:
Notes:
• The PROCESSLIST table is a nonstandard table.
• Like the output from the corresponding SHOW statement, the PROCESSLIST table will only show information about your own threads, unless you have the PROCESS privilege, in which case you will see information about other threads, too. As an anonymous user, you cannot see any rows at all.
• If an SQL statement refers to INFORMATION_SCHEMA.PROCESSLIST, MySQL populates the entire table once, when statement execution begins, so there is read consistency during the statement.
There is no read consistency for a multi-statement transaction, though.
• Process information is also available from the performance_schema.threads table. However, access to threads does not require a mutex and has minimal impact on server performance. INFORMATION_SCHEMA.PROCESSLIST and SHOW PROCESSLIST have negative performance consequences because they require a mutex. threads also shows information about background threads, which INFORMATION_SCHEMA.PROCESSLIST and SHOW PROCESSLIST do not. This means that threads can be used to monitor activity the other thread information sources cannot.
大概讲这个表不是一个标准mysql表,如果有权限可以查看其它线程的执行信息。
我的理解是:
Credence这张表在,一个线程正在执行,并开启了事务,还没有提交或关闭事务;此时又有一个线程对该表进行修改更新操作,就出现了该问题。如果可以,把INFORMATION_SCHEMA.PROCESSLIST表的线程全都干掉,就可以解决该问题!
第二条SQL语句是查询未提交事务的!
但是,这是下下策!具体解决方法,还在进行时~~~~