在对 10,000 条消息进行负载测试期间,我看到一些独特的约束违规(10,000 条消息中只有 8 条受到影响)。我想知道是否需要在 DBCP 数据源设置或 Active MQ 设置中进行更改。错误是
org.springframework.jms.UncategorizedJmsException: Uncategorized exception occured during
JMS processing; nested exception is javax.jms.JMSException:
ORA-00001: unique constraint (WEBSVC.SYS_C00181594) violated
我查看了这个约束并将其跟踪到 ACTIVEMQ_MSGS 一个我们让 Active MQ 在 Oracle 中创建和维护自己的表。例如
select * from all_constraints
where constraint_name = 'SYS_C00181594'
OWNER CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME SEARCH_CONDITION R_OWNER R_CONSTRAINT_NAME DELETE_RULE STATUS DEFERRABLE DEFERRED VALIDATED GENERATED BAD RELY LAST_CHANGE INDEX_OWNER INDEX_NAME INVALID VIEW_RELATED
------ --------------- --------------- ------------- ---------------- ------- ----------------- ----------- ------- -------------- --------- --------- -------------- --- ---- -------------------- ----------- ------------- ------- ------------
WEBSVC SYS_C00181594 P ACTIVEMQ_MSGS ENABLED NOT DEFERRABLE IMMEDIATE VALIDATED GENERATED NAME 22-Mar-2013 16:16:22 SYS_C00181594
当我将消息放入队列时会发生这种情况,下面是完整的堆栈跟踪
引起:java.io.IOException:ORA-00001:违反唯一约束(WEBSVC.SYS_C00181594)
at org.apache.activemq.util.IOExceptionSupport.create(IOExceptionSupport.java:45)
at org.apache.activemq.store.jdbc.TransactionContext.close(TransactionContext.java:138)
at org.apache.activemq.store.jdbc.JDBCMessageStore.addMessage(JDBCMessageStore.java:129)
at org.apache.activemq.store.memory.MemoryTransactionStore.addMessage(MemoryTransactionStore.java:328)
at org.apache.activemq.store.memory.MemoryTransactionStore$1.asyncAddQueueMessage(MemoryTransactionStore.java:155)
at org.apache.activemq.broker.region.Queue.doMessageSend(Queue.java:744)
at org.apache.activemq.broker.region.Queue.send(Queue.java:717)
at org.apache.activemq.broker.region.AbstractRegion.send(AbstractRegion.java:407)
at org.apache.activemq.broker.region.RegionBroker.send(RegionBroker.java:503)
at org.apache.activemq.broker.jmx.ManagedRegionBroker.send(ManagedRegionBroker.java:311)
at org.apache.activemq.broker.BrokerFilter.send(BrokerFilter.java:129)
at org.apache.activemq.broker.CompositeDestinationBroker.send(CompositeDestinationBroker.java:96)
at org.apache.activemq.broker.TransactionBroker.send(TransactionBroker.java:317)
at org.apache.activemq.broker.MutableBrokerFilter.send(MutableBrokerFilter.java:135)
at org.apache.activemq.broker.TransportConnection.processMessage(TransportConnection.java:450)
at org.apache.activemq.command.ActiveMQMessage.visit(ActiveMQMessage.java:680)
at org.apache.activemq.broker.TransportConnection.service(TransportConnection.java:294)
at org.apache.activemq.broker.TransportConnection$1.onCommand(TransportConnection.java:152)
at org.apache.activemq.transport.ResponseCorrelator.onCommand(ResponseCorrelator.java:116)
at org.apache.activemq.transport.MutexTransport.onCommand(MutexTransport.java:50)
at org.apache.activemq.transport.vm.VMTransport.iterate(VMTransport.java:241)
at org.apache.activemq.thread.PooledTaskRunner.runTask(PooledTaskRunner.java:129)
at org.apache.activemq.thread.PooledTaskRunner$1.run(PooledTaskRunner.java:47)
... 3 more
引起:java.sql.BatchUpdateException:ORA-00001:违反唯一约束(WEBSVC.SYS_C00181594)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10345)
at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:230)
at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
at org.apache.activemq.store.jdbc.TransactionContext.executeBatch(TransactionContext.java:103)
at org.apache.activemq.store.jdbc.TransactionContext.executeBatch(TransactionContext.java:81)
at org.apache.activemq.store.jdbc.TransactionContext.close(TransactionContext.java:129)
我现在有一个非常偏执的 DBCP BasicDataSource,即
<bean id="basicOracleDataSource" class="org.apache.commons.dbcp.BasicDataSource"
abstract="true" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="poolPreparedStatements" value="true"/>
<property name="initialSize" value="5"/>
<property name="maxActive" value="30"/>
<property name="maxWait" value="60000"/> <!-- default indefinitely -->
<property name="timeBetweenEvictionRunsMillis" value="30000" />
<!-- verify connections in the pool to stop connection closed errors -->
<property name="logAbandoned" value="false"/> <!-- default false -->
<property name="maxIdle" value="5"/> <!-- default 8, minIdle defaults to 0 which is OK -->
<property name="numTestsPerEvictionRun" value="4"/> <!-- default 3 -->
<property name="removeAbandoned" value="true"/> <!-- default false -->
<property name="removeAbandonedTimeout" value="60"/><!-- default 300 seconds -->
<property name="testOnBorrow" value="true"/> <!-- default false -->
<property name="testOnReturn" value="true"/> <!-- default false -->
<property name="testWhileIdle" value="true"/> <!-- default false -->
<property name="validationQuery" value="SELECT 1 FROM dual"/>
</bean>
以防万一,这也是我的 JMS 模板
<!-- Spring JMS Template -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<!-- lets wrap in a pool to avoid creating a connection per send -->
<bean class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory">
<ref local="jmsFactory" />
</property>
</bean>
</property>
</bean>