简体   繁体   English

删除记录时在 ScalarDB 中获取 InvalidUsageException

[英]Getting InvalidUsageException in ScalarDB when deleting a record

I am using ScalarDB which provides ACID functionality on Cassandra .我正在使用 ScalarDB,它在Cassandra上提供 ACID 功能。 While deleting a record, I am getting com.scalar.db.exception.transaction.InvalidUsageException: the record to be deleted must be existing and read beforehand exception.删除记录时,我收到com.scalar.db.exception.transaction.InvalidUsageException: the record to be deleted must be existing and read beforehand异常。

I am deleting entries from several tables (thus using Scalar to provide Atomocity).我正在从几个表中删除条目(因此使用 Scalar 来提供 Atomocity)。 I created a DistributedTransaction at the start and then started deleting the entries.我在开始时创建了一个DistributedTransaction ,然后开始删除条目。

def deleteQuestion(questionKey:PracticeQuestionKeys,user:User) = {
    logger.trace(s"delete question request ${questionKey}, ${user}")
    val transaction = transactionService.start
    val questionGetResult = getQuestionFromQuestionID(transaction,questionKey)//
    if(questionGetResult.isLeft) throw questionGetResult.left.get
    val question = questionGetResult.right.get
    deleteQuestionIfUserIsAuthorized(transaction,questionKey, question, user)
    deleteQuestionTagFromTagRepository(transaction,question)
    deleteQuestionFromProfileAndPortfolio(transaction, question, user.id)
    commitTransaction(transaction)
  }

All steps before commitTransaction seem to be ok but `commitTransaction fails with error commitTransaction之前的所有步骤似乎都没有问题,但是`commitTransaction 失败并出现错误

2020-08-02 13:19:12,883 [WARN] from com.scalar.db.transaction.consensuscommit.CommitHandler in scala-execution-context-global-141 - preparing records failed
com.scalar.db.exception.transaction.InvalidUsageException: the record to be deleted must be existing and read beforehand
    at com.scalar.db.transaction.consensuscommit.PrepareMutationComposer.add(PrepareMutationComposer.java:89)
    at com.scalar.db.transaction.consensuscommit.PrepareMutationComposer.add(PrepareMutationComposer.java:45)
    at com.scalar.db.transaction.consensuscommit.Snapshot.lambda$to$1(Snapshot.java:134)
    at java.util.concurrent.ConcurrentHashMap$EntrySetView.forEach(ConcurrentHashMap.java:4795)
    at com.scalar.db.transaction.consensuscommit.Snapshot.to(Snapshot.java:130)
    at com.scalar.db.transaction.consensuscommit.CommitHandler.prepareRecords(CommitHandler.java:104)
    at com.scalar.db.transaction.consensuscommit.CommitHandler.commit(CommitHandler.java:40)
    at com.scalar.db.transaction.consensuscommit.ConsensusCommit.commit(ConsensusCommit.java:121)
    at services.QuestionsTransactionDatabaseService.commitTransaction(QuestionsTransactionDatabaseService.scala:251)
    at services.QuestionsTransactionDatabaseService.deleteQuestion(QuestionsTransactionDatabaseService.scala:388)
    at services.QuestionsTransactionService.$anonfun$deleteQuestion$1(QuestionsTransactionService.scala:57)
    at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
    at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:653)
    at scala.util.Success.$anonfun$map$1(Try.scala:251)
    at scala.util.Success.map(Try.scala:209)
    at scala.concurrent.Future.$anonfun$map$1(Future.scala:287)
    at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:29)
    at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:29)
    at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:60)
    at scala.concurrent.impl.ExecutionContextImpl$AdaptedForkJoinTask.exec(ExecutionContextImpl.scala:140)
    at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
    at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
    at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)

Referring to https://scalardl.readthedocs.io/en/latest/trouble-shooting-guide/ , it seems blind delete is not allowed.参考https://scalardl.readthedocs.io/en/latest/trouble-shooting-guide/ ,好像是不允许盲删的。 But I have tried doing a get before delete and have also tried to put conditions like DeleteIfExists but I am still getting the error.但是我已经尝试在删除之前进行get ,并且还尝试设置像DeleteIfExists这样的条件,但我仍然收到错误消息。

def delete(transaction:DistributedTransaction,key:PracticeKeys) = {
    logger.trace("Deleting question. Checking if question exists for" + key)
    get(transaction,key) //I have tried with and without commenting getting/reading question before deleting
    //Perform the operations you want to group in the transaction
    val pKey = new Key(new TextValue("id", key.id.toString))
    logger.trace(s"created question keys ${pKey}")
    logger.trace(s"getting question using ${keyspaceName}, ${tablename}")
    val deleteToken:Delete =  new Delete(pKey)
      .forNamespace(keyspaceName)
      .forTable(tablename)
      .withCondition(new DeleteIfExists)

    transaction.delete(deleteToken)
  }

Why do I have to get a record before deleting it?为什么我必须先get记录才能删除它? What is the way to delete straightaway?有什么方法可以直接删除? Am I not using the library correctly?我没有正确使用图书馆吗?

As it turns out, the problem was in my code.事实证明,问题出在我的代码中。 Firstly, we have to do a get before doing a delete .首先,我们必须在执行delete之前执行get I don't know why but that is the rule it seems.我不知道为什么,但这似乎是规则。

So I added a get in each delete所以我在每次delete中添加了一个get

def delete(transaction:DistributedTransaction,questionKey:QuestionsCreatedByAUserForATagKeys) = {
    logger.trace(s"deleting question created for tag with key ${questionKey}")
    get(transaction,questionKey) // <-- HERE. I should probably also check if get returned a valid record.
    val pQuestionsCreatedKey = new Key(
      new TextValue("question_creator", questionKey.creator.creatorId.toString),
      new TextValue("tag", questionKey.tag)
    )

    val cQuestionKey = if(questionKey.creationMonth !=0 && questionKey.creationYear !=0 && questionKey.questionId.isDefined){
      new Key(
        new BigIntValue("creation_year", questionKey.creationYear),
        new BigIntValue("creation_month", questionKey.creationMonth),
        new TextValue("question_id", questionKey.questionId.get.toString),
      )
    } else {
      throw CannotDeleteWithoutEntireCompositeKeyException()
    }

    logger.trace(s"deleting question with keys ${pQuestionsCreatedKey},${cQuestionKey}")


    val deleteToken = new Delete(pQuestionsCreatedKey,cQuestionKey)
        .forNamespace(keyspaceName)
        .forTable(tablename)
        .withCondition(new DeleteIfExists)


    logger.trace(s"deleting from user profile ${deleteToken}")
    transaction.delete(deleteToken)


  }

The reason I was getting the exception despite adding get earlier was due to programming issues (mistakes in assigning variables correctly).尽管较早添加了get ,但我得到异常的原因是由于编程问题(正确分配变量时的错误)。 Say the delete was for record A but I hadn't stored A correctly but had stored it as A1 .假设删除是针对记录A但我没有正确存储A但已将其存储为A1 So the get was actually failing.所以get实际上失败了。

In general, I think this error means that the record being deleted doesn't exist.一般来说,我认为这个错误意味着被删除的记录不存在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM