Ошибка блокировки Neo4j "Не могу дождаться ресурса"

Я использую Node.js для подключения к размещенной базе данных GrapheneDB Neo4j, и при попытке добавить около 1500 записей я получаю следующую ошибку:

LockClient[19] can't wait on resource 
RWLock[NODE(248), hash=1917331445] since => LockClient[19] 
<-[:HELD_BY]- RWLock[INDEX_ENTRY(153122458561043471), hash=1171319680] 
<-[:WAITING_FOR]- LockClient[15] <-[:HELD_BY]- RWLock[NODE(248), hash=1917331445]

Код, который генерирует это, приходит из маршрута, который берет список объектов JSON и затем сохраняет их в Neo4j. При импорте около 1500 записей я получаю эту ошибку последовательно.

Использование seraph-model для доступа к базе данных и просто поиска записи, обновления, если она существует, или создания ее, если ее нет.

Любые предложения, где исследовать?

2 ответа

Решение

Похоже, что вы выполняете несколько крупных транзакций, одновременно попадающих в одну и ту же область вашего графика.

Когда Neo4j выполняет запись, блокировка записи получается на этом узле / отношении и снимается, когда транзакции закрываются. Другие транзакции, выполняющиеся одновременно, которые пытаются получить блокировку записи на уже заблокированном объекте, должны ждать - в противном случае ящик несоответствий Пандоры открылся бы. Если владелец блокировки является довольно длительной транзакцией, другая может столкнуться с тайм-аутом - это будет приведенное выше сообщение об ошибке.

Так что вы можете:

  1. сериализуйте операции: не делайте записи параллельно, вместо этого убедитесь, что в данный момент обрабатывается только одна жирная транзакция
  2. сделайте транзакции меньше: если вы делаете меньше в одной транзакции, продолжительность будет короче, а другие транзакции, ожидающие блокировки, не прекратят работу.

Я тоже переживал это. Предлагаемые обходные пути, о которых я читал:

  • сериализовать параллельные записи (но вы теряете преимущество параллелизма)
  • перечислить узлы в запросе на запись, используя некоторый порядок, например, сортировку идентификаторов (но это добавляет накладные расходы на сортировку к потокам записи)

Я решил пойти с третьим вариантом: повторить попытку операции Cypher, пока она не пойдет хорошо, или до максимума нет. времени, пауза на случайное время между попытками. Эта утилита моя может помочь. Для драйвера Neo4, org.neo4j.driver.v1.exceptions.TransientException это исключение, которое вы хотите передать конструктору.

Другие вопросы по тегам