Berkeley DB Java Edition 5.0.58 is a patch release consisting of fixes for a number of issues. We strongly recommend that users of the 5.0.x version upgrade to this release. These fixes include:

[#21396] The replay mechanism used in JE HA has been restructured to use multiple threads for increased concurrency. These changes result in a 20% increase in throughput in our performance tests.

[#21106] Made several improvements and fixes to log cleaning.
<li>Made changes to reduce bursty cleaning behavior. A burst of log cleaning would occur when selecting a log file for cleaning that has a significantly different average record size than the log files cleaned previously. The bursts impacted application performance.
<li>EnvironmentStats.getCorrectedAvgLNSize and getEstimatedAvgLNSize are deprecated and have been replaced by getLNSizeCorrectionFactor.
<li>Added INFO level logging that is output during log cleaning and helps to analyze cleaner behavior.
<li>Fixed a problem that prevented the following EnvironmentStat values from being cleared (set to zero) when StatsConfig.setClear(true) was used: getNBINDeltasObsolete, getNBINDeltasCleaned, getNBINDeltasDead, getNBINDeltasMigrated.
<li>Fixed a stats problem that incorrectly counted migrated LNs as marked for migration, even when lazy migration was disabled (which is the default setting). Migrated LNs were included in EnvironmentStats.getNLNsMarked and they should have been included in EnvironmentStats.getNLNsMigrated.
<li>Fixed a calculation error that prevented log cleaning probes (read-only cleaner runs that detect under-cleaning scenarios) from being executed. The error occurred only when the log file size was very large, e.g., 1 GB.

[#21598] Fixed a bug that sets the transaction state incorrectly when InsufficientAcksException is thrown during Transaction.commit(). Due to this bug, the transaction state is set to Transaction.State.MUST_ABORT when this exception is thrown. The incorrect state has two impacts:

<li>If Transaction.abort() is not called after InsufficientAcksException is thrown, the impact is only that Transaction.getState() will report the wrong value (MUST_ABORT). The transaction is committed on the master and will be committed on the replicas.
<li>If Transaction.abort() is called after InsufficientAcksException is thrown, the impact depends on whether Java assertions are enabled. If assertions are enabled, abort() fires an assertion resulting in a stack trace such as the one below. The transaction is committed on the master and will be committed on the replicas.

Caused by: java.lang.AssertionError
at com.sleepycat.je.txn.Txn.abortInternal(Txn.java:1127)
at com.sleepycat.je.txn.Txn.abort(Txn.java:1094)
at com.sleepycat.je.txn.Txn.abort(Txn.java:1067)
at com.sleepycat.je.Transaction.abort(Transaction.java:205)
...

<li>If assertions are disabled and Transaction.abort() is called after InsufficientAcksException is thrown, the abort() will succeed (at least temporarily) on the master, but for a brief period (between the commit and the abort) may appear to other threads as committed. It will always be committed on the replicas. The abort() will be permanent on the master unless an abnormal shutdown and recovery occur and the transaction is replayed by recovery; in that case, the transaction will be committed on the master and the replicas.
<li>To summarize, if Transaction.abort() is called after InsufficientAcksException is thrown and assertions are disabled, the transaction may be aborted on one node (the master at the time of the commit and abort), but committed on the other nodes (the replicas at the time). Otherwise, the only impact is that the transaction state will be wrong (it will be MUST_ABORT); in this case the transaction will be committed on all nodes.
<li>The likelihood of the bug occurring in production is low because the InsufficientAcksException only occurs when a replica becomes unavailable in a small window. Normally, InsufficientReplicasException (which does not trigger this bug) is thrown when a replica is unavailable.
<li>This bug was introduced in JE 5.0.48 and only applies to replicated environments. With the fix, the transaction state is correctly set to COMMITTED and the transaction will be committed on all nodes.
<li>A workaround for this bug (an alternative to upgrading JE) is to be sure not to call abort() after commit(), at least when InsufficientAcksException is thrown. Calling abort() after commit() fails can make exception handling simpler, but is never necessary.