-
Couldn't load subscription status.
- Fork 1.6k
Open
Description
I'm looking at adding support for locking in clickhouse flyway/flyway-community-db-support#48. InsertRowLock is close to working, but because clickhouse doesn't support traditional primary keys I had to make some modifications to it.
I'm allowing multiple locks to be written, but consistently selecting a winner by ordering on timestamp + version. This needs the insertLockingRow to also query the current owner.
I would like to refactor InsertRowLock a little and pull out an AbstractInsertRowLock allowing for subclasses to implement insertLockingRow.
This is what i'm currently using for clickhouse's `insertRowLock
private boolean insertLockingRow(String insertStatementTemplate, String currentLockOwnerStatementTemplate, String booleanTrue, String checksumValue) throws InterruptedException {
String currentLockOwner = getCurrentLockOwner(currentLockOwnerStatementTemplate);
if (tableLockString.equals(currentLockOwner)) {
return true;
}
if (currentLockOwner != null) {
// owned by another migration
LOG.info("[{}] Unable to lock, already owned by {}", tableLockString, currentLockOwner);
return false;
}
String insertStatement = String.format(insertStatementTemplate.replace("?", "%s"),
-100,
"'" + tableLockString + "'",
"'" + FLYWAY_LOCK_STRING + "'",
"''",
"''",
checksumValue,
"''",
0,
booleanTrue
);
// Insert the locking row - the primary key-ness of 'installed_rank' will prevent us having two
Results results = jdbcTemplate.executeStatement(insertStatement);
if (results.getException() != null) {
return false;
}
if (currentLockOwnerStatementTemplate == null) {
return true;
}
currentLockOwner = getCurrentLockOwner(currentLockOwnerStatementTemplate);
if (tableLockString.equals(currentLockOwner)) {
// double check we are still the current lock owner, in case we raced with another
// insert and need version ordering to select the current owner
currentLockOwner = getCurrentLockOwner(currentLockOwnerStatementTemplate);
if (tableLockString.equals(currentLockOwner)) {
// this row lock is the owner
return true;
}
}
// not the owner
LOG.info("[{}] Attempted to lock, but already owned by {}", tableLockString, currentLockOwner);
return false;
}
private String getCurrentLockOwner(String currentLockOwnerStatementTemplate) {
if (currentLockOwnerStatementTemplate == null) {
return null;
}
String currentLockOwnerStatement = String.format(currentLockOwnerStatementTemplate.replace("?", "%s"),
"'" + FLYWAY_LOCK_STRING + "'"
);
Results results = jdbcTemplate.executeStatement(currentLockOwnerStatement);
for (Result result : results.getResults()) {
List<List<String>> data = result.data();
if (data == null || data.isEmpty()) {
continue;
}
int columnIndex = result.columns().indexOf("version");
if (columnIndex == -1) {
throw new IllegalStateException("missing 'version' column in currentLockOwnerStatementTemplate: " + currentLockOwnerStatementTemplate);
}
return data.getFirst().get(columnIndex);
}
return null;
}
Metadata
Metadata
Assignees
Labels
No labels