Не удалось создать составной индекс, застрявший в INSTALLED
Я не могу создать индекс. Мой код Гремлина выглядит следующим образом:
usernameProperty = mgmt.getPropertyKey('username')
usernameIndex = mgmt.buildIndex('byUsernameUnique', Vertex.class).addKey(usernameProperty).unique().buildCompositeIndex()
mgmt.setConsistency(usernameIndex, ConsistencyModifier.LOCK)
mgmt.commit()
Вскоре после получения двух ошибок:
18:04:57 ERROR com.thinkaurelius.titan.graphdb.database.management.ManagementLogger - Evicted [1 @0a00009d2537-ip-10-0-0-1572] из кеша, но слишком долго ждать завершения транзакций. Предупреждение о старом транзакции: [standardtitantx [0x6549ce71]] 18:04:57 ERROR com.thinkaurelius.titan.graphdb.database.management.ManagementLogger - Evicted [1 @0a00009d2537-ip-10-0-0-1572] из кеша, но слишком долго ждать завершения транзакций. Предупреждение о старом транзакции: [standardtitantx [0x2a2815cc], standardtitantx [0x025dc2c0]]
Состояние индекса застревает в INSTALLED
:
usernameIndex.getIndexStatus(usernameProperty)
==>INSTALLED
Я прочитал, что неудавшийся экземпляр может вызвать проблему, но проверка запущенных экземпляров показывает только одно:
mgmt.getOpenInstances()
==>0a00009d3011-ip-10-0-0-1572(current)
Я также попытался выпустить действие REGISTER_INDEX
, которое также выдается из кэша транзакций с аналогичным сообщением об ошибке:
mgmt.updateIndex(usernameIndex, SchemaAction.REGISTER_INDEX).get()
mgmt.commit()
Я также пытался перезапустить сервер несколько раз.
Кажется, что процесс регистрации - это просто тайм-аут, вызывающий "выселение" из кэша транзакций. Я ждал 48 часов, чтобы убедиться, что это не медленный процесс. Нормальные чтения, записи и связанные с ними коммиты Titan действительно работают правильно, я просто не могу создать этот индекс. Я застрял, есть ли что-то еще, что я могу попробовать? Есть ли способ продлить время ожидания этой транзакции?
Я запускаю Titan 1.0.0 с использованием бэкэнда DynamoDB (настройка с использованием AWS Template Template).
EDIT:
Вот полная команда, которую я вставляю в Гремлин с добавлением шага awaitGraphStatus
, предложенного @M-T-A:
mgmt = graph.openManagement();
usernameIndex = mgmt.getPropertyKey('usernameIndex');
mgmt.buildIndex('byUsername',Vertex.class).addKey(usernameIndex).unique().buildCompositeIndex();
// I have tried with and without a commit here: mgmt.commit();
mgmt.awaitGraphIndexStatus(graph, 'byUsername').status(SchemaStatus.REGISTERED).timeout(10, java.time.temporal.ChronoUnit.MINUTES).call();
Это приводит к следующей ошибке:
java.lang.NullPointerException на com.thinkaurelius.titan.graphdb.database.management.GraphIndexStatusWatcher.call(GraphIndexStatusWatcher.java:52) на com.thinkaurelius.titan.graphdb.database.management.GraphIndexStatusWatcher.call(GraphIndexStatusWatcher.java:18) в java_util_concurrent_Callable $call.call(Неизвестный источник) на org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45) на org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:110) на org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:114) на groovysh_evaluate.run(groovysh_evaluate: 3) на org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:215) at org.codehaus.groovy.tools.shell.Interpreter.evaluate(Interpreter.groovy: 69) на org.codehaus.groovy.tools.shell.Groovysh.execute(Groovysh.groovy: 185) на org.codehaus.groovy.tools.shell.Shell.leftShift(Shell.groovy: 119) на org.codehaus.groovy.tools.shell.ShellRunner.work(ShellRunner.groovy: 94)
Я также буду замечать, что процедура отключения и удаления индекса также терпит неудачу.
mgmt = graph.openManagement()
theIndex = mgmt.getGraphIndex('byUsername')
mgmt.updateIndex(theIndex, SchemaAction.DISABLE_INDEX).get()
mgmt.commit()
mgmt.awaitGraphIndexStatus(graph, 'byUsername').status(SchemaStatus.DISABLED).timeout(10, java.time.temporal.ChronoUnit.MINUTES).call();
m = graph.openManagement()
i = m.getGraphIndex('byUsername')
m.updateIndex(i, SchemaAction.REMOVE_INDEX).get()
m.commit()
19:26:26 ERROR com.thinkaurelius.titan.graphdb.database.management.ManagementLogger - выровнен [1 @ac1f3fa810472-ip-172-31-63-1681] из кеша, но слишком долго ждать завершения транзакций. Предупреждение о старом транзакции: [standardtitantx [0x2314cd97], standardtitantx [0x39f8adc0], standardtitantx [0x09de1b85]]
ИЗМЕНИТЬ 2:
Попытка создать новый ключ свойства и индекс в пределах одной транзакции РАБОТАЕТ! Но означает ли это, что я не могу создавать индексы на существующих ключах свойств?
graph.tx().rollback();
mgmt = graph.openManagement();
indexName = 'byUsernameTest2';
propertyKeyName = 'testPropertyName2';
propertyKey = mgmt.makePropertyKey(propertyKeyName).dataType(String.class).cardinality(Cardinality.SINGLE).make();
mgmt.buildIndex(indexName,Vertex.class).addKey(propertyKey).buildCompositeIndex();
mgmt.commit();
graph.tx().commit();
mgmt.awaitGraphIndexStatus(graph, indexName).status(SchemaStatus.REGISTERED).timeout(10, java.time.temporal.ChronoUnit.MINUTES).call();
mgmt.commit();
После паузы это приводит к:
Этот экземпляр системы управления закрыт
Попытка получить новые результаты индекса:
mgmt = graph.openManagement();
index = mgmt.getGraphIndex('byUsernameTest2');
propkey = mgmt.getPropertyKey('testPropertyName2');
index.getIndexStatus(propkey);
== > ВКЛЮЧЕНО
Ответы
Ответ 1
Если вы используете несколько экземпляров Titan, вы должны знать, что они должны координировать работу до того, как индекс станет доступным.
Кроме того, существуют различные тонкости управления транзакциями и при каких обстоятельствах транзакции будут оставлены открытыми; Я полагаю, что Titan 1.0.0 не имеет последней версии от TinkerPop в этом отношении. Вы пытались создать индекс сразу после загрузки?
Наконец, процесс создания индекса отличается в зависимости от того, были ли ранее использованы индексы свойств. Вы пытаетесь индексировать новые ключи или существующие?
Ответ 2
Вам нужно подождать, пока Titan и DynamoDB не смогут зарегистрировать индекс. Вы можете сделать это:
ManagementSystem.awaitGraphIndexStatus(graph, propertyKeyIndexName)
.status(SchemaStatus.REGISTERED)
.timeout(10, java.time.temporal.ChronoUnit.MINUTES) // set timeout to 10 min
.call();
Тайм-аут по умолчанию обычно не достаточно длинный, поэтому вы можете увеличить его до 10 минут, обычно это трюк с поддержкой Dynamo.
Только когда индекс находится в состоянии REGISTERED, вы можете выполнить переопределение. Когда вы перевернете, вам нужно подождать, пока он не будет включен. повторным использованием примера кода выше и изменением состояния на ENABLED.
Для получения дополнительной информации см. docs.
Изменить
Позвольте мне разделить код, который работает со мной на Berkeley и Dynamo DB backends все время.
graph.tx().rollback(); //Never create new indexes while a transaction is active
TitanManagement mgmt=graph.openManagement();
PropertyKey propertyKey=getOrCreatePropertyKeyIfNotExist(mgmt, propertyKeyName);
String indexName = makePropertyKeyIndexName(propertyKey);
if (mgmt.getGraphIndex(indexName)==null) {
mgmt.buildIndex(indexName, Vertex.class).addKey(propertyKey).buildCompositeIndex();
mgmt.commit(); // you MUST commit mgmt
graph.tx().commit(); // and commit the transaction too
ManagementSystem.awaitGraphIndexStatus(graph, indexName).status(SchemaStatus.REGISTERED).call();
}else { // already defined.
mgmt.rollback();
graph.tx().rollback();
}
private static PropertyKey getOrCreatePropertyKeyIfNotExist(TitanManagement mgmt, String s) {
PropertyKey key = mgmt.getPropertyKey(s);
if (key != null)
return key;
else
return mgmt.makePropertyKey(s).dataType(String.class).make();
}
private static String makePropertyKeyIndexName(PropertyKey pk) {
return pk.name() + Tokens.INDEX_SUFFIX;
}
Из ошибки, которую я видел, похоже, что Titan не смог получить индекс, что означает, что вы ожидаете индекса, который даже не определен. Посмотрите на строку, которая вызывает ошибку здесь.
Убедитесь, что вы передаете правильное имя индекса в awaitGraphIndexStatus
.