Skip to content

Commit

Permalink
fix:修复了mvcc模式下无法正确删除由当前事务插入的记录 (oceanbase#315)
Browse files Browse the repository at this point in the history
### What problem were solved in this pull request?

Issue Number: close oceanbase#314 
mvcc模式下无法正确删除当前事务插入的记录


### What is changed and how it works?

在trx.delete_record添加特判,如果是删除当前事务插入的记录,就直接调用delete_record,并且也不添加到operation_里面,同时清除operation里面的相关insert_operation,这样可以保证事务内、提交后、回滚后、都能正确执行,并且不影响垃圾回收
  • Loading branch information
Fischer0522 authored Nov 8, 2023
1 parent cec6a75 commit 98707ed
Showing 1 changed file with 19 additions and 1 deletion.
20 changes: 19 additions & 1 deletion src/observer/storage/trx/mvcc_trx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ RC MvccTrx::delete_record(Table * table, Record &record)
Field end_field;
trx_fields(table, begin_field, end_field);

int32_t begin_xid = begin_field.get_int(record);
[[maybe_unused]] int32_t end_xid = end_field.get_int(record);
/// 在删除之前,第一次获取record时,就已经对record做了对应的检查,并且保证不会有其它的事务来访问这条数据
ASSERT(end_xid > 0, "concurrency conflit: other transaction is updating this record. end_xid=%d, current trx id=%d, rid=%s",
Expand All @@ -179,8 +180,25 @@ RC MvccTrx::delete_record(Table * table, Record &record)
RC rc = log_manager_->append_log(CLogType::DELETE, trx_id_, table->table_id(), record.rid(), 0, 0, nullptr);
ASSERT(rc == RC::SUCCESS, "failed to append delete record log. trx id=%d, table id=%d, rid=%s, record len=%d, rc=%s",
trx_id_, table->table_id(), record.rid().to_string().c_str(), record.len(), strrc(rc));
if (begin_xid == -trx_id_) {
// fix:此处是为了修复由当前事务插入而又被当前事务删除时无法正确删除的问题:
// 在当前事务中创建的记录从来未对外暴露过,未来方便今后添加垃圾回收功能,这里选择直接删除真实记录
// 就认为记录从来未存在过,此时无论是commit还是rollback都能得到正确的结果,并且需要清空之前的insert operation,避免事务结束时执行
auto delete_operation = Operation{Operation::Type::INSERT, table, record.rid()};
std::unordered_set<Operation>::size_type delete_result = operations_.erase(delete_operation);
ASSERT(delete_result == 1, "failed to delete insert operation,begin_xid=%d, end_xid=%d, tid=%d, rid:%s",
begin_xid, end_xid, trx_id_, record.rid().to_string().c_str());
rc = table->delete_record(record);
ASSERT(rc == RC::SUCCESS, "failed to delete record in table.table id =%d, rid=%s, begin_xid=%d, end_xid=%d, current trx id = %d",
table.->table_id(), record.rid().to_string().c_str(), begin_xid, end_xid, trx_id_);
return rc;
}

operations_.insert(Operation(Operation::Type::DELETE, table, record.rid()));
pair<OperationSet::iterator, bool> ret = operations_.insert(Operation(Operation::Type::DELETE, table, record.rid()));
if (!ret.second) {
LOG_WARN("failed to insert operation(deletion) into operation set: duplicate");
return RC::INTERNAL;
}

return RC::SUCCESS;
}
Expand Down

0 comments on commit 98707ed

Please sign in to comment.