Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: read in_hot_standby GUC on connection #2334

Merged
merged 7 commits into from Nov 10, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -76,6 +76,8 @@ public class ConnectionFactoryImpl extends ConnectionFactory {
private static final int AUTH_REQ_SASL_CONTINUE = 11;
private static final int AUTH_REQ_SASL_FINAL = 12;

private static final String IN_HOT_STANDBY = "in_hot_standby";

private ISSPIClient createSSPI(PGStream pgStream,
@Nullable String spnServiceClass,
boolean enableNegotiate) {
Expand Down Expand Up @@ -864,9 +866,15 @@ private void runInitialQueries(QueryExecutor queryExecutor, Properties info)
}

private boolean isPrimary(QueryExecutor queryExecutor) throws SQLException, IOException {
String inHotStandby = queryExecutor.getParameterStatus(IN_HOT_STANDBY);
if (inHotStandby != null && inHotStandby.equalsIgnoreCase("on")) {
davecramer marked this conversation as resolved.
Show resolved Hide resolved
return false;
}
// Host may not be in recovery but still have 'transaction_read_only=on' set,
davecramer marked this conversation as resolved.
Show resolved Hide resolved
// hence explicit check
Tuple results = SetupQueryRunner.run(queryExecutor, "show transaction_read_only", true);
Tuple nonNullResults = castNonNull(results);
String value = queryExecutor.getEncoding().decode(castNonNull(nonNullResults.get(0)));
return value.equalsIgnoreCase("off");
String queriedTransactionReadonly = queryExecutor.getEncoding().decode(castNonNull(nonNullResults.get(0)));
return queriedTransactionReadonly.equalsIgnoreCase("off");
}
}
Expand Up @@ -27,6 +27,7 @@
import org.postgresql.test.TestUtil;
import org.postgresql.util.HostSpec;
import org.postgresql.util.PSQLException;
import org.postgresql.util.PSQLState;

import org.junit.Before;
import org.junit.BeforeClass;
Expand Down Expand Up @@ -236,6 +237,29 @@ public void testConnectToMaster() throws SQLException {
assertGlobalState(secondary1, "Secondary"); // was unknown, so tried to connect in order
}

@Test
public void testConnectToPrimaryWithReadonlyTransactionMode() throws SQLException {
con = TestUtil.openPrivilegedDB();
con.createStatement().execute("ALTER DATABASE " + TestUtil.getDatabase() + " SET default_transaction_read_only=on;");
try {
getConnection(primary, true, fake1, primary1, secondary1);
} catch (PSQLException e) {
assertEquals(PSQLState.CONNECTION_UNABLE_TO_CONNECT.getState(), e.getSQLState());
assertGlobalState(fake1, "ConnectFail");
assertGlobalState(primary1, "Secondary");
assertGlobalState(secondary1, "Secondary");
} finally {
con = TestUtil.openPrivilegedDB();
con.createStatement().execute(
"BEGIN;"
+ "SET TRANSACTION READ WRITE;"
+ "ALTER DATABASE " + TestUtil.getDatabase() + " SET default_transaction_read_only=off;"
+ "COMMIT;"
);
TestUtil.closeDB(con);
}
}

@Test
public void testConnectToSecondary() throws SQLException {
getConnection(secondary, true, fake1, secondary1, primary1);
Expand Down Expand Up @@ -347,7 +371,7 @@ public void testLoadBalancing_secondary() throws SQLException {
break;
}
}
assertEquals("Did not attempt to connect to all salve hosts", new HashSet<String>(asList(secondaryIP, secondaryIP2)),
assertEquals("Did not attempt to connect to all secondary hosts", new HashSet<String>(asList(secondaryIP, secondaryIP2)),
connectedHosts);
assertEquals("Did not attempt to connect to primary and fake node", 4, tryConnectedHosts.size());

Expand Down