diff --git a/src/storage/ls/ob_ls_tablet_service.cpp b/src/storage/ls/ob_ls_tablet_service.cpp index 00ce532658..aef82f7ef0 100644 --- a/src/storage/ls/ob_ls_tablet_service.cpp +++ b/src/storage/ls/ob_ls_tablet_service.cpp @@ -2798,6 +2798,26 @@ int ObLSTabletService::direct_insert_rows( return ret; } +int ObLSTabletService::mock_duplicated_rows_(common::ObNewRowIterator *&duplicated_rows) +{ + int ret = OB_SUCCESS; + ObValueRowIterator *dup_iter = NULL; + + if (OB_ISNULL(dup_iter = ObQueryIteratorFactory::get_insert_dup_iter())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("no memory to alloc ObValueRowIterator", K(ret)); + } else { + duplicated_rows = dup_iter; + if (OB_FAIL(dup_iter->init(true))) { + LOG_WARN("failed to initialize ObValueRowIterator", K(ret)); + ObQueryIteratorFactory::free_insert_dup_iter(duplicated_rows); + duplicated_rows = nullptr; + } + } + + return ret; +} + int ObLSTabletService::insert_row( ObTabletHandle &tablet_handle, ObStoreCtx &ctx, @@ -2845,12 +2865,35 @@ int ObLSTabletService::insert_row( duplicated_column_ids, tbl_row.row_val_, duplicated_rows))) { - LOG_WARN("failed to get conflict row(s)", K(ret), K(duplicated_column_ids), K(row)); + LOG_WARN("failed to get conflict row(s)", K(ret), K(duplicated_column_ids), K(row)); } else if (nullptr == duplicated_rows) { if (OB_FAIL(insert_row_to_tablet(tablet_handle, run_ctx, tbl_row))) { if (OB_TRY_LOCK_ROW_CONFLICT != ret) { LOG_WARN("failed to write row", K(ret)); } + + if (OB_ERR_PRIMARY_KEY_DUPLICATE == ret) { + int tmp_ret = OB_SUCCESS; + // For primary key conflicts caused by concurrent insertions within + // a statement, we need to return the corresponding duplicated_rows. + // However, under circumstances where an exception may unexpectedly + // prevent us from reading the conflicting rows within statements, + // at such times, it becomes necessary for us to mock the rows. + if (OB_TMP_FAIL(get_conflict_rows(tablet_handle, + run_ctx, + flag, + duplicated_column_ids, + tbl_row.row_val_, + duplicated_rows))) { + LOG_WARN("failed to get conflict row(s)", K(ret), K(duplicated_column_ids), K(row)); + ret = tmp_ret; + } else if (nullptr == duplicated_rows) { + if (OB_TMP_FAIL(mock_duplicated_rows_(duplicated_rows))) { + LOG_WARN("failed to mock duplicated row(s)", K(ret), K(duplicated_column_ids), K(row)); + ret = tmp_ret; + } + } + } } else { LOG_DEBUG("succeeded to insert row", K(ret), K(row)); affected_rows = 1; diff --git a/src/storage/ls/ob_ls_tablet_service.h b/src/storage/ls/ob_ls_tablet_service.h index 8995c51e83..3372bd3e2e 100644 --- a/src/storage/ls/ob_ls_tablet_service.h +++ b/src/storage/ls/ob_ls_tablet_service.h @@ -563,6 +563,7 @@ private: int offline_build_tablet_without_memtable_(); int offline_gc_tablet_for_create_or_transfer_in_abort_(); int offline_destroy_memtable_and_mds_table_(); + int mock_duplicated_rows_(common::ObNewRowIterator *&duplicated_rows); private: static int check_real_leader_for_4377_(const ObLSID ls_id); static int check_need_rollback_in_transfer_for_4377_(const transaction::ObTxDesc *tx_desc,