Я разрабатываю Java-приложение, которое использует test_decoding + драйвер jdbc для выполнения логической репликации PG.Основной код взят из документации PG .
PGReplicationStream stream =
replConnection.getReplicationAPI()
.replicationStream()
.logical()
.withSlotName("demo_logical_slot")
.withSlotOption("include-xids", true)
.withSlotOption("skip-empty-xacts", true)
.withSlotOption("include-timestamp", "on")
.withStatusInterval(5, TimeUnit.SECONDS)
.start();
while (true) {
//non blocking receive message
ByteBuffer msg = stream.readPending();
if (msg == null) {
TimeUnit.MILLISECONDS.sleep(10L);
continue;
}
int offset = msg.arrayOffset();
byte[] source = msg.array();
int length = source.length - offset;
System.out.println(new String(source, offset, length));
//feedback
stream.setAppliedLSN(stream.getLastReceiveLSN());
stream.setFlushedLSN(stream.getLastReceiveLSN());
}
Приведенный выше код отлично работает для большинства сценариев.
Однако stream.readPending()
выдаст ошибку OOM, когда большая транзакция передаст postgresql.
В моем случае я обновляю 432629 строк в одной транзакции, а сервер Java (2 ЦП + 4 ГБ памяти) выдает ошибку OOM.
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at org.postgresql.core.PGStream.receive(PGStream.java:445)
at org.postgresql.core.v3.QueryExecutorImpl.processCopyResults(QueryExecutorImpl.java:1170)
at org.postgresql.core.v3.QueryExecutorImpl.readFromCopy(QueryExecutorImpl.java:1035)
at org.postgresql.core.v3.CopyDualImpl.readFromCopy(CopyDualImpl.java:41)
at org.postgresql.core.v3.replication.V3PGReplicationStream.receiveNextData(V3PGReplicationStream.java:155)
at org.postgresql.core.v3.replication.V3PGReplicationStream.readInternal(V3PGReplicationStream.java:124)
at org.postgresql.core.v3.replication.V3PGReplicationStream.readPending(V3PGReplicationStream.java:78)
Поэтому мой вопрос заключается в том, как исправить ошибкуОшибка OOM, кроме увеличения аппаратного обеспечения сервера Java.