From 98707edaea392fdec5aa2d95020a50a2b01319af Mon Sep 17 00:00:00 2001 From: Fischer <89784872+Fischer0522@users.noreply.github.com> Date: Wed, 8 Nov 2023 20:33:25 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E4=BA=86mvcc=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E4=B8=8B=E6=97=A0=E6=B3=95=E6=AD=A3=E7=A1=AE=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E7=94=B1=E5=BD=93=E5=89=8D=E4=BA=8B=E5=8A=A1=E6=8F=92?= =?UTF-8?q?=E5=85=A5=E7=9A=84=E8=AE=B0=E5=BD=95=20(#315)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What problem were solved in this pull request? Issue Number: close #314 mvcc模式下无法正确删除当前事务插入的记录 ### What is changed and how it works? 在trx.delete_record添加特判,如果是删除当前事务插入的记录,就直接调用delete_record,并且也不添加到operation_里面,同时清除operation里面的相关insert_operation,这样可以保证事务内、提交后、回滚后、都能正确执行,并且不影响垃圾回收 --- src/observer/storage/trx/mvcc_trx.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/observer/storage/trx/mvcc_trx.cpp b/src/observer/storage/trx/mvcc_trx.cpp index 4488dcc5e..ecf06a974 100644 --- a/src/observer/storage/trx/mvcc_trx.cpp +++ b/src/observer/storage/trx/mvcc_trx.cpp @@ -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", @@ -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::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 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; }