You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org> on 2024/07/23 07:48:58 UTC
[PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
SWJTU-ZhangLei opened a new pull request, #38243:
URL: https://github.com/apache/doris/pull/38243
Motivation:
* In cloud mode we use `foundationdb` for storing rowset meta, when we load data with many rowsets, `commit_txn` will failed because `foundationdb` currently limits all transactions to be below 10 MB in size, So we spilt `commit_txn` into several sub fdb txn to solve the problem
How:
Now `commit_txn` main flow like this
sub txn 1:
1. update partition `VersionPB` with txn_id
2. submit async task to txn_lazy_committer
txn_lazy_committer:
sub txn 2:
convert tmp rowset meta per batch
sub txn 3:
convert tmp rowset meta per batch
......
sub txn n:
make txn visible and remove txn_id in `VersionPB`
## Proposed changes
Issue Number: close #xxx
<!--Describe your changes.-->
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2250316468
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2303572834
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2304052045
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1722772480
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -618,11 +649,13 @@ void MetaServiceImpl::create_tablets(::google::protobuf::RpcController* controll
msg = fmt::format("failed to get vault id, vault name={}", name);
return;
}
+ DCHECK(request->has_db_id());
Review Comment:
> What happens if the doris FE is the old version?
resolved
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1722772720
##########
be/src/cloud/config.h:
##########
@@ -94,4 +94,6 @@ DECLARE_mBool(save_load_error_log_to_s3);
// the theads which sync the datas which loaded in other clusters
DECLARE_mInt32(sync_load_for_tablets_thread);
+DECLARE_mBool(txn_lazy_commit);
Review Comment:
> Add `cloud_` prefix, and add a description too.
done, add a cloud_ prefix
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2285947238
<details>
<summary>TPC-H: <b>Total hot run time: 40429 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 814829fad0b51598e72ff1c3c1e78f4f3225389e, data reload: false
------ Round 1 ----------------------------------
q1 17927 4383 4316 4316
q2 2034 184 181 181
q3 11342 1034 1190 1034
q4 10523 790 698 698
q5 7747 2819 2828 2819
q6 222 137 138 137
q7 962 595 606 595
q8 9319 2056 2106 2056
q9 8828 6576 6546 6546
q10 7085 2259 2251 2251
q11 464 249 253 249
q12 392 224 223 223
q13 18735 3010 2985 2985
q14 292 249 235 235
q15 539 475 487 475
q16 643 521 525 521
q17 988 750 656 656
q18 8051 7523 7423 7423
q19 6588 1009 1034 1009
q20 724 419 408 408
q21 5449 4587 4631 4587
q22 1110 1042 1025 1025
Total cold run time: 119964 ms
Total hot run time: 40429 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4492 4280 4336 4280
q2 376 277 270 270
q3 3011 2854 2750 2750
q4 2054 1692 1706 1692
q5 5617 5563 5667 5563
q6 233 140 136 136
q7 2172 1823 1774 1774
q8 3340 3438 3442 3438
q9 8778 8897 8768 8768
q10 3435 3237 3308 3237
q11 625 512 518 512
q12 832 631 637 631
q13 17202 3159 3235 3159
q14 334 293 309 293
q15 534 478 516 478
q16 650 578 573 573
q17 1814 1566 1533 1533
q18 8127 8014 7944 7944
q19 1769 1511 1606 1511
q20 2322 1955 1962 1955
q21 5551 5243 5251 5243
q22 1225 1055 1049 1049
Total cold run time: 74493 ms
Total hot run time: 56789 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1730964155
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(recycle_key, recycle_val);
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+ }
+}
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
+ std::stringstream ss;
+ int retry_times = 0;
+ do {
+ LOG(INFO) << "lazy task commit txn_id=" << txn_id_ << " retry_times=" << retry_times;
+ do {
+ code_ = MetaServiceCode::OK;
+ msg_.clear();
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id_, txn_id_, txn_kv_, code_, msg_, &db_id, &tmp_rowset_metas);
+ if (code_ != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id_ << " code=" << code_;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id_
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id_;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
+ partition_to_tmp_rowset_metas;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].emplace_back();
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().first =
+ tmp_rowset_key;
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().second =
+ tmp_rowset_pb;
+ }
+
+ // tablet_id -> TabletIndexPB
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ for (auto& [partition_id, tmp_rowset_metas] : partition_to_tmp_rowset_metas) {
+ for (size_t i = 0; i < tmp_rowset_metas.size();
+ i += config::txn_lazy_max_rowsets_per_batch) {
+ size_t end =
+ (i + config::txn_lazy_max_rowsets_per_batch) > tmp_rowset_metas.size()
+ ? tmp_rowset_metas.size()
+ : i + config::txn_lazy_max_rowsets_per_batch;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>
+ sub_partition_tmp_rowset_metas(tmp_rowset_metas.begin() + i,
+ tmp_rowset_metas.begin() + end);
+ convert_tmp_rowsets(instance_id_, txn_id_, txn_kv_, code_, msg_, db_id,
+ sub_partition_tmp_rowset_metas, tablet_ids);
+ if (code_ != MetaServiceCode::OK) break;
+ }
+ if (code_ != MetaServiceCode::OK) break;
+
+ DCHECK(tmp_rowset_metas.size() > 0);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code_ = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id_ << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+
+ int64_t table_id = -1;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ if (table_id <= 0) {
+ table_id = tablet_ids[tmp_rowset_pb.tablet_id()].table_id();
+ }
+ txn->remove(tmp_rowset_key);
+ }
+
+ DCHECK(table_id > 0);
+ DCHECK(partition_id > 0);
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id_, db_id, table_id, partition_id});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code_ = err == TxnErrorCode::TXN_KEY_NOT_FOUND
+ ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id_
+ << " key=" << hex(ver_key) << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id_
+ << " key=" << hex(ver_key);
+ msg_ = ss.str();
+ break;
+ }
+
+ if (version_pb.has_txn_id() && version_pb.txn_id() == txn_id_) {
+ version_pb.clear_txn_id();
+ ver_val.clear();
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id_;
+ msg_ = ss.str();
+ return;
+ }
+ txn->put(ver_key, ver_val);
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code_ = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id_ << " err=" << err;
+ msg_ = ss.str();
+ break;
+ }
+ }
+ }
+ make_committed_txn_visible(instance_id_, db_id, txn_id_, txn_kv_, code_, msg_);
+ } while (false);
+ } while (code_ == MetaServiceCode::KV_TXN_CONFLICT &&
+ retry_times++ < config::txn_store_retry_times);
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ this->finished_ = true;
Review Comment:
> do we count it as a finish even if `retry_times > config::txn_store_retry_times`? line 413 may be false and make it reach here.
Add more log about code and retry times
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1732725106
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(recycle_key, recycle_val);
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+ }
+}
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
+ std::stringstream ss;
+ int retry_times = 0;
+ do {
+ LOG(INFO) << "lazy task commit txn_id=" << txn_id_ << " retry_times=" << retry_times;
+ do {
+ code_ = MetaServiceCode::OK;
+ msg_.clear();
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id_, txn_id_, txn_kv_, code_, msg_, &db_id, &tmp_rowset_metas);
+ if (code_ != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id_ << " code=" << code_;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id_
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
Review Comment:
> how come `tmp_rowset_metas.size() == 0` may exist?
multi ms, other ms finish lazy task
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2283325550
<details>
<summary>TPC-H: <b>Total hot run time: 39545 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 80ae9bdb333044199b702c9462b10d660e2aa26c, data reload: false
------ Round 1 ----------------------------------
q1 18420 4477 4342 4342
q2 2027 226 209 209
q3 11388 1066 1125 1066
q4 10525 756 678 678
q5 7507 2594 2578 2578
q6 223 137 133 133
q7 960 594 595 594
q8 9220 1924 1964 1924
q9 8804 6595 6603 6595
q10 7000 2187 2178 2178
q11 450 238 249 238
q12 395 229 229 229
q13 18926 3003 2991 2991
q14 286 241 242 241
q15 536 476 493 476
q16 616 530 514 514
q17 989 665 644 644
q18 8133 7642 7347 7347
q19 6246 1070 1070 1070
q20 774 421 419 419
q21 5653 4444 4080 4080
q22 1098 999 1010 999
Total cold run time: 120176 ms
Total hot run time: 39545 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4537 4252 4264 4252
q2 397 274 276 274
q3 2906 2764 2851 2764
q4 2021 1718 1686 1686
q5 5498 5501 5429 5429
q6 225 133 131 131
q7 2198 1781 1774 1774
q8 3272 3421 3444 3421
q9 8707 8869 8800 8800
q10 3495 3193 3283 3193
q11 614 514 510 510
q12 821 690 645 645
q13 17081 3110 3171 3110
q14 310 286 298 286
q15 526 499 481 481
q16 646 562 574 562
q17 1872 1564 1524 1524
q18 8143 7994 7749 7749
q19 4278 1575 1648 1575
q20 2253 1980 1913 1913
q21 5521 5221 5325 5221
q22 1136 1060 1034 1034
Total cold run time: 76457 ms
Total hot run time: 56334 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1732486494
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,471 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ // tmp rowset key has been converted
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
Review Comment:
warning: function 'make_committed_txn_visible' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:197:** 82 lines including whitespace and comments (threshold 80)
```cpp
void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
^
```
</details>
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -403,9 +419,9 @@ void MetaServiceImpl::batch_get_version(::google::protobuf::RpcController* contr
}
}
-void internal_create_tablet(MetaServiceCode& code, std::string& msg,
- const doris::TabletMetaCloudPB& meta, std::shared_ptr<TxnKv> txn_kv,
- const std::string& instance_id,
+void internal_create_tablet(const CreateTabletsRequest* request, MetaServiceCode& code,
Review Comment:
warning: function 'internal_create_tablet' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void internal_create_tablet(const CreateTabletsRequest* request, MetaServiceCode& code,
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/meta_service.cpp:421:** 130 lines including whitespace and comments (threshold 80)
```cpp
void internal_create_tablet(const CreateTabletsRequest* request, MetaServiceCode& code,
^
```
</details>
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,471 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
Review Comment:
warning: function 'convert_tmp_rowsets' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void convert_tmp_rowsets(
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:40:** 151 lines including whitespace and comments (threshold 80)
```cpp
void convert_tmp_rowsets(
^
```
</details>
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,471 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ // tmp rowset key has been converted
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(recycle_key, recycle_val);
+ LOG(INFO) << "put recycle_key=" << hex(recycle_key) << " txn_id=" << txn_id;
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+ }
+}
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
Review Comment:
warning: function 'commit' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void TxnLazyCommitTask::commit() {
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:293:** 137 lines including whitespace and comments (threshold 80)
```cpp
void TxnLazyCommitTask::commit() {
^
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "gavinchou (via GitHub)" <gi...@apache.org>.
gavinchou commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1713020176
##########
cloud/src/common/config.h:
##########
@@ -201,4 +201,8 @@ CONF_Validator(s3_client_http_scheme, [](const std::string& config) -> bool {
// Max retry times for object storage request
CONF_mInt64(max_s3_client_retry, "10");
+CONF_Bool(enable_txn_lazy_commit, "true");
+CONF_Int32(txn_lazy_commit_rowsets_thresold, "1024");
+CONF_Int32(txn_lazy_commit_worker_num, "8");
Review Comment:
naming `txn_lazy_commit_num_threads`
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2259595020
<details>
<summary>ClickBench: <b>Total hot run time: 30.16 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 8ed44221f04cb0a14f7132c207fbd3cf93e572f1, data reload: false
query1 0.04 0.03 0.03
query2 0.07 0.04 0.04
query3 0.22 0.05 0.05
query4 1.67 0.07 0.07
query5 0.50 0.49 0.48
query6 1.15 0.71 0.71
query7 0.02 0.01 0.01
query8 0.06 0.04 0.05
query9 0.56 0.52 0.52
query10 0.57 0.56 0.56
query11 0.16 0.13 0.12
query12 0.15 0.12 0.14
query13 0.61 0.60 0.60
query14 0.78 0.78 0.82
query15 0.90 0.86 0.86
query16 0.37 0.36 0.36
query17 1.00 1.00 0.97
query18 0.23 0.21 0.22
query19 1.83 1.74 1.77
query20 0.01 0.00 0.01
query21 15.40 0.77 0.66
query22 4.67 6.67 1.31
query23 17.94 1.31 1.31
query24 2.29 0.22 0.22
query25 0.19 0.09 0.08
query26 0.32 0.22 0.21
query27 0.45 0.23 0.23
query28 13.16 0.99 0.97
query29 12.62 3.35 3.32
query30 0.26 0.06 0.06
query31 2.86 0.40 0.41
query32 3.25 0.50 0.47
query33 2.96 2.96 3.03
query34 15.47 4.31 4.27
query35 4.30 4.31 4.34
query36 0.68 0.49 0.49
query37 0.19 0.16 0.17
query38 0.16 0.16 0.16
query39 0.05 0.04 0.04
query40 0.17 0.13 0.13
query41 0.10 0.04 0.05
query42 0.06 0.06 0.05
query43 0.05 0.05 0.04
Total cold run time: 108.5 s
Total hot run time: 30.16 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2260550318
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1708565487
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -917,320 +1461,418 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
- msg = ss.str();
- return;
- }
- version = version_pb.version();
- } else {
- version = 1;
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
}
- new_versions[version_keys[i]] = version + 1;
+ txn->put(recycle_key, recycle_val);
}
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ err = txn->commit();
Review Comment:
> No need to commit if this TXN is in TXN_STATUS_VISIBLE
done
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,208 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
+ std::stringstream ss;
+ do {
+ code_ = MetaServiceCode::OK;
+ msg_.clear();
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id_, txn_id_, txn_kv_, code_, msg_, &db_id, &tmp_rowset_metas);
+ if (code_ != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id_ << " code=" << code_;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id_
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id_;
+ break;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t, std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
+ partition_to_tmp_rowset_metas;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].emplace_back();
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().first =
+ tmp_rowset_key;
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().second =
+ tmp_rowset_pb;
+ }
+
+ // tablet_id -> TabletIndexPB
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ for (auto& [partition_id, tmp_rowset_metas] : partition_to_tmp_rowset_metas) {
+ for (size_t i = 0; i < tmp_rowset_metas.size();
+ i += config::txn_lazy_max_rowsets_per_batch) {
+ size_t end = (i + config::txn_lazy_max_rowsets_per_batch) > tmp_rowset_metas.size()
+ ? tmp_rowset_metas.size()
+ : i + config::txn_lazy_max_rowsets_per_batch;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>
+ sub_partition_tmp_rowset_metas(tmp_rowset_metas.begin() + i,
+ tmp_rowset_metas.begin() + end);
+ convert_tmp_rowsets(instance_id_, txn_id_, txn_kv_, code_, msg_, db_id,
+ sub_partition_tmp_rowset_metas, tablet_ids);
+ if (code_ != MetaServiceCode::OK) break;
+ }
+ if (code_ != MetaServiceCode::OK) break;
+
+ DCHECK(tmp_rowset_metas.size() > 0);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code_ = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id_ << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+
+ int64_t table_id = -1;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ if (table_id <= 0) {
+ table_id = tablet_ids[tmp_rowset_pb.tablet_id()].table_id();
+ }
+ txn->remove(tmp_rowset_key);
+ }
+
+ DCHECK(table_id > 0);
+ DCHECK(partition_id > 0);
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id_, db_id, table_id, partition_id});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code_ = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id_
+ << " key=" << hex(ver_key) << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id_ << " key=" << hex(ver_key);
+ msg_ = ss.str();
+ break;
+ }
+
+ if (version_pb.has_txn_id() && version_pb.txn_id() == txn_id_) {
+ version_pb.clear_txn_id();
+ ver_val.clear();
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id_;
+ msg_ = ss.str();
+ return;
+ }
+ txn->put(ver_key, ver_val);
+ }
+
+ err = txn->commit();
Review Comment:
> No need to commit if `version_pb.has_txn_id() && version_pb.txn_id() == txn_id_` is false.
done
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2283493319
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1724473528
##########
cloud/test/txn_lazy_commit_test.cpp:
##########
@@ -0,0 +1,214 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <brpc/controller.h>
+#include <bvar/window.h>
+#include <fmt/core.h>
+#include <gen_cpp/cloud.pb.h>
+#include <gen_cpp/olap_file.pb.h>
+#include <google/protobuf/repeated_field.h>
+#include <gtest/gtest.h>
+
+#include <atomic>
+#include <condition_variable>
+#include <cstdint>
+#include <memory>
+#include <random>
+#include <string>
+#include <thread>
+
+#include "common/config.h"
+#include "common/logging.h"
+#include "common/util.h"
+#include "cpp/sync_point.h"
+#include "meta-service/keys.h"
+#include "meta-service/mem_txn_kv.h"
+#include "meta-service/meta_service.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/txn_kv_error.h"
+#include "mock_resource_manager.h"
+#include "rate-limiter/rate_limiter.h"
+#include "resource-manager/resource_manager.h"
+
+int main(int argc, char** argv) {
+ const std::string conf_file = "doris_cloud.conf";
+ if (!doris::cloud::config::init(conf_file.c_str(), true)) {
+ std::cerr << "failed to init config file, conf=" << conf_file << std::endl;
+ return -1;
+ }
+
+ config::enable_txn_lazy_commit = true;
+ config::txn_lazy_commit_rowsets_thresold = 1;
+ config::txn_lazy_max_rowsets_per_batch = 1;
+ config::txn_lazy_commit_num_threads = 2;
+
+ if (!doris::cloud::init_glog("txn_lazy_commit_test")) {
+ std::cerr << "failed to init glog" << std::endl;
+ return -1;
+ }
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+namespace doris::cloud {
+
+std::unique_ptr<MetaServiceProxy> get_meta_service(std::shared_ptr<TxnKv> txn_kv,
+ bool mock_resource_mgr) {
+ std::unique_ptr<Transaction> txn;
+ EXPECT_EQ(txn_kv->create_txn(&txn), TxnErrorCode::TXN_OK);
+ txn->remove("\x00", "\xfe"); // This is dangerous if the fdb is not correctly set
+ EXPECT_EQ(txn->commit(), TxnErrorCode::TXN_OK);
+
+ auto rs = mock_resource_mgr ? std::make_shared<MockResourceManager>(txn_kv)
+ : std::make_shared<ResourceManager>(txn_kv);
+ auto rl = std::make_shared<RateLimiter>();
+ auto meta_service = std::make_unique<MetaServiceImpl>(txn_kv, rs, rl);
+ return std::make_unique<MetaServiceProxy>(std::move(meta_service));
+}
+
+static std::string next_rowset_id() {
+ static int cnt = 0;
+ return std::to_string(++cnt);
+}
+
+static void add_tablet(CreateTabletsRequest& req, int64_t table_id, int64_t index_id,
+ int64_t partition_id, int64_t tablet_id) {
+ auto tablet = req.add_tablet_metas();
+ tablet->set_table_id(table_id);
+ tablet->set_index_id(index_id);
+ tablet->set_partition_id(partition_id);
+ tablet->set_tablet_id(tablet_id);
+ auto schema = tablet->mutable_schema();
+ schema->set_schema_version(0);
+ auto first_rowset = tablet->add_rs_metas();
+ first_rowset->set_rowset_id(0); // required
+ first_rowset->set_rowset_id_v2(next_rowset_id());
+ first_rowset->set_start_version(0);
+ first_rowset->set_end_version(1);
+ first_rowset->mutable_tablet_schema()->CopyFrom(*schema);
+}
+
+static void create_tablet(MetaServiceProxy* meta_service, int64_t table_id, int64_t index_id,
+ int64_t partition_id, int64_t tablet_id) {
+ brpc::Controller cntl;
+ CreateTabletsRequest req;
+ CreateTabletsResponse res;
+ add_tablet(req, table_id, index_id, partition_id, tablet_id);
+ meta_service->create_tablets(&cntl, &req, &res, nullptr);
+ ASSERT_EQ(res.status().code(), MetaServiceCode::OK) << tablet_id;
+}
+
+static doris::RowsetMetaCloudPB create_rowset(int64_t txn_id, int64_t tablet_id,
+ int partition_id = 10, int64_t version = -1,
+ int num_rows = 100) {
+ doris::RowsetMetaCloudPB rowset;
+ rowset.set_rowset_id(0); // required
+ rowset.set_rowset_id_v2(next_rowset_id());
+ rowset.set_tablet_id(tablet_id);
+ rowset.set_partition_id(partition_id);
+ rowset.set_txn_id(txn_id);
+ if (version > 0) {
+ rowset.set_start_version(version);
+ rowset.set_end_version(version);
+ }
+ rowset.set_num_segments(1);
+ rowset.set_num_rows(num_rows);
+ rowset.set_data_disk_size(num_rows * 100);
+ rowset.mutable_tablet_schema()->set_schema_version(0);
+ rowset.set_txn_expiration(::time(nullptr)); // Required by DCHECK
+ return rowset;
+}
+
+static void commit_rowset(MetaServiceProxy* meta_service, const doris::RowsetMetaCloudPB& rowset,
+ CreateRowsetResponse& res) {
+ brpc::Controller cntl;
+ auto arena = res.GetArena();
+ auto req = google::protobuf::Arena::CreateMessage<CreateRowsetRequest>(arena);
+ req->mutable_rowset_meta()->CopyFrom(rowset);
+ meta_service->commit_rowset(&cntl, req, &res, nullptr);
+ if (!arena) delete req;
Review Comment:
warning: statement should be inside braces [readability-braces-around-statements]
```suggestion
if (!arena) { delete req;
}
```
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -403,9 +434,9 @@ void MetaServiceImpl::batch_get_version(::google::protobuf::RpcController* contr
}
}
-void internal_create_tablet(MetaServiceCode& code, std::string& msg,
- const doris::TabletMetaCloudPB& meta, std::shared_ptr<TxnKv> txn_kv,
- const std::string& instance_id,
+void internal_create_tablet(const CreateTabletsRequest* request, MetaServiceCode& code,
Review Comment:
warning: function 'internal_create_tablet' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void internal_create_tablet(const CreateTabletsRequest* request, MetaServiceCode& code,
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/meta_service.cpp:436:** 130 lines including whitespace and comments (threshold 80)
```cpp
void internal_create_tablet(const CreateTabletsRequest* request, MetaServiceCode& code,
^
```
</details>
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(recycle_key, recycle_val);
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+ }
+}
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
Review Comment:
warning: function 'commit' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void TxnLazyCommitTask::commit() {
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:292:** 126 lines including whitespace and comments (threshold 80)
```cpp
void TxnLazyCommitTask::commit() {
^
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2298087733
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2296748712
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2298398447
<details>
<summary>TPC-DS: <b>Total hot run time: 196613 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 1d63b327147196a6029b3421305f1eed1a00dc18, data reload: false
query1 1302 889 891 889
query2 6558 2012 1940 1940
query3 10662 3872 3599 3599
query4 56834 23811 23250 23250
query5 5779 730 727 727
query6 556 215 210 210
query7 6406 334 337 334
query8 558 438 440 438
query9 9321 2531 2518 2518
query10 588 349 340 340
query11 17888 14983 15301 14983
query12 200 147 146 146
query13 1705 488 448 448
query14 11903 6914 7511 6914
query15 260 201 204 201
query16 7505 554 529 529
query17 1182 606 623 606
query18 2028 352 339 339
query19 308 174 172 172
query20 156 139 136 136
query21 259 148 143 143
query22 5026 4640 4638 4638
query23 34688 33877 33919 33877
query24 5698 3005 3003 3003
query25 585 432 427 427
query26 721 183 188 183
query27 1867 306 307 306
query28 4045 2187 2179 2179
query29 718 457 451 451
query30 233 184 204 184
query31 1037 851 792 792
query32 97 75 80 75
query33 545 355 340 340
query34 903 502 493 493
query35 858 770 781 770
query36 1096 997 968 968
query37 156 104 103 103
query38 3898 3968 3902 3902
query39 1537 1500 1455 1455
query40 237 157 151 151
query41 139 138 138 138
query42 133 114 116 114
query43 528 505 504 504
query44 1114 781 789 781
query45 231 197 197 197
query46 1112 795 781 781
query47 1912 1858 1872 1858
query48 406 332 333 332
query49 937 598 577 577
query50 863 466 475 466
query51 7192 7230 7107 7107
query52 120 109 105 105
query53 296 228 229 228
query54 617 503 497 497
query55 89 87 90 87
query56 330 313 312 312
query57 1207 1141 1124 1124
query58 295 311 306 306
query59 2885 2791 2861 2791
query60 345 330 323 323
query61 149 146 147 146
query62 791 689 672 672
query63 259 234 228 228
query64 3388 1882 1862 1862
query65 3272 3184 3201 3184
query66 1032 696 667 667
query67 15332 15027 15052 15027
query68 5210 586 580 580
query69 643 310 315 310
query70 1217 1211 1161 1161
query71 544 311 313 311
query72 7683 2379 2084 2084
query73 820 356 356 356
query74 9368 8968 8854 8854
query75 4506 2781 2756 2756
query76 3458 1053 1100 1053
query77 839 440 425 425
query78 10020 9154 9219 9154
query79 7492 556 556 556
query80 1423 600 618 600
query81 621 268 265 265
query82 1222 156 157 156
query83 402 210 207 207
query84 302 97 97 97
query85 1250 358 360 358
query86 455 317 325 317
query87 4393 4288 4138 4138
query88 5536 2465 2476 2465
query89 445 328 325 325
query90 2127 230 237 230
query91 150 127 126 126
query92 86 77 77 77
query93 6062 551 556 551
query94 971 321 326 321
query95 383 300 298 298
query96 624 287 287 287
query97 3211 3144 3111 3111
query98 239 226 223 223
query99 1571 1288 1318 1288
Total cold run time: 334150 ms
Total hot run time: 196613 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1732235705
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
msg = ss.str();
return;
}
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
- std::string_view ver_key = i.first;
- ver_key.remove_prefix(1); // Remove key space
- // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- int ret = decode_key(&ver_key, &out);
- if (ret != 0) [[unlikely]] {
- // decode version key error means this is something wrong,
- // we can not continue this txn
- LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = "decode version key error";
- return;
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
}
- int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
- int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
- VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+ // save versions for partition
+ int64_t version_update_time_ms =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ response->set_version_update_time_ms(version_update_time_ms);
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_txn_id(txn_id);
+ version_pb.set_update_time_ms(version_update_time_ms);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- response->add_table_ids(table_id);
- response->add_partition_ids(partition_id);
- response->add_versions(i.second);
- }
+ txn->put(i.first, ver_val);
+ LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
+ << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+
+ std::string_view ver_key = i.first;
+ ver_key.remove_prefix(1); // Remove key space
+ // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
+ int ret = decode_key(&ver_key, &out);
+ if (ret != 0) [[unlikely]] {
+ // decode version key error means this is something wrong,
+ // we can not continue this txn
+ LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = "decode version key error";
+ return;
+ }
- // Save table versions
- for (auto& i : table_id_tablet_ids) {
- std::string ver_key = table_version_key({instance_id, db_id, i.first});
- txn->atomic_add(ver_key, 1);
- LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key) << " txn_id=" << txn_id;
- }
+ int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
+ int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
+ VLOG_DEBUG << "txn_id=" << txn_id << " table_id=" << table_id
+ << " partition_id=" << partition_id << " version=" << i.second;
- LOG(INFO) << " before update txn_info=" << txn_info.ShortDebugString();
+ response->add_table_ids(table_id);
+ response->add_partition_ids(partition_id);
+ response->add_versions(i.second);
+ }
- // Update txn_info
- txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ // process mow table, check lock and remove pending key
+ std::vector<std::string> lock_keys;
+ lock_keys.reserve(request->mow_table_ids().size());
+ for (auto table_id : request->mow_table_ids()) {
+ lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
+ }
+ std::vector<std::optional<std::string>> lock_values;
+ err = txn->batch_get(&lock_values, lock_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
+ << " err=" << err;
+ msg = ss.str();
+ code = cast_as<ErrCategory::READ>(err);
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- auto now_time = system_clock::now();
- uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
- if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
- LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
- << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
- return;
- }
- txn_info.set_commit_time(commit_time);
- txn_info.set_finish_time(commit_time);
- if (request->has_commit_attachment()) {
- txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
- }
- LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
- info_val.clear();
- if (!txn_info.SerializeToString(&info_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(info_key, info_val);
- LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+ for (size_t i = 0; i < lock_keys.size(); i++) {
+ int64_t table_id = request->mow_table_ids(i);
+ // When the key does not exist, it means the lock has been acquired
+ // by another transaction and successfully committed.
+ if (!lock_values[i].has_value()) {
+ ss << "get delete bitmap update lock info, lock is expired"
+ << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
+ code = MetaServiceCode::LOCK_EXPIRED;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- // Update stats of affected tablet
- for (auto& [tablet_id, stats] : tablet_stats) {
- DCHECK(tablet_ids.count(tablet_id));
- auto& tablet_idx = tablet_ids[tablet_id];
- StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
- tablet_idx.partition_id(), tablet_id};
- update_tablet_stats(info, stats, txn, code, msg);
- if (code != MetaServiceCode::OK) return;
- }
- // Remove tmp rowset meta
- for (auto& [k, _] : tmp_rowsets_meta) {
- txn->remove(k);
- LOG(INFO) << "xxx remove tmp_rowset_key=" << hex(k) << " txn_id=" << txn_id;
- }
+ DeleteBitmapUpdateLockPB lock_info;
+ if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "failed to parse DeleteBitmapUpdateLockPB";
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ if (lock_info.lock_id() != request->txn_id()) {
+ msg = "lock is expired";
+ code = MetaServiceCode::LOCK_EXPIRED;
+ return;
+ }
+ txn->remove(lock_keys[i]);
+ LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
+ << " txn_id=" << txn_id;
- const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
- LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
- txn->remove(running_key);
+ for (auto tablet_id : table_id_tablet_ids[table_id]) {
+ std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
+ txn->remove(pending_key);
+ LOG(INFO) << "xxx remove delete bitmap pending key, pending_key="
+ << hex(pending_key) << " txn_id=" << txn_id;
+ }
+ }
+ lock_keys.clear();
+ lock_values.clear();
- std::string recycle_val;
- std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
- RecycleTxnPB recycle_pb;
- recycle_pb.set_creation_time(commit_time);
- recycle_pb.set_label(txn_info.label());
+ // Save table versions
+ for (auto& i : table_id_tablet_ids) {
+ std::string ver_key = table_version_key({instance_id, db_id, i.first});
+ txn->atomic_add(ver_key, 1);
+ LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key)
+ << " txn_id=" << txn_id;
+ }
- if (!recycle_pb.SerializeToString(&recycle_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(recycle_key, recycle_val);
+ LOG(INFO) << "commit_txn_eventually put_size=" << txn->put_bytes()
+ << " del_size=" << txn->delete_bytes() << " num_put_keys=" << txn->num_put_keys()
+ << " num_del_keys=" << txn->num_del_keys()
+ << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
- if (txn_info.load_job_source_type() ==
- LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
- put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
- }
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
- LOG(INFO) << "xxx commit_txn put recycle_key key=" << hex(recycle_key) << " txn_id=" << txn_id;
- LOG(INFO) << "commit_txn put_size=" << txn->put_bytes() << " del_size=" << txn->delete_bytes()
- << " num_put_keys=" << txn->num_put_keys() << " num_del_keys=" << txn->num_del_keys()
- << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
+ std::shared_ptr<TxnLazyCommitTask> task = txn_lazy_committer->submit(instance_id, txn_id);
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ if (ret.first != MetaServiceCode::OK) {
+ LOG(WARNING) << "lazy commit txn failed txn_id=" << txn_id << " code=" << ret.first
+ << "msg=" << ret.second;
+ }
- // Finally we are done...
- err = txn->commit();
- if (err != TxnErrorCode::TXN_OK) {
- if ((err == TxnErrorCode::TXN_VALUE_TOO_LARGE ||
- err == TxnErrorCode::TXN_BYTES_TOO_LARGE) &&
- !tmp_rowsets_meta.empty()) {
- size_t max_size = 0, max_idx = 0, max_num_segments = 0,
- min_num_segments = std::numeric_limits<size_t>::max(), avg_num_segments = 0;
- for (size_t i = 0; i < tmp_rowsets_meta.size(); i++) {
- auto& [k, v] = tmp_rowsets_meta[i];
- if (v.ByteSizeLong() > max_size) {
- max_size = v.ByteSizeLong();
- max_idx = i;
- }
- if (v.num_segments() > max_num_segments) {
- max_num_segments = v.num_segments();
- }
- if (v.num_segments() < min_num_segments) {
- min_num_segments = v.num_segments();
- }
- avg_num_segments += v.num_segments();
- }
- if (!tmp_rowsets_meta.empty()) {
- avg_num_segments /= tmp_rowsets_meta.size();
- }
- LOG(WARNING) << "failed to commit kv txn"
- << ", err=" << err << ", txn_id=" << txn_id
- << ", total_rowsets=" << tmp_rowsets_meta.size()
- << ", avg_num_segments=" << avg_num_segments
- << ", min_num_segments=" << min_num_segments
- << ", max_num_segments=" << max_num_segments
- << ", largest_rowset_size=" << max_size
- << ", largest_rowset_key=" << hex(tmp_rowsets_meta[max_idx].first)
- << ", largest_rowset_value="
- << tmp_rowsets_meta[max_idx].second.ShortDebugString();
+ std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ // Accumulate affected rows
+ auto& stats = tablet_stats[i.tablet_id()];
+ stats.data_size += i.data_disk_size();
+ stats.num_rows += i.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += i.num_segments();
}
- code = cast_as<ErrCategory::COMMIT>(err);
- ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- return;
- }
- // calculate table stats from tablets stats
- std::map<int64_t /*table_id*/, TableStats> table_stats;
- std::vector<int64_t> base_tablet_ids(request->base_tablet_ids().begin(),
- request->base_tablet_ids().end());
- calc_table_stats(tablet_ids, tablet_stats, table_stats, base_tablet_ids);
- for (const auto& pair : table_stats) {
- TableStatsPB* stats_pb = response->add_table_stats();
- auto table_id = pair.first;
- auto stats = pair.second;
- get_pb_from_tablestats(stats, stats_pb);
- stats_pb->set_table_id(table_id);
- VLOG_DEBUG << "Add TableStats to CommitTxnResponse. txn_id=" << txn_id
- << " table_id=" << table_id
- << " updated_row_count=" << stats_pb->updated_row_count();
- }
+ // calculate table stats from tablets stats
+ std::map<int64_t /*table_id*/, TableStats> table_stats;
+ std::vector<int64_t> base_tablet_ids(request->base_tablet_ids().begin(),
+ request->base_tablet_ids().end());
+ calc_table_stats(tablet_ids, tablet_stats, table_stats, base_tablet_ids);
+ for (const auto& pair : table_stats) {
+ TableStatsPB* stats_pb = response->add_table_stats();
+ auto table_id = pair.first;
+ auto stats = pair.second;
+ get_pb_from_tablestats(stats, stats_pb);
+ stats_pb->set_table_id(table_id);
+ VLOG_DEBUG << "Add TableStats to CommitTxnResponse. txn_id=" << txn_id
+ << " table_id=" << table_id
+ << " updated_row_count=" << stats_pb->updated_row_count();
+ }
- response->mutable_txn_info()->CopyFrom(txn_info);
-} // end commit_txn
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
Review Comment:
> add comment to describe why it is OK to set VISIBLE
Add a comment, this is used for fe callback
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2312796154
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "gavinchou (via GitHub)" <gi...@apache.org>.
gavinchou commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1730632559
##########
cloud/src/recycler/recycler.cpp:
##########
@@ -1843,11 +1997,12 @@ int InstanceRecycler::scan_and_recycle(
return ret;
}
-int InstanceRecycler::abort_timeout_txn() {
- const std::string task_name = "abort_timeout_txn";
+int InstanceRecycler::advance_pending_txn() {
Review Comment:
keep the old name
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2314623553
<details>
<summary>TPC-H: <b>Total hot run time: 38018 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 0f6412f7fa9a90fc50e6af06a04d4e9b42655491, data reload: false
------ Round 1 ----------------------------------
q1 18641 6512 4348 4348
q2 2027 187 175 175
q3 11731 927 1167 927
q4 10429 762 784 762
q5 7734 2851 2828 2828
q6 227 139 135 135
q7 978 612 597 597
q8 9340 2102 2094 2094
q9 7220 6535 6556 6535
q10 6999 2273 2219 2219
q11 466 249 255 249
q12 401 224 228 224
q13 18090 3009 3042 3009
q14 284 241 242 241
q15 518 481 490 481
q16 575 510 521 510
q17 991 676 713 676
q18 7504 6750 6894 6750
q19 1404 1097 979 979
q20 690 333 333 333
q21 3979 3097 2923 2923
q22 1134 1023 1040 1023
Total cold run time: 111362 ms
Total hot run time: 38018 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4371 4339 4267 4267
q2 373 274 269 269
q3 2889 2698 2647 2647
q4 1904 1722 1698 1698
q5 5698 5689 5758 5689
q6 223 131 131 131
q7 2224 1826 1851 1826
q8 3287 3449 3521 3449
q9 8854 8835 8861 8835
q10 3619 3413 3347 3347
q11 592 521 496 496
q12 847 661 670 661
q13 14093 3119 3253 3119
q14 339 289 289 289
q15 540 499 477 477
q16 625 590 576 576
q17 1871 1533 1486 1486
q18 8244 7927 7923 7923
q19 1758 1675 1565 1565
q20 2186 1876 1935 1876
q21 5852 5440 5415 5415
q22 1151 1091 1077 1077
Total cold run time: 71540 ms
Total hot run time: 57118 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2314663277
<details>
<summary>ClickBench: <b>Total hot run time: 32.53 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 0f6412f7fa9a90fc50e6af06a04d4e9b42655491, data reload: false
query1 0.05 0.04 0.04
query2 0.08 0.03 0.04
query3 0.23 0.05 0.04
query4 1.68 0.07 0.07
query5 0.49 0.48 0.50
query6 1.13 0.72 0.73
query7 0.02 0.01 0.01
query8 0.06 0.04 0.04
query9 0.55 0.49 0.49
query10 0.55 0.54 0.54
query11 0.15 0.12 0.12
query12 0.15 0.12 0.11
query13 0.62 0.60 0.59
query14 2.02 2.07 2.10
query15 0.84 0.83 0.83
query16 0.38 0.36 0.37
query17 0.98 0.98 1.02
query18 0.20 0.20 0.20
query19 1.84 1.81 1.77
query20 0.01 0.01 0.01
query21 15.40 0.67 0.66
query22 4.64 6.18 2.61
query23 18.29 1.32 1.25
query24 2.10 0.22 0.23
query25 0.15 0.08 0.08
query26 0.28 0.18 0.17
query27 0.08 0.08 0.07
query28 13.25 1.02 0.99
query29 12.59 3.35 3.30
query30 0.24 0.06 0.05
query31 2.86 0.39 0.40
query32 3.27 0.48 0.47
query33 2.98 2.93 3.03
query34 17.29 4.35 4.41
query35 4.47 4.49 4.41
query36 0.66 0.48 0.47
query37 0.19 0.17 0.15
query38 0.16 0.15 0.15
query39 0.05 0.04 0.04
query40 0.15 0.12 0.12
query41 0.10 0.06 0.06
query42 0.06 0.05 0.06
query43 0.05 0.04 0.04
Total cold run time: 111.34 s
Total hot run time: 32.53 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1732711244
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
Review Comment:
> add comment what does it do and why
done
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1732716284
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,478 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
Review Comment:
warning: function 'convert_tmp_rowsets' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void convert_tmp_rowsets(
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:40:** 158 lines including whitespace and comments (threshold 80)
```cpp
void convert_tmp_rowsets(
^
```
</details>
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,478 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+ DCHECK(version_pb.txn_ids_size() > 0);
+ DCHECK_EQ(version_pb.txn_ids(0), txn_id);
+ int64_t version = 0;
+ if (version_pb.has_version()) {
+ version = version_pb.version() + 1;
+ } else {
+ version = 2;
+ }
+
+ std::string rowset_key = meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ // tmp rowset key has been converted
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version);
+ tmp_rowset_pb.set_end_version(version);
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
Review Comment:
warning: function 'make_committed_txn_visible' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:204:** 82 lines including whitespace and comments (threshold 80)
```cpp
void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
^
```
</details>
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,478 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+ DCHECK(version_pb.txn_ids_size() > 0);
+ DCHECK_EQ(version_pb.txn_ids(0), txn_id);
+ int64_t version = 0;
+ if (version_pb.has_version()) {
+ version = version_pb.version() + 1;
+ } else {
+ version = 2;
+ }
+
+ std::string rowset_key = meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ // tmp rowset key has been converted
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version);
+ tmp_rowset_pb.set_end_version(version);
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(recycle_key, recycle_val);
+ LOG(INFO) << "put recycle_key=" << hex(recycle_key) << " txn_id=" << txn_id;
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+ }
+}
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
Review Comment:
warning: function 'commit' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void TxnLazyCommitTask::commit() {
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:300:** 137 lines including whitespace and comments (threshold 80)
```cpp
void TxnLazyCommitTask::commit() {
^
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1732712524
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
Review Comment:
done
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2250637297
<details>
<summary>ClickBench: <b>Total hot run time: 30.73 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 9511fed37daee25d5ec0c6d5a1033b69e5eddf44, data reload: false
query1 0.04 0.03 0.04
query2 0.08 0.03 0.04
query3 0.22 0.05 0.06
query4 1.67 0.10 0.10
query5 0.51 0.49 0.52
query6 1.15 0.74 0.73
query7 0.02 0.01 0.02
query8 0.05 0.04 0.05
query9 0.55 0.50 0.49
query10 0.55 0.54 0.55
query11 0.15 0.10 0.11
query12 0.15 0.12 0.12
query13 0.59 0.58 0.58
query14 0.75 0.78 0.77
query15 0.86 0.81 0.81
query16 0.36 0.37 0.36
query17 1.03 1.03 1.00
query18 0.23 0.22 0.22
query19 1.82 1.81 1.79
query20 0.01 0.00 0.01
query21 15.39 0.78 0.67
query22 3.76 8.18 1.96
query23 18.25 1.40 1.21
query24 2.20 0.22 0.22
query25 0.16 0.08 0.08
query26 0.29 0.22 0.21
query27 0.45 0.23 0.23
query28 13.26 1.02 1.00
query29 12.65 3.31 3.32
query30 0.24 0.07 0.06
query31 2.86 0.40 0.39
query32 3.25 0.47 0.47
query33 2.93 2.88 2.91
query34 17.12 4.32 4.35
query35 4.37 4.43 4.44
query36 0.66 0.46 0.50
query37 0.18 0.15 0.16
query38 0.15 0.14 0.15
query39 0.04 0.04 0.03
query40 0.15 0.11 0.13
query41 0.09 0.05 0.05
query42 0.06 0.05 0.06
query43 0.05 0.04 0.04
Total cold run time: 109.35 s
Total hot run time: 30.73 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "w41ter (via GitHub)" <gi...@apache.org>.
w41ter commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1692768644
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -913,320 +1458,420 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
- msg = ss.str();
- return;
- }
- version = version_pb.version();
- } else {
- version = 1;
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
}
- new_versions[version_keys[i]] = version + 1;
+ txn->put(recycle_key, recycle_val);
}
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
+ }
+
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ code = ret.first;
+ msg = ret.second;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
+ continue;
Review Comment:
Add some comments to explain why we need to retry.
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -804,91 +962,483 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
*/
void commit_txn_immediately(
const CommitTxnRequest* request, CommitTxnResponse* response,
- std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
- const std::string& instance_id, int64_t db_id,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
std::stringstream ss;
int64_t txn_id = request->txn_id();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // Get txn info with db_id and txn_id
- std::string info_val; // Will be reused when saving updated txn
- const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
- err = txn->get(info_key, &info_val);
- if (err != TxnErrorCode::TXN_OK) {
- code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
- : cast_as<ErrCategory::READ>(err);
- if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
- ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
- } else {
- ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
- << " err=" << err;
+ // Get txn info with db_id and txn_id
+ std::string info_val; // Will be reused when saving updated txn
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
+ } else {
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
+ }
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
- TxnInfoPB txn_info;
- if (!txn_info.ParseFromString(info_val)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // TODO: do more check like txn state, 2PC etc.
- DCHECK(txn_info.txn_id() == txn_id);
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
- code = MetaServiceCode::TXN_ALREADY_ABORTED;
- ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ // TODO: do more check like txn state, 2PC etc.
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
- code = MetaServiceCode::TXN_ALREADY_VISIBLE;
- if (request->has_is_2pc() && request->is_2pc()) {
- ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ if (request->has_is_2pc() && request->is_2pc()) {
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- response->mutable_txn_info()->CopyFrom(txn_info);
- return;
- }
- if (request->has_is_2pc() && request->is_2pc() &&
- txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
- code = MetaServiceCode::TXN_INVALID_STATUS;
- ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Prepare rowset meta and new_versions
+ // Prepare rowset meta and new_versions
+ // Read tablet indexes in batch.
+ std::vector<std::string> tablet_idx_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
+ }
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ size_t total_rowsets = tmp_rowsets_meta.size();
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ for (size_t i = 0; i < total_rowsets; i++) {
+ uint64_t tablet_id = tmp_rowsets_meta[i].second.tablet_id();
+ if (!tablet_idx_values[i].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " tablet_id=" << tablet_id << " key=" << hex(tablet_idx_keys[i]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "malformed tablet index value tablet_id=" << tablet_id
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ VLOG_DEBUG << "tablet_id:" << tablet_id
+ << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ }
+
+ tablet_idx_keys.clear();
+ tablet_idx_values.clear();
+
+ // {table/partition} -> version
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
+ }
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ size_t total_versions = version_keys.size();
+ for (size_t i = 0; i < total_versions; i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+ version_keys.clear();
+ version_values.clear();
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ // std::shared_ptr<TxnLazyCommitTask> task =
+ // txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ // std::pair<MetaServiceCode, std::string> ret = task->wait();
+ // need_advance_last_txn = false;
+ // last_pending_txn_id = 0;
+ // code = ret.first;
+ // msg = ret.second;
+ // if (code != MetaServiceCode::OK) {
+ // LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ // << " code=" << code << "msg=" << msg;
+ // return;
+ // }
+ // continue;
Review Comment:
Missing?
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -913,320 +1458,420 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
- msg = ss.str();
- return;
- }
- version = version_pb.version();
- } else {
- version = 1;
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
}
- new_versions[version_keys[i]] = version + 1;
+ txn->put(recycle_key, recycle_val);
}
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
+ }
+
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ code = ret.first;
+ msg = ret.second;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
+ continue;
+ }
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ if (request->has_is_2pc() && request->is_2pc()) {
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
-
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
-
- std::string_view ver_key = i.first;
- ver_key.remove_prefix(1); // Remove key space
- // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- int ret = decode_key(&ver_key, &out);
- if (ret != 0) [[unlikely]] {
- // decode version key error means this is something wrong,
- // we can not continue this txn
- LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
code = MetaServiceCode::UNDEFINED_ERR;
- msg = "decode version key error";
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
return;
}
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
- int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
- VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- response->add_table_ids(table_id);
- response->add_partition_ids(partition_id);
- response->add_versions(i.second);
- }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
- // Save table versions
- for (auto& i : table_id_tablet_ids) {
- std::string ver_key = table_version_key({instance_id, db_id, i.first});
- txn->atomic_add(ver_key, 1);
- LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key) << " txn_id=" << txn_id;
- }
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
+ }
- LOG(INFO) << " before update txn_info=" << txn_info.ShortDebugString();
+ // save versions for partition
+ response->clear_table_ids();
+ response->clear_partition_ids();
+ response->clear_versions();
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_txn_id(txn_id);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- // Update txn_info
- txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ txn->put(i.first, ver_val);
+ LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
+ << " txn_id=" << txn_id;
- auto now_time = system_clock::now();
- uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
- if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
- LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
- << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
- return;
- }
- txn_info.set_commit_time(commit_time);
- txn_info.set_finish_time(commit_time);
- if (request->has_commit_attachment()) {
- txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
- }
- LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
- info_val.clear();
- if (!txn_info.SerializeToString(&info_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(info_key, info_val);
- LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+ std::string_view ver_key = i.first;
+ ver_key.remove_prefix(1); // Remove key space
+ // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
+ int ret = decode_key(&ver_key, &out);
+ if (ret != 0) [[unlikely]] {
+ // decode version key error means this is something wrong,
+ // we can not continue this txn
+ LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = "decode version key error";
+ return;
+ }
- // Update stats of affected tablet
- for (auto& [tablet_id, stats] : tablet_stats) {
- DCHECK(tablet_ids.count(tablet_id));
- auto& tablet_idx = tablet_ids[tablet_id];
- StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
- tablet_idx.partition_id(), tablet_id};
- update_tablet_stats(info, stats, txn, code, msg);
- if (code != MetaServiceCode::OK) return;
- }
- // Remove tmp rowset meta
- for (auto& [k, _] : tmp_rowsets_meta) {
- txn->remove(k);
- LOG(INFO) << "xxx remove tmp_rowset_key=" << hex(k) << " txn_id=" << txn_id;
- }
+ int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
+ int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
+ VLOG_DEBUG << "txn_id=" << txn_id << " table_id=" << table_id
+ << " partition_id=" << partition_id << " version=" << i.second;
- const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
- LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
- txn->remove(running_key);
+ response->add_table_ids(table_id);
+ response->add_partition_ids(partition_id);
+ response->add_versions(i.second);
+ }
- std::string recycle_val;
- std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
- RecycleTxnPB recycle_pb;
- recycle_pb.set_creation_time(commit_time);
- recycle_pb.set_label(txn_info.label());
+ // process mow table, check lock and remove pending key
+ std::vector<std::string> lock_keys;
+ lock_keys.reserve(request->mow_table_ids().size());
+ for (auto table_id : request->mow_table_ids()) {
+ lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
+ }
+ std::vector<std::optional<std::string>> lock_values;
+ err = txn->batch_get(&lock_values, lock_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
+ << " err=" << err;
+ msg = ss.str();
+ code = cast_as<ErrCategory::READ>(err);
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- if (!recycle_pb.SerializeToString(&recycle_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(recycle_key, recycle_val);
+ for (size_t i = 0; i < lock_keys.size(); i++) {
+ int64_t table_id = request->mow_table_ids(i);
+ // When the key does not exist, it means the lock has been acquired
+ // by another transaction and successfully committed.
+ if (!lock_values[i].has_value()) {
+ ss << "get delete bitmap update lock info, lock is expired"
+ << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
+ code = MetaServiceCode::LOCK_EXPIRED;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- if (txn_info.load_job_source_type() ==
- LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
- put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
- }
+ DeleteBitmapUpdateLockPB lock_info;
+ if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "failed to parse DeleteBitmapUpdateLockPB";
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ if (lock_info.lock_id() != request->txn_id()) {
+ msg = "lock is expired";
+ code = MetaServiceCode::LOCK_EXPIRED;
+ return;
+ }
+ txn->remove(lock_keys[i]);
+ LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
+ << " txn_id=" << txn_id;
- LOG(INFO) << "xxx commit_txn put recycle_key key=" << hex(recycle_key) << " txn_id=" << txn_id;
- LOG(INFO) << "commit_txn put_size=" << txn->put_bytes() << " del_size=" << txn->delete_bytes()
- << " num_put_keys=" << txn->num_put_keys() << " num_del_keys=" << txn->num_del_keys()
- << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
+ for (auto tablet_id : table_id_tablet_ids[table_id]) {
+ std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
+ txn->remove(pending_key);
+ LOG(INFO) << "xxx remove delete bitmap pending key, pending_key="
+ << hex(pending_key) << " txn_id=" << txn_id;
+ }
+ }
+ lock_keys.clear();
+ lock_values.clear();
- // Finally we are done...
- err = txn->commit();
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::COMMIT>(err);
- ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- return;
- }
+ // Save table versions
+ for (auto& i : table_id_tablet_ids) {
+ std::string ver_key = table_version_key({instance_id, db_id, i.first});
+ txn->atomic_add(ver_key, 1);
+ LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key)
+ << " txn_id=" << txn_id;
+ }
- // calculate table stats from tablets stats
- std::map<int64_t /*table_id*/, TableStats> table_stats;
- std::vector<int64_t> base_tablet_ids(request->base_tablet_ids().begin(),
- request->base_tablet_ids().end());
- calc_table_stats(tablet_ids, tablet_stats, table_stats, base_tablet_ids);
- for (const auto& pair : table_stats) {
- TableStatsPB* stats_pb = response->add_table_stats();
- auto table_id = pair.first;
- auto stats = pair.second;
- get_pb_from_tablestats(stats, stats_pb);
- stats_pb->set_table_id(table_id);
- VLOG_DEBUG << "Add TableStats to CommitTxnResponse. txn_id=" << txn_id
- << " table_id=" << table_id
- << " updated_row_count=" << stats_pb->updated_row_count();
- }
+ LOG(INFO) << "commit_txn_eventually put_size=" << txn->put_bytes()
+ << " del_size=" << txn->delete_bytes() << " num_put_keys=" << txn->num_put_keys()
+ << " num_del_keys=" << txn->num_del_keys()
+ << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
- response->mutable_txn_info()->CopyFrom(txn_info);
-} // end commit_txn
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+
+ std::shared_ptr<TxnLazyCommitTask> task = txn_lazy_committer->submit(instance_id, txn_id);
Review Comment:
In the future, we can pass the already read data to TxnLazyCommitter to optimize read performance. For now, let's focus on merging this PR.
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -913,320 +1458,420 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
- msg = ss.str();
- return;
- }
- version = version_pb.version();
- } else {
- version = 1;
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
}
- new_versions[version_keys[i]] = version + 1;
+ txn->put(recycle_key, recycle_val);
}
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
+ }
+
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ code = ret.first;
+ msg = ret.second;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
+ continue;
+ }
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ if (request->has_is_2pc() && request->is_2pc()) {
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
-
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
-
- std::string_view ver_key = i.first;
- ver_key.remove_prefix(1); // Remove key space
- // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- int ret = decode_key(&ver_key, &out);
- if (ret != 0) [[unlikely]] {
- // decode version key error means this is something wrong,
- // we can not continue this txn
- LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
code = MetaServiceCode::UNDEFINED_ERR;
- msg = "decode version key error";
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
return;
}
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
- int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
- VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- response->add_table_ids(table_id);
- response->add_partition_ids(partition_id);
- response->add_versions(i.second);
- }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
- // Save table versions
- for (auto& i : table_id_tablet_ids) {
- std::string ver_key = table_version_key({instance_id, db_id, i.first});
- txn->atomic_add(ver_key, 1);
- LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key) << " txn_id=" << txn_id;
- }
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
+ }
- LOG(INFO) << " before update txn_info=" << txn_info.ShortDebugString();
+ // save versions for partition
+ response->clear_table_ids();
+ response->clear_partition_ids();
+ response->clear_versions();
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_txn_id(txn_id);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- // Update txn_info
- txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ txn->put(i.first, ver_val);
+ LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
+ << " txn_id=" << txn_id;
- auto now_time = system_clock::now();
- uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
- if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
- LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
- << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
- return;
- }
- txn_info.set_commit_time(commit_time);
- txn_info.set_finish_time(commit_time);
- if (request->has_commit_attachment()) {
- txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
- }
- LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
- info_val.clear();
- if (!txn_info.SerializeToString(&info_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(info_key, info_val);
- LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+ std::string_view ver_key = i.first;
+ ver_key.remove_prefix(1); // Remove key space
+ // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
+ int ret = decode_key(&ver_key, &out);
+ if (ret != 0) [[unlikely]] {
+ // decode version key error means this is something wrong,
+ // we can not continue this txn
+ LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = "decode version key error";
+ return;
+ }
- // Update stats of affected tablet
- for (auto& [tablet_id, stats] : tablet_stats) {
- DCHECK(tablet_ids.count(tablet_id));
- auto& tablet_idx = tablet_ids[tablet_id];
- StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
- tablet_idx.partition_id(), tablet_id};
- update_tablet_stats(info, stats, txn, code, msg);
- if (code != MetaServiceCode::OK) return;
- }
- // Remove tmp rowset meta
- for (auto& [k, _] : tmp_rowsets_meta) {
- txn->remove(k);
- LOG(INFO) << "xxx remove tmp_rowset_key=" << hex(k) << " txn_id=" << txn_id;
- }
+ int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
+ int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
+ VLOG_DEBUG << "txn_id=" << txn_id << " table_id=" << table_id
+ << " partition_id=" << partition_id << " version=" << i.second;
- const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
- LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
- txn->remove(running_key);
+ response->add_table_ids(table_id);
+ response->add_partition_ids(partition_id);
+ response->add_versions(i.second);
+ }
- std::string recycle_val;
- std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
- RecycleTxnPB recycle_pb;
- recycle_pb.set_creation_time(commit_time);
- recycle_pb.set_label(txn_info.label());
+ // process mow table, check lock and remove pending key
+ std::vector<std::string> lock_keys;
+ lock_keys.reserve(request->mow_table_ids().size());
+ for (auto table_id : request->mow_table_ids()) {
+ lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
+ }
+ std::vector<std::optional<std::string>> lock_values;
+ err = txn->batch_get(&lock_values, lock_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
+ << " err=" << err;
+ msg = ss.str();
+ code = cast_as<ErrCategory::READ>(err);
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- if (!recycle_pb.SerializeToString(&recycle_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(recycle_key, recycle_val);
+ for (size_t i = 0; i < lock_keys.size(); i++) {
+ int64_t table_id = request->mow_table_ids(i);
+ // When the key does not exist, it means the lock has been acquired
+ // by another transaction and successfully committed.
+ if (!lock_values[i].has_value()) {
+ ss << "get delete bitmap update lock info, lock is expired"
+ << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
+ code = MetaServiceCode::LOCK_EXPIRED;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- if (txn_info.load_job_source_type() ==
- LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
- put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
- }
+ DeleteBitmapUpdateLockPB lock_info;
+ if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "failed to parse DeleteBitmapUpdateLockPB";
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ if (lock_info.lock_id() != request->txn_id()) {
+ msg = "lock is expired";
+ code = MetaServiceCode::LOCK_EXPIRED;
+ return;
+ }
+ txn->remove(lock_keys[i]);
+ LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
+ << " txn_id=" << txn_id;
- LOG(INFO) << "xxx commit_txn put recycle_key key=" << hex(recycle_key) << " txn_id=" << txn_id;
- LOG(INFO) << "commit_txn put_size=" << txn->put_bytes() << " del_size=" << txn->delete_bytes()
- << " num_put_keys=" << txn->num_put_keys() << " num_del_keys=" << txn->num_del_keys()
- << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
+ for (auto tablet_id : table_id_tablet_ids[table_id]) {
+ std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
+ txn->remove(pending_key);
+ LOG(INFO) << "xxx remove delete bitmap pending key, pending_key="
+ << hex(pending_key) << " txn_id=" << txn_id;
+ }
+ }
+ lock_keys.clear();
+ lock_values.clear();
- // Finally we are done...
- err = txn->commit();
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::COMMIT>(err);
- ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- return;
- }
+ // Save table versions
+ for (auto& i : table_id_tablet_ids) {
+ std::string ver_key = table_version_key({instance_id, db_id, i.first});
+ txn->atomic_add(ver_key, 1);
+ LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key)
+ << " txn_id=" << txn_id;
+ }
- // calculate table stats from tablets stats
- std::map<int64_t /*table_id*/, TableStats> table_stats;
- std::vector<int64_t> base_tablet_ids(request->base_tablet_ids().begin(),
- request->base_tablet_ids().end());
- calc_table_stats(tablet_ids, tablet_stats, table_stats, base_tablet_ids);
- for (const auto& pair : table_stats) {
- TableStatsPB* stats_pb = response->add_table_stats();
- auto table_id = pair.first;
- auto stats = pair.second;
- get_pb_from_tablestats(stats, stats_pb);
- stats_pb->set_table_id(table_id);
- VLOG_DEBUG << "Add TableStats to CommitTxnResponse. txn_id=" << txn_id
- << " table_id=" << table_id
- << " updated_row_count=" << stats_pb->updated_row_count();
- }
+ LOG(INFO) << "commit_txn_eventually put_size=" << txn->put_bytes()
+ << " del_size=" << txn->delete_bytes() << " num_put_keys=" << txn->num_put_keys()
+ << " num_del_keys=" << txn->num_del_keys()
+ << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
- response->mutable_txn_info()->CopyFrom(txn_info);
-} // end commit_txn
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+
+ std::shared_ptr<TxnLazyCommitTask> task = txn_lazy_committer->submit(instance_id, txn_id);
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
Review Comment:
```suggestion
std::tie(code, msg) = task->wait();
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2260705985
<details>
<summary>TPC-DS: <b>Total hot run time: 170002 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit f23de131c772e5e5b480379dddd6cae001bf04a6, data reload: false
query1 923 373 372 372
query2 6466 1714 1613 1613
query3 6652 215 221 215
query4 20217 17552 17284 17284
query5 3642 528 520 520
query6 310 168 187 168
query7 4595 298 302 298
query8 243 202 190 190
query9 8512 2403 2374 2374
query10 450 279 284 279
query11 10457 10081 10106 10081
query12 119 88 92 88
query13 1616 382 370 370
query14 9005 7054 8274 7054
query15 205 171 161 161
query16 6864 444 455 444
query17 954 570 563 563
query18 1808 296 304 296
query19 195 150 147 147
query20 95 89 89 89
query21 208 102 103 102
query22 4135 4083 4048 4048
query23 33793 33840 33649 33649
query24 10461 3126 3040 3040
query25 687 421 411 411
query26 1789 164 160 160
query27 3149 289 282 282
query28 7741 2047 2033 2033
query29 1292 445 449 445
query30 237 162 170 162
query31 955 767 758 758
query32 115 59 56 56
query33 686 323 359 323
query34 935 482 504 482
query35 882 803 764 764
query36 1046 863 898 863
query37 283 96 82 82
query38 2905 2816 2806 2806
query39 860 830 822 822
query40 264 116 117 116
query41 47 46 44 44
query42 135 102 99 99
query43 458 422 400 400
query44 1195 737 736 736
query45 214 180 180 180
query46 1086 795 776 776
query47 1808 1713 1696 1696
query48 365 291 296 291
query49 931 415 418 415
query50 914 439 433 433
query51 6697 6738 6608 6608
query52 109 87 96 87
query53 251 182 178 178
query54 650 461 452 452
query55 78 75 77 75
query56 286 256 248 248
query57 1127 1000 1073 1000
query58 281 263 261 261
query59 2623 2309 2342 2309
query60 301 281 283 281
query61 98 100 96 96
query62 886 656 667 656
query63 207 182 187 182
query64 5673 1968 1980 1968
query65 3172 3102 3103 3102
query66 1351 354 331 331
query67 15497 14829 14849 14829
query68 4332 583 571 571
query69 642 386 315 315
query70 1069 1004 1038 1004
query71 443 284 275 275
query72 7099 2736 2483 2483
query73 778 325 325 325
query74 5992 5678 5585 5585
query75 3505 2795 2776 2776
query76 2762 1322 1410 1322
query77 565 305 306 305
query78 9477 8868 8959 8868
query79 1914 555 544 544
query80 952 508 499 499
query81 576 229 225 225
query82 1025 134 128 128
query83 249 171 173 171
query84 278 82 94 82
query85 1359 320 307 307
query86 444 297 285 285
query87 3261 3133 3130 3130
query88 2968 2430 2418 2418
query89 392 298 287 287
query90 1738 194 193 193
query91 126 102 103 102
query92 63 50 53 50
query93 1758 632 640 632
query94 828 298 305 298
query95 392 279 275 275
query96 610 279 278 278
query97 3236 3047 3098 3047
query98 220 208 197 197
query99 1612 1282 1310 1282
Total cold run time: 262856 ms
Total hot run time: 170002 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2262300969
<details>
<summary>TPC-H: <b>Total hot run time: 41825 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit f40d3af909e3a4ce446ee5217827a6811bce34d1, data reload: false
------ Round 1 ----------------------------------
q1 17655 4407 4071 4071
q2 2028 208 202 202
q3 10546 1379 1373 1373
q4 10237 818 935 818
q5 7634 3022 2976 2976
q6 219 135 140 135
q7 1039 612 606 606
q8 9443 1881 1988 1881
q9 8530 6629 6621 6621
q10 8797 3904 3892 3892
q11 435 249 239 239
q12 412 230 225 225
q13 17774 2969 2945 2945
q14 269 250 247 247
q15 517 479 484 479
q16 518 380 393 380
q17 998 889 918 889
q18 8073 7286 7355 7286
q19 1490 1222 1220 1220
q20 549 341 342 341
q21 5317 4724 4798 4724
q22 349 282 275 275
Total cold run time: 112829 ms
Total hot run time: 41825 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4136 4032 4002 4002
q2 324 218 216 216
q3 2992 3044 3185 3044
q4 2028 2039 2006 2006
q5 5679 5470 5473 5470
q6 220 130 130 130
q7 2187 1859 1819 1819
q8 3341 3390 3372 3372
q9 8688 8711 8782 8711
q10 3962 4136 3933 3933
q11 546 455 476 455
q12 781 601 580 580
q13 16313 3157 3132 3132
q14 299 277 276 276
q15 530 497 487 487
q16 470 415 440 415
q17 1755 1748 1737 1737
q18 8350 7779 7726 7726
q19 1740 1707 1710 1707
q20 2054 1894 1828 1828
q21 5857 5468 5419 5419
q22 531 450 475 450
Total cold run time: 72783 ms
Total hot run time: 56915 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2312706402
<details>
<summary>ClickBench: <b>Total hot run time: 31.14 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 5f3b5ea8bfb6214887e8d1bb42d8f87233ccc8a0, data reload: false
query1 0.05 0.05 0.04
query2 0.07 0.04 0.04
query3 0.23 0.05 0.05
query4 1.67 0.06 0.07
query5 0.52 0.48 0.49
query6 1.13 0.72 0.72
query7 0.02 0.01 0.02
query8 0.05 0.04 0.04
query9 0.56 0.49 0.48
query10 0.53 0.55 0.56
query11 0.16 0.12 0.12
query12 0.15 0.12 0.12
query13 0.62 0.60 0.59
query14 0.76 0.79 0.77
query15 0.84 0.82 0.82
query16 0.39 0.37 0.37
query17 1.04 1.03 0.96
query18 0.22 0.21 0.20
query19 1.95 1.79 1.72
query20 0.02 0.00 0.01
query21 15.40 0.64 0.64
query22 4.17 7.19 2.44
query23 18.32 1.40 1.31
query24 2.06 0.22 0.22
query25 0.16 0.08 0.08
query26 0.27 0.17 0.18
query27 0.07 0.07 0.07
query28 13.24 1.01 1.00
query29 12.56 3.42 3.32
query30 0.25 0.06 0.05
query31 2.86 0.39 0.38
query32 3.28 0.48 0.47
query33 2.92 3.02 2.98
query34 16.76 4.38 4.36
query35 4.41 4.43 4.49
query36 0.66 0.49 0.48
query37 0.19 0.16 0.15
query38 0.15 0.14 0.15
query39 0.05 0.04 0.04
query40 0.16 0.13 0.13
query41 0.09 0.05 0.05
query42 0.06 0.05 0.05
query43 0.05 0.04 0.04
Total cold run time: 109.12 s
Total hot run time: 31.14 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2304123512
<details>
<summary>TPC-H: <b>Total hot run time: 38205 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 20e25bf51ae7f01a6fff2f9704c155a8c059045a, data reload: false
------ Round 1 ----------------------------------
q1 19192 4702 4345 4345
q2 2041 194 177 177
q3 10529 1143 1093 1093
q4 10231 818 702 702
q5 7742 2906 2785 2785
q6 226 139 143 139
q7 970 612 594 594
q8 9320 2070 2070 2070
q9 7204 6550 6517 6517
q10 7024 2200 2236 2200
q11 450 255 247 247
q12 397 225 230 225
q13 17764 3034 3046 3034
q14 282 232 234 232
q15 525 487 507 487
q16 502 385 385 385
q17 992 664 772 664
q18 7521 6772 6869 6772
q19 1403 1091 1011 1011
q20 671 346 337 337
q21 3893 3193 3204 3193
q22 1125 1017 996 996
Total cold run time: 110004 ms
Total hot run time: 38205 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4424 4320 4270 4270
q2 383 275 275 275
q3 2903 2654 2668 2654
q4 1962 1681 1669 1669
q5 5417 5375 5403 5375
q6 219 132 135 132
q7 2111 1735 1750 1735
q8 3193 3374 3346 3346
q9 8419 8461 8505 8461
q10 3449 3180 3191 3180
q11 626 487 495 487
q12 779 627 589 589
q13 14709 3061 3015 3015
q14 309 277 284 277
q15 516 497 470 470
q16 469 434 427 427
q17 1792 1498 1503 1498
q18 7758 7556 7379 7379
q19 1677 1584 1601 1584
q20 2058 1821 1855 1821
q21 5517 5257 5090 5090
q22 1095 1045 1011 1011
Total cold run time: 69785 ms
Total hot run time: 54745 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2249642741
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2245067398
<details>
<summary>TPC-H: <b>Total hot run time: 39622 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit d47f33a15e68079183da96a15302b529dc1c36a2, data reload: false
------ Round 1 ----------------------------------
q1 17610 4591 4263 4263
q2 2019 191 183 183
q3 10556 1161 1064 1064
q4 10294 769 821 769
q5 7575 2708 2662 2662
q6 222 139 134 134
q7 957 606 591 591
q8 9220 2038 2078 2038
q9 8838 6519 6549 6519
q10 8687 3803 3783 3783
q11 454 230 238 230
q12 410 231 223 223
q13 17772 2996 3008 2996
q14 280 239 251 239
q15 519 484 487 484
q16 495 393 382 382
q17 964 687 677 677
q18 8151 7595 7343 7343
q19 5829 1332 1256 1256
q20 677 328 319 319
q21 4912 3178 4004 3178
q22 354 289 294 289
Total cold run time: 116795 ms
Total hot run time: 39622 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4369 4246 4227 4227
q2 363 270 262 262
q3 2996 2880 2880 2880
q4 2022 1704 1774 1704
q5 5665 5532 5524 5524
q6 220 135 131 131
q7 2212 1865 1850 1850
q8 3276 3410 3423 3410
q9 8768 8788 8888 8788
q10 4095 3860 3791 3791
q11 581 499 493 493
q12 819 644 645 644
q13 15995 3187 3186 3186
q14 325 291 287 287
q15 530 491 477 477
q16 502 427 437 427
q17 1829 1516 1523 1516
q18 8112 7917 7832 7832
q19 1714 1663 1480 1480
q20 2138 1909 1857 1857
q21 5088 4874 4896 4874
q22 586 507 527 507
Total cold run time: 72205 ms
Total hot run time: 56147 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1708897290
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,371 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
Review Comment:
warning: function 'commit' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void TxnLazyCommitTask::commit() {
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:208:** 122 lines including whitespace and comments (threshold 80)
```cpp
void TxnLazyCommitTask::commit() {
^
```
</details>
##########
cloud/test/txn_lazy_commit_test.cpp:
##########
@@ -0,0 +1,68 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <brpc/controller.h>
Review Comment:
warning: 'brpc/controller.h' file not found [clang-diagnostic-error]
```cpp
#include <brpc/controller.h>
^
```
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,371 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
Review Comment:
warning: function 'convert_tmp_rowsets' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void convert_tmp_rowsets(
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:36:** 152 lines including whitespace and comments (threshold 80)
```cpp
void convert_tmp_rowsets(
^
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "w41ter (via GitHub)" <gi...@apache.org>.
w41ter commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1708714602
##########
cloud/src/recycler/recycler.cpp:
##########
@@ -1888,72 +2019,90 @@ int InstanceRecycler::abort_timeout_txn() {
}
++num_timeout;
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv_->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- LOG_ERROR("failed to create txn err={}", err).tag("key", hex(k));
- return -1;
- }
- std::string_view k1 = k;
- //TxnRunningKeyInfo 0:instance_id 1:db_id 2:txn_id
- k1.remove_prefix(1); // Remove key space
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- if (decode_key(&k1, &out) != 0) {
- LOG_ERROR("failed to decode key").tag("key", hex(k));
- return -1;
- }
- int64_t db_id = std::get<int64_t>(std::get<0>(out[3]));
- int64_t txn_id = std::get<int64_t>(std::get<0>(out[4]));
- VLOG_DEBUG << "instance_id=" << instance_id_ << " db_id=" << db_id << " txn_id=" << txn_id;
- // Update txn_info
- std::string txn_inf_key, txn_inf_val;
- txn_info_key({instance_id_, db_id, txn_id}, &txn_inf_key);
- err = txn->get(txn_inf_key, &txn_inf_val);
- if (err != TxnErrorCode::TXN_OK) {
- LOG_WARNING("failed to get txn info err={}", err).tag("key", hex(txn_inf_key));
- return -1;
- }
- TxnInfoPB txn_info;
- if (!txn_info.ParseFromString(txn_inf_val)) {
- LOG_WARNING("failed to parse txn info").tag("key", hex(k));
- return -1;
- }
- txn_info.set_status(TxnStatusPB::TXN_STATUS_ABORTED);
- txn_info.set_finish_time(current_time);
- txn_info.set_reason("timeout");
- VLOG_DEBUG << "txn_info=" << txn_info.DebugString();
- txn_inf_val.clear();
- if (!txn_info.SerializeToString(&txn_inf_val)) {
- LOG_WARNING("failed to serialize txn info").tag("key", hex(k));
- return -1;
- }
- txn->put(txn_inf_key, txn_inf_val);
- VLOG_DEBUG << "txn->put, txn_inf_key=" << hex(txn_inf_key);
- // Put recycle txn key
- std::string recyc_txn_key, recyc_txn_val;
- recycle_txn_key({instance_id_, db_id, txn_id}, &recyc_txn_key);
- RecycleTxnPB recycle_txn_pb;
- recycle_txn_pb.set_creation_time(current_time);
- recycle_txn_pb.set_label(txn_info.label());
- if (!recycle_txn_pb.SerializeToString(&recyc_txn_val)) {
- LOG_WARNING("failed to serialize txn recycle info")
- .tag("key", hex(k))
- .tag("db_id", db_id)
- .tag("txn_id", txn_id);
- return -1;
- }
- txn->put(recyc_txn_key, recyc_txn_val);
- // Remove txn running key
- txn->remove(k);
- err = txn->commit();
- if (err != TxnErrorCode::TXN_OK) {
- LOG_WARNING("failed to commit txn err={}", err)
- .tag("key", hex(k))
- .tag("db_id", db_id)
- .tag("txn_id", txn_id);
- return -1;
- }
- ++num_abort;
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ LOG_ERROR("failed to create txn err={}", err).tag("key", hex(k));
+ return -1;
+ }
+ std::string_view k1 = k;
+ //TxnRunningKeyInfo 0:instance_id 1:db_id 2:txn_id
+ k1.remove_prefix(1); // Remove key space
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
+ if (decode_key(&k1, &out) != 0) {
+ LOG_ERROR("failed to decode key").tag("key", hex(k));
+ return -1;
+ }
+ int64_t db_id = std::get<int64_t>(std::get<0>(out[3]));
+ int64_t txn_id = std::get<int64_t>(std::get<0>(out[4]));
+ VLOG_DEBUG << "instance_id=" << instance_id_ << " db_id=" << db_id
+ << " txn_id=" << txn_id;
+ // Update txn_info
+ std::string txn_inf_key, txn_inf_val;
+ txn_info_key({instance_id_, db_id, txn_id}, &txn_inf_key);
+ err = txn->get(txn_inf_key, &txn_inf_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ LOG_WARNING("failed to get txn info err={}", err).tag("key", hex(txn_inf_key));
+ return -1;
+ }
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(txn_inf_val)) {
+ LOG_WARNING("failed to parse txn info").tag("key", hex(k));
+ return -1;
+ }
+
+ if (TxnStatusPB::TXN_STATUS_COMMITTED == txn_info.status()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer_->submit(instance_id_, txn_info.txn_id());
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ if (ret.first != MetaServiceCode::OK) {
+ LOG(WARNING) << "lazy commit txn failed txn_id=" << txn_id
+ << " code=" << ret.first << "msg=" << ret.second;
+ return -1;
+ }
+ continue;
+ } else {
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_VISIBLE);
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_ABORTED);
Review Comment:
The `continue` means retry to recycle this "timeouted" TXN, but it has been committed (status visible) via the `TxnLazyCommitTask`, then this DCHECK will panic.
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -788,6 +788,164 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
txn->put(key, val);
}
}
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
Review Comment:
`convert_tmp_rowsets` seems only used in TxnLazyCommiter, and line 986 is `DCHECK(partition_versions.size() == 1);`.
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -326,8 +342,12 @@ void MetaServiceImpl::batch_get_version(::google::protobuf::RpcController* contr
std::vector<std::optional<std::string>> version_values;
version_keys.reserve(BATCH_SIZE);
version_values.reserve(BATCH_SIZE);
+
while ((code == MetaServiceCode::OK || code == MetaServiceCode::KV_TXN_TOO_OLD) &&
response->versions_size() < response->partition_ids_size()) {
+ response->clear_versions();
+ code = MetaServiceCode::OK;
+
Review Comment:
```suggestion
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2259578842
<details>
<summary>TPC-H: <b>Total hot run time: 41912 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 8ed44221f04cb0a14f7132c207fbd3cf93e572f1, data reload: false
------ Round 1 ----------------------------------
q1 17781 4217 4081 4081
q2 2028 204 203 203
q3 10544 1343 1350 1343
q4 10233 886 939 886
q5 7670 2956 3002 2956
q6 222 138 138 138
q7 1047 617 626 617
q8 9452 1953 1979 1953
q9 8581 6628 6655 6628
q10 8755 3878 3841 3841
q11 426 258 253 253
q12 409 226 232 226
q13 17766 2947 2972 2947
q14 274 243 247 243
q15 530 487 495 487
q16 506 407 393 393
q17 977 948 911 911
q18 8058 7242 7300 7242
q19 1437 1226 1221 1221
q20 560 334 343 334
q21 5293 4729 4901 4729
q22 357 287 280 280
Total cold run time: 112906 ms
Total hot run time: 41912 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4042 4026 4059 4026
q2 336 231 237 231
q3 3023 3063 3167 3063
q4 2029 2006 1987 1987
q5 5680 5501 5509 5501
q6 218 133 132 132
q7 2188 1843 1839 1839
q8 3394 3455 3400 3400
q9 8734 8763 8839 8763
q10 3948 4064 3935 3935
q11 557 453 465 453
q12 761 610 602 602
q13 15136 3184 3162 3162
q14 308 275 288 275
q15 533 501 488 488
q16 500 416 415 415
q17 1770 1757 1754 1754
q18 8415 7710 7738 7710
q19 1766 1746 1729 1729
q20 2068 1861 1841 1841
q21 5836 5525 5278 5278
q22 537 467 469 467
Total cold run time: 71779 ms
Total hot run time: 57051 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2283623317
<details>
<summary>TPC-H: <b>Total hot run time: 39992 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 88d3d52a5127df11de69d64be57d1e49cab899b7, data reload: false
------ Round 1 ----------------------------------
q1 18613 4819 4379 4379
q2 2629 189 191 189
q3 11330 1169 1177 1169
q4 10588 760 732 732
q5 7616 2585 2580 2580
q6 231 139 145 139
q7 989 628 614 614
q8 9927 1934 1946 1934
q9 8769 6582 6620 6582
q10 7058 2190 2210 2190
q11 476 248 247 247
q12 401 218 212 212
q13 17847 2991 2961 2961
q14 276 242 239 239
q15 543 479 496 479
q16 640 532 514 514
q17 995 651 667 651
q18 8178 7472 7455 7455
q19 4377 1072 980 980
q20 743 421 413 413
q21 5404 4693 4319 4319
q22 1103 1058 1014 1014
Total cold run time: 118733 ms
Total hot run time: 39992 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4473 4231 4294 4231
q2 392 288 268 268
q3 2835 2650 2664 2650
q4 1876 1639 1588 1588
q5 5259 5275 5286 5275
q6 223 129 129 129
q7 2071 1652 1653 1652
q8 3133 3314 3349 3314
q9 8362 8329 8349 8329
q10 3372 3116 3118 3116
q11 584 490 487 487
q12 753 617 592 592
q13 17360 3000 2970 2970
q14 300 274 284 274
q15 532 476 482 476
q16 608 548 558 548
q17 1807 1493 1479 1479
q18 7627 7485 7457 7457
q19 1651 1625 1566 1566
q20 2060 1888 1886 1886
q21 5303 5005 5053 5005
q22 1086 1036 1016 1016
Total cold run time: 71667 ms
Total hot run time: 54308 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "w41ter (via GitHub)" <gi...@apache.org>.
w41ter commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1715102836
##########
cloud/src/recycler/recycler.cpp:
##########
@@ -1707,6 +1777,62 @@ int InstanceRecycler::recycle_rowsets() {
return ret;
}
+bool check_txn_abort(std::shared_ptr<TxnKv> txn_kv, const std::string& instance_id,
+ int64_t txn_id) {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ LOG(WARNING) << "failed to create txn, txn_id=" << txn_id << " instance_id=" << instance_id;
+ return false;
+ }
+
+ std::string index_val;
+ const std::string index_key = txn_index_key({instance_id, txn_id});
+ err = txn->get(index_key, &index_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // txn has been recycled;
+ return true;
+ }
+ LOG(WARNING) << "failed to get txn index key, txn_id=" << txn_id
+ << " instance_id=" << instance_id << " key=" << hex(index_key);
+ return false;
+ }
+
+ TxnIndexPB index_pb;
+ if (!index_pb.ParseFromString(index_val)) {
+ LOG(WARNING) << "failed to parse txn_index_pb, txn_id=" << txn_id
+ << " instance_id=" << instance_id;
+ return false;
+ }
+
+ DCHECK(index_pb.has_tablet_index() == true);
+ DCHECK(index_pb.tablet_index().has_db_id() == true);
+ int64_t db_id = index_pb.tablet_index().db_id();
Review Comment:
For compatibility, consider checking the DB id before using it, just like:
```c++
if (!index_pb.tablet_index().has_db_id()) {
return false;
}
```
##########
cloud/src/recycler/recycler.cpp:
##########
@@ -1707,6 +1777,62 @@ int InstanceRecycler::recycle_rowsets() {
return ret;
}
+bool check_txn_abort(std::shared_ptr<TxnKv> txn_kv, const std::string& instance_id,
+ int64_t txn_id) {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ LOG(WARNING) << "failed to create txn, txn_id=" << txn_id << " instance_id=" << instance_id;
+ return false;
+ }
+
+ std::string index_val;
+ const std::string index_key = txn_index_key({instance_id, txn_id});
+ err = txn->get(index_key, &index_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // txn has been recycled;
+ return true;
+ }
+ LOG(WARNING) << "failed to get txn index key, txn_id=" << txn_id
+ << " instance_id=" << instance_id << " key=" << hex(index_key);
+ return false;
+ }
+
+ TxnIndexPB index_pb;
+ if (!index_pb.ParseFromString(index_val)) {
+ LOG(WARNING) << "failed to parse txn_index_pb, txn_id=" << txn_id
+ << " instance_id=" << instance_id;
+ return false;
+ }
+
+ DCHECK(index_pb.has_tablet_index() == true);
+ DCHECK(index_pb.tablet_index().has_db_id() == true);
+ int64_t db_id = index_pb.tablet_index().db_id();
Review Comment:
A new kind of task needs to be added. This task should scan all partition keys, parse db_id, and fill the db_id of the `TabletIndexPB`.
##########
cloud/src/recycler/recycler.cpp:
##########
@@ -1918,42 +2043,69 @@ int InstanceRecycler::abort_timeout_txn() {
LOG_WARNING("failed to parse txn info").tag("key", hex(k));
return -1;
}
- txn_info.set_status(TxnStatusPB::TXN_STATUS_ABORTED);
- txn_info.set_finish_time(current_time);
- txn_info.set_reason("timeout");
- VLOG_DEBUG << "txn_info=" << txn_info.DebugString();
- txn_inf_val.clear();
- if (!txn_info.SerializeToString(&txn_inf_val)) {
- LOG_WARNING("failed to serialize txn info").tag("key", hex(k));
- return -1;
- }
- txn->put(txn_inf_key, txn_inf_val);
- VLOG_DEBUG << "txn->put, txn_inf_key=" << hex(txn_inf_key);
- // Put recycle txn key
- std::string recyc_txn_key, recyc_txn_val;
- recycle_txn_key({instance_id_, db_id, txn_id}, &recyc_txn_key);
- RecycleTxnPB recycle_txn_pb;
- recycle_txn_pb.set_creation_time(current_time);
- recycle_txn_pb.set_label(txn_info.label());
- if (!recycle_txn_pb.SerializeToString(&recyc_txn_val)) {
- LOG_WARNING("failed to serialize txn recycle info")
- .tag("key", hex(k))
- .tag("db_id", db_id)
- .tag("txn_id", txn_id);
- return -1;
- }
- txn->put(recyc_txn_key, recyc_txn_val);
- // Remove txn running key
- txn->remove(k);
- err = txn->commit();
- if (err != TxnErrorCode::TXN_OK) {
- LOG_WARNING("failed to commit txn err={}", err)
- .tag("key", hex(k))
- .tag("db_id", db_id)
- .tag("txn_id", txn_id);
- return -1;
+
+ if (TxnStatusPB::TXN_STATUS_COMMITTED == txn_info.status()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer_->submit(instance_id_, txn_info.txn_id());
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ if (ret.first != MetaServiceCode::OK) {
+ LOG(WARNING) << "lazy commit txn failed txn_id=" << txn_id << " code=" << ret.first
+ << "msg=" << ret.second;
+ return -1;
+ }
+ ++num_advance;
+ return 0;
+ } else {
Review Comment:
A suggestion, remove this `else {`, so the diff view will be clearer.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1722773609
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -913,320 +1458,420 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
- msg = ss.str();
- return;
- }
- version = version_pb.version();
- } else {
- version = 1;
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
}
- new_versions[version_keys[i]] = version + 1;
+ txn->put(recycle_key, recycle_val);
}
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
+ }
+
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ code = ret.first;
+ msg = ret.second;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
+ continue;
Review Comment:
> Add some comments to explain why we need to retry.
done, i have added a comment
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2303598622
run cloudut
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1708566789
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -237,46 +238,63 @@ void MetaServiceImpl::get_version(::google::protobuf::RpcController* controller,
partition_version_key({instance_id, db_id, table_id, partition_id}, &ver_key);
}
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv_->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- msg = "failed to create txn";
- code = cast_as<ErrCategory::CREATE>(err);
- return;
- }
+ do {
+ code = MetaServiceCode::OK;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ msg = "failed to create txn";
+ code = cast_as<ErrCategory::CREATE>(err);
+ return;
+ }
- std::string ver_val;
- // 0 for success get a key, 1 for key not found, negative for error
- err = txn->get(ver_key, &ver_val);
- VLOG_DEBUG << "xxx get version_key=" << hex(ver_key);
- if (err == TxnErrorCode::TXN_OK) {
- if (is_table_version) {
- int64_t version = 0;
- if (!txn->decode_atomic_int(ver_val, &version)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "malformed table version value";
- return;
- }
- response->set_version(version);
- } else {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(ver_val)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "malformed version value";
- return;
+ std::string ver_val;
+ // 0 for success get a key, 1 for key not found, negative for error
+ err = txn->get(ver_key, &ver_val);
+ VLOG_DEBUG << "xxx get version_key=" << hex(ver_key);
+ if (err == TxnErrorCode::TXN_OK) {
+ if (is_table_version) {
+ int64_t version = 0;
+ if (!txn->decode_atomic_int(ver_val, &version)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "malformed table version value";
+ return;
+ }
+ response->set_version(version);
+ } else {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "malformed version value";
+ return;
+ }
+
+ if (version_pb.has_txn_id()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer_->submit(instance_id, version_pb.txn_id());
+
+ std::tie(code, msg) = task->wait();
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING)
+ << "wait txn lazy commit failed, txn_id=" << version_pb.txn_id();
+ return;
+ }
+ }
+
+ response->set_version(version_pb.version());
+ response->add_version_update_time_ms(version_pb.update_time_ms());
}
- response->set_version(version_pb.version());
- response->add_version_update_time_ms(version_pb.update_time_ms());
+ { TEST_SYNC_POINT_CALLBACK("get_version_code", &code); }
+ return;
+ } else if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ msg = "not found";
+ code = MetaServiceCode::VERSION_NOT_FOUND;
+ return;
}
- { TEST_SYNC_POINT_CALLBACK("get_version_code", &code); }
- return;
- } else if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
- msg = "not found";
- code = MetaServiceCode::VERSION_NOT_FOUND;
- return;
- }
- msg = fmt::format("failed to get txn, err={}", err);
- code = cast_as<ErrCategory::READ>(err);
+ msg = fmt::format("failed to get txn, err={}", err);
+ code = cast_as<ErrCategory::READ>(err);
+ } while (false);
Review Comment:
> remove the `while`, since the `continue` are removed.
done
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1708573142
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,212 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
Review Comment:
warning: function 'commit' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void TxnLazyCommitTask::commit() {
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:51:** 122 lines including whitespace and comments (threshold 80)
```cpp
void TxnLazyCommitTask::commit() {
^
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2304148055
<details>
<summary>TPC-DS: <b>Total hot run time: 187877 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 20e25bf51ae7f01a6fff2f9704c155a8c059045a, data reload: false
query1 912 367 370 367
query2 6460 2003 1946 1946
query3 6646 209 215 209
query4 34307 23218 23202 23202
query5 4138 517 486 486
query6 258 165 157 157
query7 4596 298 296 296
query8 266 213 214 213
query9 8471 2436 2458 2436
query10 438 285 267 267
query11 17646 15092 15030 15030
query12 158 104 96 96
query13 1628 379 367 367
query14 10029 7431 7436 7431
query15 280 174 179 174
query16 8105 462 493 462
query17 1631 592 568 568
query18 2144 303 297 297
query19 338 154 156 154
query20 118 112 108 108
query21 211 107 103 103
query22 4503 4246 4237 4237
query23 34461 33369 33427 33369
query24 11101 2880 2892 2880
query25 656 410 402 402
query26 1405 166 167 166
query27 2811 288 286 286
query28 7129 2040 2033 2033
query29 907 432 433 432
query30 318 169 152 152
query31 989 783 756 756
query32 100 64 64 64
query33 771 299 303 299
query34 955 492 501 492
query35 869 746 719 719
query36 1111 938 950 938
query37 158 88 87 87
query38 3975 3880 3824 3824
query39 1454 1440 1380 1380
query40 274 123 120 120
query41 49 49 52 49
query42 124 107 99 99
query43 522 453 458 453
query44 1183 756 780 756
query45 198 168 170 168
query46 1117 781 750 750
query47 1876 1776 1796 1776
query48 382 307 298 298
query49 1064 437 455 437
query50 823 433 428 428
query51 7200 7009 7031 7009
query52 101 93 93 93
query53 262 189 186 186
query54 1064 467 479 467
query55 82 78 80 78
query56 302 259 267 259
query57 1195 1091 1086 1086
query58 268 229 266 229
query59 2939 2838 2747 2747
query60 314 282 291 282
query61 126 124 128 124
query62 862 670 677 670
query63 232 192 198 192
query64 6619 2326 1740 1740
query65 3258 3261 3168 3168
query66 1365 348 390 348
query67 15659 15165 15311 15165
query68 4826 575 570 570
query69 641 369 298 298
query70 1181 1083 1133 1083
query71 448 285 303 285
query72 7274 2306 2079 2079
query73 785 333 346 333
query74 9276 8868 8766 8766
query75 3742 2708 2746 2708
query76 3163 1016 983 983
query77 679 331 331 331
query78 9843 8989 9581 8989
query79 2803 545 548 545
query80 831 505 519 505
query81 587 233 229 229
query82 1192 142 133 133
query83 287 153 153 153
query84 239 77 78 77
query85 1556 285 283 283
query86 337 304 294 294
query87 4407 4243 4399 4243
query88 3986 2396 2369 2369
query89 399 290 287 287
query90 1638 203 202 202
query91 181 102 101 101
query92 61 58 54 54
query93 2196 567 558 558
query94 616 303 318 303
query95 343 270 264 264
query96 641 275 275 275
query97 3197 3084 3043 3043
query98 231 202 206 202
query99 1731 1270 1290 1270
Total cold run time: 301230 ms
Total hot run time: 187877 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2302343162
<details>
<summary>TPC-DS: <b>Total hot run time: 199083 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 3ecb308aa0ea6ae75918b441fcce5ed28f71c479, data reload: false
query1 1327 922 876 876
query2 6544 1987 1894 1894
query3 10663 4057 4004 4004
query4 59596 27013 23328 23328
query5 5505 687 708 687
query6 454 214 212 212
query7 5801 328 333 328
query8 521 437 440 437
query9 8947 2561 2545 2545
query10 559 349 351 349
query11 16591 15251 15522 15251
query12 205 145 144 144
query13 1636 497 451 451
query14 11528 8031 7960 7960
query15 251 199 193 193
query16 7039 462 501 462
query17 1177 641 631 631
query18 1965 375 346 346
query19 310 172 179 172
query20 160 143 137 137
query21 253 147 147 147
query22 4677 4472 4433 4433
query23 34993 33978 34414 33978
query24 6218 3056 3047 3047
query25 579 433 441 433
query26 705 184 184 184
query27 1708 315 329 315
query28 3623 2184 2175 2175
query29 714 458 457 457
query30 243 206 197 197
query31 1036 887 895 887
query32 110 80 90 80
query33 535 368 369 368
query34 932 515 527 515
query35 880 759 753 753
query36 1130 949 996 949
query37 171 115 112 112
query38 4013 3936 3821 3821
query39 1538 1499 1492 1492
query40 241 160 156 156
query41 139 136 140 136
query42 137 121 115 115
query43 548 520 508 508
query44 1137 801 802 801
query45 224 193 193 193
query46 1117 799 798 798
query47 1966 1863 1842 1842
query48 416 348 347 347
query49 920 601 604 601
query50 912 478 485 478
query51 7343 7126 7043 7043
query52 122 111 111 111
query53 304 230 232 230
query54 647 524 520 520
query55 94 96 94 94
query56 349 339 332 332
query57 1247 1157 1152 1152
query58 298 322 332 322
query59 2996 2754 2791 2754
query60 367 334 340 334
query61 160 152 152 152
query62 801 682 761 682
query63 267 238 239 238
query64 3044 1899 1871 1871
query65 3283 3227 3234 3227
query66 960 679 693 679
query67 15472 15357 15298 15298
query68 4511 616 602 602
query69 472 334 333 333
query70 1242 1170 1139 1139
query71 384 324 328 324
query72 6440 2325 2113 2113
query73 800 368 376 368
query74 9060 8864 8879 8864
query75 3433 2704 2796 2704
query76 1773 1088 1080 1080
query77 674 446 466 446
query78 9879 9232 9017 9017
query79 1136 582 574 574
query80 978 630 630 630
query81 577 262 271 262
query82 861 167 176 167
query83 239 216 268 216
query84 289 97 99 97
query85 853 366 367 366
query86 331 339 324 324
query87 4473 4333 4236 4236
query88 3444 2550 2551 2550
query89 434 348 324 324
query90 1809 242 238 238
query91 159 133 135 133
query92 96 78 77 77
query93 1424 561 557 557
query94 700 333 331 331
query95 398 305 314 305
query96 615 304 285 285
query97 3221 3127 3116 3116
query98 239 227 223 223
query99 1871 1318 1318 1318
Total cold run time: 313163 ms
Total hot run time: 199083 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2314312023
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2314380356
<details>
<summary>TPC-DS: <b>Total hot run time: 195283 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit cbbeda91329c7f9ecaf9f55ca0b98af79b86d7ee, data reload: false
query1 1271 898 869 869
query2 6287 2025 2028 2025
query3 10783 4136 4143 4136
query4 60232 26807 23447 23447
query5 5309 500 499 499
query6 411 162 163 162
query7 5754 300 300 300
query8 316 218 218 218
query9 8643 2501 2480 2480
query10 466 269 273 269
query11 18168 15119 15538 15119
query12 160 105 102 102
query13 1502 403 403 403
query14 10627 7806 7516 7516
query15 225 182 193 182
query16 7262 500 473 473
query17 1102 593 611 593
query18 1981 311 312 311
query19 291 153 154 153
query20 122 119 123 119
query21 212 112 113 112
query22 4733 4626 4523 4523
query23 34472 33691 33805 33691
query24 6008 2936 2862 2862
query25 520 407 401 401
query26 649 165 163 163
query27 1712 279 282 279
query28 3942 2146 2142 2142
query29 678 428 429 428
query30 243 162 163 162
query31 936 771 769 769
query32 81 60 61 60
query33 428 292 293 292
query34 873 486 488 486
query35 833 722 766 722
query36 1058 958 977 958
query37 152 93 94 93
query38 3962 3815 4024 3815
query39 1460 1377 1395 1377
query40 203 123 118 118
query41 49 47 46 46
query42 114 99 101 99
query43 511 487 491 487
query44 1085 748 751 748
query45 199 167 168 167
query46 1096 773 763 763
query47 1866 1828 1802 1802
query48 385 300 304 300
query49 783 440 445 440
query50 826 440 420 420
query51 7263 7137 7115 7115
query52 97 89 90 89
query53 259 184 188 184
query54 577 478 473 473
query55 77 81 83 81
query56 279 267 270 267
query57 1192 1109 1080 1080
query58 233 250 228 228
query59 3129 2899 3049 2899
query60 296 266 275 266
query61 104 94 92 92
query62 768 664 635 635
query63 211 182 181 181
query64 2471 675 663 663
query65 3236 3161 3194 3161
query66 657 333 367 333
query67 15576 15299 15303 15299
query68 4378 571 560 560
query69 528 372 299 299
query70 1153 1067 1063 1063
query71 400 279 281 279
query72 6470 4107 4002 4002
query73 778 337 334 334
query74 9234 8848 9004 8848
query75 3389 2725 2754 2725
query76 1682 1036 1060 1036
query77 648 321 318 318
query78 11039 9489 9257 9257
query79 1976 537 547 537
query80 813 534 501 501
query81 567 236 242 236
query82 471 153 147 147
query83 175 151 150 150
query84 271 77 74 74
query85 731 292 316 292
query86 399 307 294 294
query87 4416 4276 4460 4276
query88 3373 2332 2346 2332
query89 392 285 282 282
query90 1964 193 195 193
query91 125 99 98 98
query92 58 53 52 52
query93 1505 544 548 544
query94 709 307 284 284
query95 364 271 264 264
query96 604 273 272 272
query97 3238 3105 3088 3088
query98 234 217 226 217
query99 1625 1286 1282 1282
Total cold run time: 311115 ms
Total hot run time: 195283 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2314387526
<details>
<summary>ClickBench: <b>Total hot run time: 31.9 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit cbbeda91329c7f9ecaf9f55ca0b98af79b86d7ee, data reload: false
query1 0.04 0.04 0.04
query2 0.07 0.04 0.04
query3 0.23 0.05 0.05
query4 1.68 0.08 0.09
query5 0.52 0.50 0.50
query6 1.14 0.74 0.73
query7 0.02 0.02 0.01
query8 0.05 0.05 0.05
query9 0.56 0.50 0.49
query10 0.55 0.53 0.54
query11 0.16 0.12 0.12
query12 0.16 0.13 0.13
query13 0.62 0.61 0.59
query14 2.07 2.05 2.14
query15 0.85 0.82 0.83
query16 0.38 0.38 0.38
query17 1.08 1.07 1.01
query18 0.21 0.20 0.21
query19 1.98 1.80 1.68
query20 0.01 0.01 0.01
query21 15.42 0.68 0.66
query22 3.75 7.63 1.74
query23 18.27 1.44 1.28
query24 2.07 0.24 0.22
query25 0.14 0.09 0.08
query26 0.28 0.18 0.17
query27 0.08 0.08 0.07
query28 13.66 1.02 1.00
query29 12.67 3.41 3.34
query30 0.25 0.06 0.05
query31 2.86 0.40 0.39
query32 3.26 0.49 0.48
query33 2.97 3.06 3.02
query34 17.13 4.37 4.42
query35 4.48 4.53 4.43
query36 0.66 0.48 0.48
query37 0.19 0.16 0.15
query38 0.15 0.15 0.16
query39 0.05 0.04 0.04
query40 0.16 0.13 0.14
query41 0.10 0.05 0.05
query42 0.07 0.05 0.06
query43 0.05 0.04 0.04
Total cold run time: 111.1 s
Total hot run time: 31.9 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2272472453
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1706546681
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -788,6 +788,164 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
txn->put(key, val);
}
}
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
Review Comment:
> `partition_versions` is not needed here, since all rowsets belong to the same partition. Read the partition version in here directly.
`convert_tmp_rowsets` is a common api, all roswets not belong to the same partition also work
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2290937110
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2286243101
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2286433958
<details>
<summary>TPC-H: <b>Total hot run time: 40288 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 814829fad0b51598e72ff1c3c1e78f4f3225389e, data reload: false
------ Round 1 ----------------------------------
q1 18298 4620 4309 4309
q2 2031 186 182 182
q3 11493 1035 1107 1035
q4 10529 716 700 700
q5 7766 2871 2836 2836
q6 224 140 143 140
q7 969 594 602 594
q8 9352 2072 2112 2072
q9 8621 6549 6576 6549
q10 7070 2253 2201 2201
q11 457 254 256 254
q12 392 222 222 222
q13 18130 2961 2995 2961
q14 270 244 230 230
q15 534 498 498 498
q16 646 510 527 510
q17 992 674 729 674
q18 8147 7359 7419 7359
q19 6085 1089 1023 1023
q20 740 414 411 411
q21 5448 4525 4538 4525
q22 1101 1003 1016 1003
Total cold run time: 119295 ms
Total hot run time: 40288 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4503 4260 4267 4260
q2 393 281 273 273
q3 2944 2779 2758 2758
q4 1945 1758 1743 1743
q5 5639 5621 5540 5540
q6 238 139 138 138
q7 2220 1783 1748 1748
q8 3341 3481 3480 3480
q9 8768 8866 8848 8848
q10 3472 3214 3265 3214
q11 620 528 501 501
q12 848 667 645 645
q13 17066 3144 3151 3144
q14 319 288 287 287
q15 542 498 486 486
q16 635 583 579 579
q17 1821 1524 1549 1524
q18 8226 7975 7871 7871
q19 1868 1605 1708 1605
q20 3147 1963 1993 1963
q21 7727 5299 5379 5299
q22 1129 1043 1052 1043
Total cold run time: 77411 ms
Total hot run time: 56949 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2298075542
PR approved by at least one committer and no changes requested.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2297065838
<details>
<summary>ClickBench: <b>Total hot run time: 30.99 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 26c7330ea2ca69f58795f6cc0b7821111e82c0d5, data reload: false
query1 0.05 0.04 0.04
query2 0.09 0.04 0.05
query3 0.22 0.06 0.04
query4 1.67 0.07 0.07
query5 0.50 0.50 0.50
query6 1.14 0.73 0.72
query7 0.02 0.02 0.02
query8 0.06 0.05 0.05
query9 0.55 0.49 0.50
query10 0.54 0.53 0.56
query11 0.16 0.12 0.12
query12 0.16 0.13 0.12
query13 0.62 0.60 0.59
query14 0.77 0.79 0.77
query15 0.85 0.84 0.82
query16 0.36 0.35 0.39
query17 1.02 1.03 1.04
query18 0.22 0.20 0.19
query19 1.88 1.76 1.73
query20 0.02 0.01 0.01
query21 15.41 0.68 0.65
query22 3.97 8.23 1.79
query23 18.24 1.34 1.34
query24 2.17 0.21 0.22
query25 0.16 0.08 0.09
query26 0.28 0.19 0.17
query27 0.09 0.08 0.08
query28 13.19 1.02 1.00
query29 12.64 3.33 3.30
query30 0.43 0.25 0.24
query31 2.81 0.41 0.41
query32 3.25 0.49 0.50
query33 2.98 2.99 2.97
query34 17.13 4.41 4.37
query35 4.41 4.44 4.47
query36 0.67 0.51 0.51
query37 0.22 0.18 0.17
query38 0.17 0.16 0.16
query39 0.07 0.06 0.05
query40 0.19 0.15 0.15
query41 0.12 0.06 0.06
query42 0.07 0.06 0.06
query43 0.06 0.06 0.06
Total cold run time: 109.63 s
Total hot run time: 30.99 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2245520383
<details>
<summary>TPC-H: <b>Total hot run time: 40400 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit a7e2b1bd85dd3827c86fb9ead1aa462b016a3aba, data reload: false
------ Round 1 ----------------------------------
q1 18792 7352 4251 4251
q2 2021 202 185 185
q3 10539 1167 1066 1066
q4 10298 778 816 778
q5 7549 2694 2668 2668
q6 222 139 136 136
q7 969 594 583 583
q8 9200 2070 2049 2049
q9 8685 6594 6523 6523
q10 8708 3782 3771 3771
q11 464 232 233 232
q12 387 216 218 216
q13 17801 3008 2997 2997
q14 289 228 241 228
q15 521 476 493 476
q16 498 388 370 370
q17 951 615 671 615
q18 8136 7389 7379 7379
q19 6302 1449 1418 1418
q20 649 329 313 313
q21 4889 3895 3863 3863
q22 339 285 283 283
Total cold run time: 118209 ms
Total hot run time: 40400 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4376 4238 4225 4225
q2 371 275 288 275
q3 3167 2889 2929 2889
q4 2046 1686 1636 1636
q5 5561 5472 5560 5472
q6 227 133 132 132
q7 2198 1765 1833 1765
q8 3272 3391 3371 3371
q9 8706 8901 8628 8628
q10 4037 3781 3873 3781
q11 573 504 492 492
q12 794 622 624 622
q13 17154 3183 3183 3183
q14 319 285 297 285
q15 518 499 479 479
q16 484 440 413 413
q17 1832 1536 1487 1487
q18 8250 7937 7726 7726
q19 1719 1522 1542 1522
q20 2168 1851 1844 1844
q21 5142 4646 4859 4646
q22 561 512 520 512
Total cold run time: 73475 ms
Total hot run time: 55385 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2244658181
<details>
<summary>TPC-DS: <b>Total hot run time: 173045 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 0cac9c57dfbabd3aa3c3d90819462ad7e839f881, data reload: false
query1 903 376 374 374
query2 6431 1960 1851 1851
query3 6653 205 210 205
query4 25068 17541 17450 17450
query5 4183 478 478 478
query6 272 162 162 162
query7 4592 280 286 280
query8 237 202 218 202
query9 8631 2398 2375 2375
query10 457 296 272 272
query11 10780 10084 10096 10084
query12 140 90 82 82
query13 1633 371 366 366
query14 10095 7647 7731 7647
query15 226 167 168 167
query16 7766 444 474 444
query17 1587 565 553 553
query18 1827 291 289 289
query19 207 155 156 155
query20 90 84 82 82
query21 212 134 128 128
query22 4411 3962 3969 3962
query23 33979 33094 33140 33094
query24 11103 2927 2807 2807
query25 662 401 390 390
query26 1485 160 154 154
query27 2893 276 273 273
query28 7510 1977 1973 1973
query29 1000 662 629 629
query30 286 156 151 151
query31 976 739 745 739
query32 95 54 65 54
query33 794 351 359 351
query34 900 493 487 487
query35 933 755 762 755
query36 1133 917 918 917
query37 151 84 83 83
query38 2859 2762 2751 2751
query39 868 811 836 811
query40 283 126 120 120
query41 52 46 48 46
query42 113 98 108 98
query43 522 464 474 464
query44 1255 728 722 722
query45 197 165 162 162
query46 1088 822 740 740
query47 1843 1744 1755 1744
query48 351 287 290 287
query49 1138 426 422 422
query50 784 399 390 390
query51 6742 6757 6678 6678
query52 109 94 96 94
query53 366 299 282 282
query54 1020 450 446 446
query55 75 72 71 71
query56 290 283 277 277
query57 1195 1061 1041 1041
query58 256 256 261 256
query59 2924 2817 2677 2677
query60 307 278 298 278
query61 98 117 95 95
query62 828 664 663 663
query63 320 291 301 291
query64 10595 2243 1689 1689
query65 3207 3102 3096 3096
query66 1306 340 340 340
query67 15601 14971 14717 14717
query68 4963 530 543 530
query69 553 337 351 337
query70 1201 1161 1010 1010
query71 459 286 289 286
query72 8821 5691 5593 5593
query73 762 328 323 323
query74 6146 5612 5636 5612
query75 4391 2698 2707 2698
query76 3331 937 893 893
query77 703 320 297 297
query78 11692 9404 9046 9046
query79 7963 520 519 519
query80 1067 488 492 488
query81 596 230 234 230
query82 658 135 130 130
query83 352 167 169 167
query84 275 85 87 85
query85 792 371 301 301
query86 479 296 316 296
query87 3327 3091 3094 3091
query88 4491 2376 2390 2376
query89 510 371 386 371
query90 1961 199 197 197
query91 136 100 104 100
query92 68 51 49 49
query93 4526 503 490 490
query94 1197 295 296 295
query95 409 328 315 315
query96 602 272 268 268
query97 3171 3043 3014 3014
query98 218 204 201 201
query99 1727 1224 1234 1224
Total cold run time: 294440 ms
Total hot run time: 173045 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2250621990
<details>
<summary>TPC-DS: <b>Total hot run time: 173957 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 9511fed37daee25d5ec0c6d5a1033b69e5eddf44, data reload: false
query1 907 379 364 364
query2 6450 1920 1771 1771
query3 6645 212 223 212
query4 28599 17564 17378 17378
query5 3757 505 522 505
query6 259 177 163 163
query7 4603 292 294 292
query8 243 199 191 191
query9 8619 2476 2428 2428
query10 424 305 260 260
query11 12272 10097 10053 10053
query12 119 83 88 83
query13 1618 369 367 367
query14 8708 7890 7891 7890
query15 222 170 172 170
query16 7490 490 479 479
query17 1136 560 545 545
query18 1975 286 278 278
query19 200 149 152 149
query20 98 92 89 89
query21 209 102 102 102
query22 4293 4072 4032 4032
query23 34289 34043 33923 33923
query24 11081 2979 2852 2852
query25 622 427 425 425
query26 733 163 160 160
query27 2288 292 283 283
query28 6051 2105 2097 2097
query29 831 471 455 455
query30 272 167 160 160
query31 994 769 760 760
query32 98 54 59 54
query33 719 380 355 355
query34 921 502 497 497
query35 878 756 749 749
query36 1139 999 952 952
query37 140 84 82 82
query38 2990 2857 2820 2820
query39 920 851 853 851
query40 213 122 123 122
query41 47 44 45 44
query42 112 96 96 96
query43 507 467 455 455
query44 1124 726 734 726
query45 204 174 175 174
query46 1088 732 776 732
query47 1830 1769 1754 1754
query48 382 283 308 283
query49 843 417 427 417
query50 802 404 404 404
query51 6707 6663 6709 6663
query52 110 86 94 86
query53 270 190 183 183
query54 858 443 440 440
query55 79 75 72 72
query56 295 287 270 270
query57 1123 1047 1035 1035
query58 242 268 259 259
query59 2864 2593 2607 2593
query60 321 291 281 281
query61 120 93 93 93
query62 787 662 621 621
query63 210 184 187 184
query64 9236 2279 1770 1770
query65 3148 3096 3113 3096
query66 773 330 350 330
query67 15550 14902 14887 14887
query68 4608 553 557 553
query69 539 296 308 296
query70 1102 1138 1123 1123
query71 417 294 328 294
query72 8551 5290 5347 5290
query73 770 374 337 337
query74 6020 5670 5675 5670
query75 3518 2729 2629 2629
query76 2635 953 892 892
query77 658 323 326 323
query78 10463 9003 9161 9003
query79 2349 527 537 527
query80 2598 495 503 495
query81 606 222 216 216
query82 805 137 140 137
query83 324 179 177 177
query84 268 80 83 80
query85 1931 312 308 308
query86 443 308 297 297
query87 3238 3106 3081 3081
query88 4272 2392 2395 2392
query89 399 294 286 286
query90 1937 197 195 195
query91 127 101 100 100
query92 58 52 50 50
query93 2614 555 571 555
query94 769 290 285 285
query95 364 263 339 263
query96 611 268 277 268
query97 3201 3029 3051 3029
query98 228 205 205 205
query99 1740 1255 1267 1255
Total cold run time: 281820 ms
Total hot run time: 173957 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2250578064
<details>
<summary>TPC-H: <b>Total hot run time: 39691 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 9511fed37daee25d5ec0c6d5a1033b69e5eddf44, data reload: false
------ Round 1 ----------------------------------
q1 18811 4758 4467 4467
q2 2040 200 196 196
q3 10519 1189 1081 1081
q4 10174 739 745 739
q5 7579 2739 2718 2718
q6 226 140 139 139
q7 966 596 595 595
q8 9232 1919 1946 1919
q9 8840 6535 6598 6535
q10 8827 3787 3812 3787
q11 456 244 247 244
q12 408 225 231 225
q13 19056 2969 2996 2969
q14 283 239 244 239
q15 525 468 501 468
q16 497 393 385 385
q17 980 640 706 640
q18 8179 7546 7485 7485
q19 3813 1068 1077 1068
q20 703 351 339 339
q21 4977 3167 3330 3167
q22 353 287 286 286
Total cold run time: 117444 ms
Total hot run time: 39691 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4467 4261 4262 4261
q2 368 272 266 266
q3 3009 2900 2855 2855
q4 2049 1690 1806 1690
q5 5653 5529 5499 5499
q6 222 137 144 137
q7 2191 1861 1847 1847
q8 3274 3420 3477 3420
q9 8807 8824 8867 8824
q10 4161 3860 3843 3843
q11 612 512 514 512
q12 818 650 644 644
q13 16136 3184 3231 3184
q14 333 298 290 290
q15 533 512 508 508
q16 499 461 446 446
q17 1820 1546 1508 1508
q18 8130 8162 7951 7951
q19 1729 1590 1651 1590
q20 2159 1861 1898 1861
q21 5038 4803 4769 4769
q22 585 485 505 485
Total cold run time: 72593 ms
Total hot run time: 56390 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1708565085
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,208 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
+ std::stringstream ss;
+ do {
+ code_ = MetaServiceCode::OK;
+ msg_.clear();
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id_, txn_id_, txn_kv_, code_, msg_, &db_id, &tmp_rowset_metas);
+ if (code_ != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id_ << " code=" << code_;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id_
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id_;
+ break;
Review Comment:
> Even if the tmp_rowset_metas is empty, the TXN might still not be visible. Consider call `make_committed_txn_visible` here.
done, i have removed the `break`
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2259590990
<details>
<summary>TPC-DS: <b>Total hot run time: 171014 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 8ed44221f04cb0a14f7132c207fbd3cf93e572f1, data reload: false
query1 924 382 383 382
query2 6468 1796 1679 1679
query3 6663 209 223 209
query4 20108 17608 17528 17528
query5 3662 511 519 511
query6 265 168 157 157
query7 4468 299 292 292
query8 261 194 191 191
query9 7635 2391 2388 2388
query10 399 280 268 268
query11 10526 10127 10078 10078
query12 124 90 88 88
query13 1474 400 374 374
query14 9689 8623 8296 8296
query15 204 168 163 163
query16 6823 474 445 445
query17 928 548 548 548
query18 1886 300 278 278
query19 188 147 141 141
query20 91 87 85 85
query21 197 103 98 98
query22 4294 4137 4012 4012
query23 33920 33821 33437 33437
query24 10284 3131 3150 3131
query25 665 408 414 408
query26 1686 164 148 148
query27 2899 273 280 273
query28 7622 2018 1996 1996
query29 1286 431 493 431
query30 248 157 154 154
query31 927 775 775 775
query32 98 62 56 56
query33 652 332 319 319
query34 917 500 497 497
query35 887 773 755 755
query36 1089 923 887 887
query37 296 84 84 84
query38 3011 2853 2805 2805
query39 868 799 804 799
query40 273 114 115 114
query41 46 43 45 43
query42 123 100 96 96
query43 483 448 440 440
query44 1172 747 736 736
query45 207 183 181 181
query46 1086 826 788 788
query47 1785 1700 1703 1700
query48 367 300 304 300
query49 959 455 414 414
query50 923 432 437 432
query51 6761 6808 6629 6629
query52 95 94 87 87
query53 252 184 185 184
query54 582 446 459 446
query55 78 74 76 74
query56 266 253 248 248
query57 1131 1032 1000 1000
query58 282 263 266 263
query59 2793 2398 2502 2398
query60 291 279 270 270
query61 94 94 96 94
query62 875 659 655 655
query63 218 183 190 183
query64 5666 1944 1874 1874
query65 3190 3080 3095 3080
query66 1321 337 325 325
query67 15311 14794 14663 14663
query68 4227 547 564 547
query69 543 346 312 312
query70 1105 1029 1118 1029
query71 412 286 277 277
query72 7008 2714 2474 2474
query73 765 332 329 329
query74 5984 5697 5561 5561
query75 3406 2732 2744 2732
query76 2318 1347 1412 1347
query77 406 313 310 310
query78 9328 8954 8944 8944
query79 1495 541 535 535
query80 938 498 547 498
query81 556 226 227 226
query82 823 127 124 124
query83 258 170 173 170
query84 265 79 79 79
query85 1412 305 296 296
query86 491 304 319 304
query87 3356 3077 3108 3077
query88 3702 2397 2409 2397
query89 380 288 295 288
query90 1779 188 194 188
query91 124 99 101 99
query92 63 51 51 51
query93 2069 613 617 613
query94 776 309 285 285
query95 384 266 266 266
query96 612 283 275 275
query97 3214 3017 3046 3017
query98 230 206 197 197
query99 1678 1308 1284 1284
Total cold run time: 261369 ms
Total hot run time: 171014 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2274915525
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2245374489
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2245549983
<details>
<summary>TPC-DS: <b>Total hot run time: 174268 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit a7e2b1bd85dd3827c86fb9ead1aa462b016a3aba, data reload: false
query1 912 373 376 373
query2 6371 1871 1800 1800
query3 6641 204 216 204
query4 28243 17484 17186 17186
query5 3760 466 462 462
query6 262 188 172 172
query7 4573 294 281 281
query8 238 192 189 189
query9 8532 2427 2431 2427
query10 441 295 275 275
query11 11762 10107 10087 10087
query12 114 81 81 81
query13 1623 369 353 353
query14 10048 7513 7638 7513
query15 215 162 158 158
query16 7488 469 457 457
query17 1384 573 513 513
query18 1847 275 269 269
query19 195 145 147 145
query20 88 80 79 79
query21 202 127 123 123
query22 4267 4026 3993 3993
query23 34119 33647 33662 33647
query24 10994 2936 2928 2928
query25 620 386 396 386
query26 708 155 149 149
query27 2423 273 278 273
query28 6388 2089 2106 2089
query29 911 627 637 627
query30 278 154 155 154
query31 975 778 769 769
query32 101 54 53 53
query33 720 334 335 334
query34 904 495 493 493
query35 877 758 756 756
query36 1166 962 973 962
query37 141 83 82 82
query38 2939 2882 2979 2882
query39 865 833 800 800
query40 203 121 119 119
query41 46 44 47 44
query42 113 96 102 96
query43 500 459 460 459
query44 1137 727 728 727
query45 192 162 162 162
query46 1101 761 732 732
query47 1849 1796 1756 1756
query48 371 295 300 295
query49 868 416 425 416
query50 765 385 383 383
query51 6757 6699 6656 6656
query52 103 91 91 91
query53 361 293 283 283
query54 955 454 456 454
query55 75 73 72 72
query56 301 280 288 280
query57 1137 1033 1060 1033
query58 268 282 292 282
query59 2739 2670 2450 2450
query60 314 291 288 288
query61 120 115 120 115
query62 803 662 646 646
query63 318 289 288 288
query64 9235 2287 7542 2287
query65 3127 3116 3090 3090
query66 760 340 346 340
query67 15665 15032 14933 14933
query68 6166 547 555 547
query69 768 466 383 383
query70 1316 1158 1095 1095
query71 501 274 285 274
query72 8876 5462 5718 5462
query73 752 327 324 324
query74 6289 5716 5739 5716
query75 4470 2712 2672 2672
query76 4033 922 930 922
query77 732 299 294 294
query78 9595 8950 8940 8940
query79 7861 522 523 522
query80 2347 489 472 472
query81 590 223 260 223
query82 1092 140 137 137
query83 282 164 163 163
query84 278 84 84 84
query85 1329 317 306 306
query86 448 304 321 304
query87 3272 3077 3103 3077
query88 5184 2406 2412 2406
query89 510 393 385 385
query90 1984 199 192 192
query91 129 98 104 98
query92 61 49 48 48
query93 6449 519 527 519
query94 1239 282 291 282
query95 413 321 332 321
query96 629 281 272 272
query97 3187 3042 3046 3042
query98 211 210 241 210
query99 1589 1286 1275 1275
Total cold run time: 297100 ms
Total hot run time: 174268 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2245114473
<details>
<summary>ClickBench: <b>Total hot run time: 31.44 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit d47f33a15e68079183da96a15302b529dc1c36a2, data reload: false
query1 0.05 0.04 0.04
query2 0.07 0.04 0.04
query3 0.23 0.05 0.05
query4 1.67 0.08 0.08
query5 0.52 0.49 0.50
query6 1.12 0.73 0.74
query7 0.02 0.01 0.01
query8 0.06 0.05 0.04
query9 0.55 0.50 0.49
query10 0.55 0.55 0.54
query11 0.15 0.12 0.12
query12 0.15 0.12 0.12
query13 0.59 0.59 0.58
query14 0.76 0.77 0.78
query15 0.85 0.82 0.81
query16 0.35 0.35 0.38
query17 0.96 0.94 0.96
query18 0.23 0.22 0.22
query19 1.77 1.68 1.73
query20 0.01 0.01 0.01
query21 15.39 0.74 0.65
query22 4.62 6.41 2.77
query23 18.36 1.42 1.28
query24 2.11 0.22 0.23
query25 0.14 0.09 0.09
query26 0.29 0.21 0.21
query27 0.45 0.24 0.24
query28 13.27 1.02 1.02
query29 12.62 3.30 3.29
query30 0.25 0.06 0.05
query31 2.90 0.40 0.40
query32 3.23 0.49 0.47
query33 2.87 2.89 2.95
query34 17.08 4.33 4.37
query35 4.41 4.39 4.40
query36 0.65 0.45 0.46
query37 0.19 0.16 0.15
query38 0.16 0.15 0.14
query39 0.05 0.04 0.04
query40 0.15 0.12 0.12
query41 0.09 0.04 0.05
query42 0.06 0.05 0.05
query43 0.04 0.04 0.04
Total cold run time: 110.04 s
Total hot run time: 31.44 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1733771936
##########
cloud/src/recycler/recycler.cpp:
##########
@@ -1119,6 +1200,12 @@ int InstanceRecycler::recycle_tablets(int64_t table_id, int64_t index_id, int64_
return -1;
}
int64_t tablet_id = tablet_meta_pb.tablet_id();
+
+ if (!check_lazy_txn_finished(txn_kv_, instance_id_, tablet_meta_pb.tablet_id())) {
+ LOG(WARNING) << "lazy txn not finished tablet_id=" << tablet_meta_pb.tablet_id();
Review Comment:
> LOG "lazy txn not finished, skip recycling. tablet_id= ... txn_id ..." and add a bvar to monitor `skip_recyle_tablet_lazy_txn`
int the `check_lazy_txn_finished `, every abnormal branch has more detail log
##########
cloud/src/recycler/recycler.cpp:
##########
@@ -1119,6 +1200,12 @@ int InstanceRecycler::recycle_tablets(int64_t table_id, int64_t index_id, int64_
return -1;
}
int64_t tablet_id = tablet_meta_pb.tablet_id();
+
+ if (!check_lazy_txn_finished(txn_kv_, instance_id_, tablet_meta_pb.tablet_id())) {
+ LOG(WARNING) << "lazy txn not finished tablet_id=" << tablet_meta_pb.tablet_id();
Review Comment:
> LOG "lazy txn not finished, skip recycling. tablet_id= ... txn_id ..." and add a bvar to monitor `skip_recyle_tablet_lazy_txn`
in the `check_lazy_txn_finished `, every abnormal branch has more detail log
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1733036625
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,475 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
Review Comment:
warning: function 'convert_tmp_rowsets' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void convert_tmp_rowsets(
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:40:** 154 lines including whitespace and comments (threshold 80)
```cpp
void convert_tmp_rowsets(
^
```
</details>
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,475 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+ DCHECK(version_pb.txn_ids_size() > 0);
+ DCHECK_EQ(version_pb.txn_ids(0), txn_id);
+
+ int64_t version = version_pb.has_version() ? (version_pb.version() + 1) : 2;
+
+ std::string rowset_key = meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ // tmp rowset key has been converted
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version);
+ tmp_rowset_pb.set_end_version(version);
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
Review Comment:
warning: function 'make_committed_txn_visible' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:200:** 82 lines including whitespace and comments (threshold 80)
```cpp
void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
^
```
</details>
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,475 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+ DCHECK(version_pb.txn_ids_size() > 0);
+ DCHECK_EQ(version_pb.txn_ids(0), txn_id);
+
+ int64_t version = version_pb.has_version() ? (version_pb.version() + 1) : 2;
+
+ std::string rowset_key = meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ // tmp rowset key has been converted
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version);
+ tmp_rowset_pb.set_end_version(version);
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(recycle_key, recycle_val);
+ LOG(INFO) << "put recycle_key=" << hex(recycle_key) << " txn_id=" << txn_id;
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+ }
+}
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
Review Comment:
warning: function 'commit' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void TxnLazyCommitTask::commit() {
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:296:** 138 lines including whitespace and comments (threshold 80)
```cpp
void TxnLazyCommitTask::commit() {
^
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2312931990
<details>
<summary>TPC-H: <b>Total hot run time: 38230 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 40557e2131ead7df254d700743017f557f0777e6, data reload: false
------ Round 1 ----------------------------------
q1 17711 4543 4324 4324
q2 2018 199 171 171
q3 11601 990 1079 990
q4 10486 659 727 659
q5 7748 2839 2779 2779
q6 225 137 137 137
q7 985 617 612 612
q8 9318 2062 2084 2062
q9 7205 6534 6530 6530
q10 7012 2266 2255 2255
q11 449 246 251 246
q12 401 219 224 219
q13 17765 3017 3012 3012
q14 277 228 225 225
q15 532 483 488 483
q16 489 398 389 389
q17 974 636 726 636
q18 7507 6936 6959 6936
q19 1398 1086 1052 1052
q20 699 324 339 324
q21 4320 3156 3167 3156
q22 1120 1033 1033 1033
Total cold run time: 110240 ms
Total hot run time: 38230 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4368 4350 4321 4321
q2 382 276 269 269
q3 2895 2682 2687 2682
q4 1944 1589 1654 1589
q5 5615 5696 5751 5696
q6 231 139 142 139
q7 2246 1859 1790 1790
q8 3292 3435 3491 3435
q9 8903 8729 8782 8729
q10 3568 3422 3394 3394
q11 607 533 514 514
q12 830 674 636 636
q13 13700 3194 3203 3194
q14 323 291 291 291
q15 530 501 503 501
q16 513 448 435 435
q17 1844 1527 1533 1527
q18 8147 7748 7744 7744
q19 1752 1507 1601 1507
q20 2145 1933 1929 1929
q21 5787 5364 5580 5364
q22 1099 1059 1058 1058
Total cold run time: 70721 ms
Total hot run time: 56744 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2314139153
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2317508011
PR approved by at least one committer and no changes requested.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1732239346
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(recycle_key, recycle_val);
Review Comment:
> log
Add a log
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1713235462
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -1405,104 +1438,144 @@ void MetaServiceImpl::get_rowset(::google::protobuf::RpcController* controller,
int64_t req_cc_cnt = request->cumulative_compaction_cnt();
int64_t req_cp = request->cumulative_point();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv_->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- msg = "failed to create txn";
- return;
- }
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ msg = "failed to create txn";
+ return;
+ }
- TabletIndexPB idx(request->idx());
- // Get tablet id index from kv
- if (!idx.has_table_id() || !idx.has_index_id() || !idx.has_partition_id()) {
+ TabletIndexPB idx;
+ // Get tablet id index from kv
get_tablet_idx(code, msg, txn.get(), instance_id, tablet_id, idx);
- if (code != MetaServiceCode::OK) return;
- }
- // TODO(plat1ko): Judge if tablet has been dropped (in dropped index/partition)
-
- TabletStatsPB tablet_stat;
- internal_get_tablet_stats(code, msg, txn.get(), instance_id, idx, tablet_stat, true);
- if (code != MetaServiceCode::OK) return;
- VLOG_DEBUG << "tablet_id=" << tablet_id << " stats=" << proto_to_json(tablet_stat);
-
- int64_t bc_cnt = tablet_stat.base_compaction_cnt();
- int64_t cc_cnt = tablet_stat.cumulative_compaction_cnt();
- int64_t cp = tablet_stat.cumulative_point();
-
- response->mutable_stats()->CopyFrom(tablet_stat);
-
- int64_t req_start = request->start_version();
- int64_t req_end = request->end_version();
- req_end = req_end < 0 ? std::numeric_limits<int64_t>::max() - 1 : req_end;
-
- //==========================================================================
- // Find version ranges to be synchronized due to compaction
- //==========================================================================
- if (req_bc_cnt > bc_cnt || req_cc_cnt > cc_cnt || req_cp > cp) {
- code = MetaServiceCode::INVALID_ARGUMENT;
- ss << "no valid compaction_cnt or cumulative_point given. req_bc_cnt=" << req_bc_cnt
- << ", bc_cnt=" << bc_cnt << ", req_cc_cnt=" << req_cc_cnt << ", cc_cnt=" << cc_cnt
- << ", req_cp=" << req_cp << ", cp=" << cp;
- msg = ss.str();
- return;
- }
- auto versions = calc_sync_versions(req_bc_cnt, bc_cnt, req_cc_cnt, cc_cnt, req_cp, cp,
- req_start, req_end);
- for (auto [start, end] : versions) {
- internal_get_rowset(txn.get(), start, end, instance_id, tablet_id, code, msg, response);
if (code != MetaServiceCode::OK) {
return;
}
- }
+ DCHECK(request->has_idx());
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id, idx.db_id(), idx.table_id(), idx.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, tablet_id=" << tablet_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // get referenced schema
- std::unordered_map<int32_t, doris::TabletSchemaCloudPB*> version_to_schema;
- for (auto& rowset_meta : *response->mutable_rowset_meta()) {
- if (rowset_meta.has_tablet_schema()) {
- version_to_schema.emplace(rowset_meta.tablet_schema().schema_version(),
- rowset_meta.mutable_tablet_schema());
- rowset_meta.set_schema_version(rowset_meta.tablet_schema().schema_version());
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb tablet_id=" << tablet_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
}
- rowset_meta.set_index_id(idx.index_id());
- }
- bool need_read_schema_dict = false;
- auto arena = response->GetArena();
- for (auto& rowset_meta : *response->mutable_rowset_meta()) {
- if (rowset_meta.has_schema_dict_key_list()) {
- need_read_schema_dict = true;
+
+ if (version_pb.has_txn_id()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer_->submit(instance_id, version_pb.txn_id());
+
+ std::tie(code, msg) = task->wait();
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << version_pb.txn_id()
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
+ continue;
}
- if (rowset_meta.has_tablet_schema()) continue;
- if (!rowset_meta.has_schema_version()) {
+
+ // TODO(plat1ko): Judge if tablet has been dropped (in dropped index/partition)
+
+ TabletStatsPB tablet_stat;
+ internal_get_tablet_stats(code, msg, txn.get(), instance_id, idx, tablet_stat, true);
+ if (code != MetaServiceCode::OK) return;
Review Comment:
warning: statement should be inside braces [readability-braces-around-statements]
```suggestion
if (code != MetaServiceCode::OK) { return;
}
```
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -1405,104 +1438,144 @@
int64_t req_cc_cnt = request->cumulative_compaction_cnt();
int64_t req_cp = request->cumulative_point();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv_->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- msg = "failed to create txn";
- return;
- }
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ msg = "failed to create txn";
+ return;
+ }
- TabletIndexPB idx(request->idx());
- // Get tablet id index from kv
- if (!idx.has_table_id() || !idx.has_index_id() || !idx.has_partition_id()) {
+ TabletIndexPB idx;
+ // Get tablet id index from kv
get_tablet_idx(code, msg, txn.get(), instance_id, tablet_id, idx);
- if (code != MetaServiceCode::OK) return;
- }
- // TODO(plat1ko): Judge if tablet has been dropped (in dropped index/partition)
-
- TabletStatsPB tablet_stat;
- internal_get_tablet_stats(code, msg, txn.get(), instance_id, idx, tablet_stat, true);
- if (code != MetaServiceCode::OK) return;
- VLOG_DEBUG << "tablet_id=" << tablet_id << " stats=" << proto_to_json(tablet_stat);
-
- int64_t bc_cnt = tablet_stat.base_compaction_cnt();
- int64_t cc_cnt = tablet_stat.cumulative_compaction_cnt();
- int64_t cp = tablet_stat.cumulative_point();
-
- response->mutable_stats()->CopyFrom(tablet_stat);
-
- int64_t req_start = request->start_version();
- int64_t req_end = request->end_version();
- req_end = req_end < 0 ? std::numeric_limits<int64_t>::max() - 1 : req_end;
-
- //==========================================================================
- // Find version ranges to be synchronized due to compaction
- //==========================================================================
- if (req_bc_cnt > bc_cnt || req_cc_cnt > cc_cnt || req_cp > cp) {
- code = MetaServiceCode::INVALID_ARGUMENT;
- ss << "no valid compaction_cnt or cumulative_point given. req_bc_cnt=" << req_bc_cnt
- << ", bc_cnt=" << bc_cnt << ", req_cc_cnt=" << req_cc_cnt << ", cc_cnt=" << cc_cnt
- << ", req_cp=" << req_cp << ", cp=" << cp;
- msg = ss.str();
- return;
- }
- auto versions = calc_sync_versions(req_bc_cnt, bc_cnt, req_cc_cnt, cc_cnt, req_cp, cp,
- req_start, req_end);
- for (auto [start, end] : versions) {
- internal_get_rowset(txn.get(), start, end, instance_id, tablet_id, code, msg, response);
if (code != MetaServiceCode::OK) {
return;
}
- }
+ DCHECK(request->has_idx());
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id, idx.db_id(), idx.table_id(), idx.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, tablet_id=" << tablet_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // get referenced schema
- std::unordered_map<int32_t, doris::TabletSchemaCloudPB*> version_to_schema;
- for (auto& rowset_meta : *response->mutable_rowset_meta()) {
- if (rowset_meta.has_tablet_schema()) {
- version_to_schema.emplace(rowset_meta.tablet_schema().schema_version(),
- rowset_meta.mutable_tablet_schema());
- rowset_meta.set_schema_version(rowset_meta.tablet_schema().schema_version());
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb tablet_id=" << tablet_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
}
- rowset_meta.set_index_id(idx.index_id());
- }
- bool need_read_schema_dict = false;
- auto arena = response->GetArena();
- for (auto& rowset_meta : *response->mutable_rowset_meta()) {
- if (rowset_meta.has_schema_dict_key_list()) {
- need_read_schema_dict = true;
+
+ if (version_pb.has_txn_id()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer_->submit(instance_id, version_pb.txn_id());
+
+ std::tie(code, msg) = task->wait();
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << version_pb.txn_id()
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
+ continue;
}
- if (rowset_meta.has_tablet_schema()) continue;
- if (!rowset_meta.has_schema_version()) {
+
+ // TODO(plat1ko): Judge if tablet has been dropped (in dropped index/partition)
+
+ TabletStatsPB tablet_stat;
+ internal_get_tablet_stats(code, msg, txn.get(), instance_id, idx, tablet_stat, true);
+ if (code != MetaServiceCode::OK) return;
+ VLOG_DEBUG << "tablet_id=" << tablet_id << " stats=" << proto_to_json(tablet_stat);
+
+ int64_t bc_cnt = tablet_stat.base_compaction_cnt();
+ int64_t cc_cnt = tablet_stat.cumulative_compaction_cnt();
+ int64_t cp = tablet_stat.cumulative_point();
+
+ response->mutable_stats()->CopyFrom(tablet_stat);
+
+ int64_t req_start = request->start_version();
+ int64_t req_end = request->end_version();
+ req_end = req_end < 0 ? std::numeric_limits<int64_t>::max() - 1 : req_end;
+
+ //==========================================================================
+ // Find version ranges to be synchronized due to compaction
+ //==========================================================================
+ if (req_bc_cnt > bc_cnt || req_cc_cnt > cc_cnt || req_cp > cp) {
code = MetaServiceCode::INVALID_ARGUMENT;
- msg = fmt::format(
- "rowset_meta must have either schema or schema_version, "
- "rowset_version=[{}-{}]",
- rowset_meta.start_version(), rowset_meta.end_version());
+ ss << "no valid compaction_cnt or cumulative_point given. req_bc_cnt=" << req_bc_cnt
+ << ", bc_cnt=" << bc_cnt << ", req_cc_cnt=" << req_cc_cnt << ", cc_cnt=" << cc_cnt
+ << ", req_cp=" << req_cp << ", cp=" << cp;
+ msg = ss.str();
return;
}
- if (auto it = version_to_schema.find(rowset_meta.schema_version());
- it != version_to_schema.end()) {
- if (arena != nullptr) {
- rowset_meta.set_allocated_tablet_schema(it->second);
- } else {
- rowset_meta.mutable_tablet_schema()->CopyFrom(*it->second);
+ auto versions = calc_sync_versions(req_bc_cnt, bc_cnt, req_cc_cnt, cc_cnt, req_cp, cp,
+ req_start, req_end);
+ for (auto [start, end] : versions) {
+ internal_get_rowset(txn.get(), start, end, instance_id, tablet_id, code, msg, response);
+ if (code != MetaServiceCode::OK) {
+ return;
}
- } else {
- auto key = meta_schema_key({instance_id, idx.index_id(), rowset_meta.schema_version()});
- if (!try_fetch_and_parse_schema(txn.get(), rowset_meta, key, code, msg)) {
+ }
+
+ // get referenced schema
+ std::unordered_map<int32_t, doris::TabletSchemaCloudPB*> version_to_schema;
+ for (auto& rowset_meta : *response->mutable_rowset_meta()) {
+ if (rowset_meta.has_tablet_schema()) {
+ version_to_schema.emplace(rowset_meta.tablet_schema().schema_version(),
+ rowset_meta.mutable_tablet_schema());
+ rowset_meta.set_schema_version(rowset_meta.tablet_schema().schema_version());
+ }
+ rowset_meta.set_index_id(idx.index_id());
+ }
+ bool need_read_schema_dict = false;
+ auto arena = response->GetArena();
+ for (auto& rowset_meta : *response->mutable_rowset_meta()) {
+ if (rowset_meta.has_schema_dict_key_list()) {
+ need_read_schema_dict = true;
+ }
+ if (rowset_meta.has_tablet_schema()) continue;
+ if (!rowset_meta.has_schema_version()) {
+ code = MetaServiceCode::INVALID_ARGUMENT;
+ msg = fmt::format(
+ "rowset_meta must have either schema or schema_version, "
+ "rowset_version=[{}-{}]",
+ rowset_meta.start_version(), rowset_meta.end_version());
return;
}
- version_to_schema.emplace(rowset_meta.schema_version(),
- rowset_meta.mutable_tablet_schema());
+ if (auto it = version_to_schema.find(rowset_meta.schema_version());
+ it != version_to_schema.end()) {
+ if (arena != nullptr) {
+ rowset_meta.set_allocated_tablet_schema(it->second);
+ } else {
+ rowset_meta.mutable_tablet_schema()->CopyFrom(*it->second);
+ }
+ } else {
+ auto key = meta_schema_key({instance_id, idx.index_id(), rowset_meta.schema_version()});
+ if (!try_fetch_and_parse_schema(txn.get(), rowset_meta, key, code, msg)) {
+ return;
+ }
+ version_to_schema.emplace(rowset_meta.schema_version(),
+ rowset_meta.mutable_tablet_schema());
+ }
}
- }
- if (need_read_schema_dict) {
- read_schema_from_dict(code, msg, instance_id, idx.index_id(), txn.get(),
- response->mutable_rowset_meta());
- if (code != MetaServiceCode::OK) return;
- }
+ if (need_read_schema_dict) {
+ read_schema_from_dict(code, msg, instance_id, idx.index_id(), txn.get(),
+ response->mutable_rowset_meta());
+ if (code != MetaServiceCode::OK) return;
Review Comment:
warning: statement should be inside braces [readability-braces-around-statements]
```suggestion
if (code != MetaServiceCode::OK) { return;
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1691448015
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,209 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+extern void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+extern void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+extern void make_committed_txn_visible(const std::string& instance_id, int64_t db_id,
+ int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id,
Review Comment:
warning: function 'TxnLazyCommitTask' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id,
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:41:** 130 lines including whitespace and comments (threshold 80)
```cpp
TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id,
^
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2249289401
<details>
<summary>ClickBench: <b>Total hot run time: 30.6 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit a7e2b1bd85dd3827c86fb9ead1aa462b016a3aba, data reload: false
query1 0.04 0.04 0.03
query2 0.10 0.04 0.04
query3 0.22 0.07 0.06
query4 1.66 0.10 0.10
query5 0.50 0.49 0.47
query6 1.13 0.73 0.73
query7 0.02 0.01 0.02
query8 0.04 0.04 0.04
query9 0.54 0.49 0.50
query10 0.54 0.55 0.54
query11 0.15 0.11 0.12
query12 0.15 0.13 0.13
query13 0.59 0.59 0.58
query14 0.78 0.77 0.77
query15 0.86 0.81 0.82
query16 0.37 0.35 0.36
query17 1.04 0.96 1.00
query18 0.23 0.22 0.21
query19 1.76 1.67 1.76
query20 0.01 0.01 0.01
query21 15.39 0.78 0.65
query22 4.40 7.39 1.91
query23 18.28 1.43 1.28
query24 2.08 0.25 0.22
query25 0.16 0.08 0.08
query26 0.31 0.22 0.22
query27 0.45 0.23 0.23
query28 13.27 1.02 1.01
query29 12.57 3.31 3.27
query30 0.26 0.06 0.06
query31 2.88 0.40 0.38
query32 3.27 0.48 0.49
query33 2.90 2.91 2.92
query34 16.97 4.33 4.33
query35 4.42 4.40 4.42
query36 0.67 0.49 0.48
query37 0.19 0.16 0.16
query38 0.16 0.14 0.14
query39 0.05 0.03 0.03
query40 0.15 0.13 0.12
query41 0.09 0.04 0.05
query42 0.05 0.05 0.05
query43 0.04 0.04 0.04
Total cold run time: 109.74 s
Total hot run time: 30.6 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2260719555
<details>
<summary>ClickBench: <b>Total hot run time: 30.38 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit f23de131c772e5e5b480379dddd6cae001bf04a6, data reload: false
query1 0.04 0.03 0.03
query2 0.07 0.04 0.05
query3 0.23 0.05 0.04
query4 1.67 0.07 0.07
query5 0.48 0.48 0.48
query6 1.15 0.72 0.72
query7 0.02 0.01 0.01
query8 0.05 0.04 0.05
query9 0.58 0.52 0.52
query10 0.60 0.56 0.55
query11 0.15 0.11 0.11
query12 0.15 0.13 0.13
query13 0.62 0.61 0.60
query14 0.77 0.80 0.80
query15 0.89 0.87 0.87
query16 0.35 0.35 0.36
query17 0.97 1.00 1.01
query18 0.22 0.22 0.22
query19 1.87 1.77 1.73
query20 0.02 0.01 0.01
query21 15.38 0.80 0.65
query22 3.83 7.61 1.38
query23 18.02 1.42 1.40
query24 2.28 0.22 0.21
query25 0.18 0.09 0.09
query26 0.33 0.22 0.22
query27 0.45 0.24 0.24
query28 13.15 1.01 0.98
query29 12.59 3.35 3.36
query30 0.26 0.06 0.07
query31 2.84 0.41 0.41
query32 3.24 0.51 0.48
query33 2.95 2.95 2.99
query34 15.43 4.27 4.26
query35 4.31 4.28 4.30
query36 0.68 0.49 0.50
query37 0.19 0.17 0.17
query38 0.16 0.15 0.15
query39 0.04 0.03 0.04
query40 0.16 0.13 0.13
query41 0.10 0.06 0.05
query42 0.05 0.04 0.04
query43 0.05 0.04 0.04
Total cold run time: 107.57 s
Total hot run time: 30.38 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2261901251
<details>
<summary>TPC-DS: <b>Total hot run time: 169623 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit c0a6c5ac10a4aa5587bfabcd3b74e29aa97bef62, data reload: false
query1 916 387 373 373
query2 6441 1716 1653 1653
query3 6654 213 229 213
query4 19174 17504 17339 17339
query5 3627 530 510 510
query6 288 165 174 165
query7 4627 314 296 296
query8 248 193 183 183
query9 8515 2432 2426 2426
query10 415 263 258 258
query11 10738 9918 10013 9918
query12 117 86 90 86
query13 1644 385 363 363
query14 9036 7071 7760 7071
query15 209 158 170 158
query16 6944 444 451 444
query17 919 552 539 539
query18 1916 284 288 284
query19 189 138 139 138
query20 90 88 81 81
query21 199 100 97 97
query22 4285 4057 4105 4057
query23 33745 33678 33404 33404
query24 10363 3176 3128 3128
query25 696 408 408 408
query26 2031 158 153 153
query27 3130 284 285 284
query28 7564 2058 2035 2035
query29 1346 437 452 437
query30 230 153 158 153
query31 967 759 777 759
query32 101 59 57 57
query33 669 315 345 315
query34 950 505 528 505
query35 894 790 760 760
query36 1024 855 862 855
query37 225 85 81 81
query38 2924 2800 2776 2776
query39 875 812 819 812
query40 261 115 112 112
query41 47 43 45 43
query42 126 100 97 97
query43 457 397 427 397
query44 1201 744 732 732
query45 205 176 178 176
query46 1083 813 788 788
query47 1824 1737 1723 1723
query48 366 298 301 298
query49 940 430 419 419
query50 909 436 441 436
query51 6654 6729 6688 6688
query52 103 87 89 87
query53 249 181 186 181
query54 662 457 462 457
query55 76 73 74 73
query56 288 249 246 246
query57 1162 1026 1053 1026
query58 278 272 303 272
query59 2626 2449 2407 2407
query60 294 279 261 261
query61 94 93 93 93
query62 871 673 656 656
query63 220 183 189 183
query64 5699 1910 1892 1892
query65 3179 3086 3107 3086
query66 1241 347 328 328
query67 15076 14712 14793 14712
query68 4321 572 571 571
query69 446 317 301 301
query70 1113 976 1067 976
query71 369 279 274 274
query72 7581 2752 2480 2480
query73 763 332 336 332
query74 6086 5643 5553 5553
query75 3404 2740 2730 2730
query76 2272 1342 1419 1342
query77 420 305 308 305
query78 9381 8930 8986 8930
query79 1878 545 528 528
query80 1109 501 557 501
query81 554 225 219 219
query82 1049 129 126 126
query83 237 175 167 167
query84 281 79 77 77
query85 1300 310 302 302
query86 401 298 297 297
query87 3279 3116 3084 3084
query88 3095 2513 2497 2497
query89 389 287 286 286
query90 1683 197 195 195
query91 128 101 96 96
query92 56 50 47 47
query93 1475 625 629 625
query94 824 295 300 295
query95 380 265 281 265
query96 593 279 285 279
query97 3226 3035 3030 3030
query98 218 198 191 191
query99 1662 1279 1287 1279
Total cold run time: 261089 ms
Total hot run time: 169623 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2262331605
<details>
<summary>ClickBench: <b>Total hot run time: 30.72 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit f40d3af909e3a4ce446ee5217827a6811bce34d1, data reload: false
query1 0.04 0.03 0.03
query2 0.07 0.03 0.04
query3 0.23 0.05 0.04
query4 1.71 0.07 0.09
query5 0.49 0.49 0.50
query6 1.14 0.72 0.72
query7 0.02 0.02 0.02
query8 0.05 0.04 0.04
query9 0.56 0.52 0.51
query10 0.57 0.57 0.55
query11 0.16 0.12 0.12
query12 0.15 0.12 0.12
query13 0.61 0.60 0.60
query14 0.78 0.79 0.77
query15 0.90 0.86 0.87
query16 0.35 0.36 0.35
query17 1.01 0.98 0.98
query18 0.22 0.20 0.20
query19 1.87 1.75 1.73
query20 0.01 0.01 0.01
query21 15.40 0.78 0.67
query22 3.84 6.74 2.14
query23 18.03 1.28 1.21
query24 2.24 0.23 0.23
query25 0.18 0.08 0.07
query26 0.32 0.21 0.21
query27 0.46 0.24 0.23
query28 13.16 1.01 0.97
query29 12.53 3.32 3.29
query30 0.26 0.05 0.06
query31 2.85 0.41 0.40
query32 3.24 0.49 0.50
query33 2.95 2.94 3.00
query34 15.44 4.26 4.29
query35 4.29 4.30 4.26
query36 0.67 0.47 0.48
query37 0.19 0.17 0.16
query38 0.16 0.14 0.15
query39 0.04 0.04 0.03
query40 0.16 0.13 0.13
query41 0.10 0.05 0.05
query42 0.06 0.04 0.05
query43 0.04 0.05 0.04
Total cold run time: 107.55 s
Total hot run time: 30.72 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2261914348
<details>
<summary>ClickBench: <b>Total hot run time: 30.23 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit c0a6c5ac10a4aa5587bfabcd3b74e29aa97bef62, data reload: false
query1 0.04 0.04 0.03
query2 0.07 0.03 0.04
query3 0.23 0.04 0.05
query4 1.69 0.08 0.08
query5 0.48 0.48 0.48
query6 1.14 0.72 0.71
query7 0.02 0.02 0.01
query8 0.05 0.04 0.04
query9 0.56 0.51 0.50
query10 0.59 0.56 0.57
query11 0.16 0.11 0.12
query12 0.15 0.13 0.13
query13 0.62 0.60 0.60
query14 0.78 0.78 0.81
query15 0.91 0.86 0.86
query16 0.36 0.35 0.35
query17 0.98 0.99 0.99
query18 0.22 0.21 0.21
query19 1.83 1.72 1.71
query20 0.01 0.01 0.01
query21 15.40 0.80 0.67
query22 4.36 7.85 1.52
query23 18.10 1.28 1.30
query24 2.26 0.23 0.22
query25 0.18 0.09 0.08
query26 0.32 0.21 0.21
query27 0.46 0.23 0.23
query28 13.16 1.00 0.97
query29 12.53 3.33 3.32
query30 0.26 0.06 0.06
query31 2.87 0.43 0.41
query32 3.21 0.49 0.50
query33 2.95 2.96 2.93
query34 15.44 4.23 4.26
query35 4.30 4.31 4.29
query36 0.69 0.47 0.49
query37 0.18 0.17 0.16
query38 0.18 0.15 0.15
query39 0.04 0.04 0.03
query40 0.16 0.14 0.14
query41 0.10 0.05 0.05
query42 0.06 0.05 0.05
query43 0.05 0.04 0.04
Total cold run time: 108.15 s
Total hot run time: 30.23 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2302361848
<details>
<summary>ClickBench: <b>Total hot run time: 31.6 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 3ecb308aa0ea6ae75918b441fcce5ed28f71c479, data reload: false
query1 0.05 0.04 0.04
query2 0.08 0.04 0.04
query3 0.23 0.06 0.06
query4 1.66 0.07 0.08
query5 0.54 0.52 0.50
query6 1.13 0.72 0.73
query7 0.03 0.02 0.02
query8 0.05 0.05 0.05
query9 0.55 0.48 0.49
query10 0.55 0.55 0.56
query11 0.17 0.13 0.12
query12 0.17 0.13 0.12
query13 0.62 0.59 0.58
query14 0.77 0.81 0.79
query15 0.84 0.82 0.83
query16 0.38 0.37 0.38
query17 1.07 1.06 1.04
query18 0.23 0.21 0.21
query19 1.98 1.87 1.83
query20 0.02 0.01 0.01
query21 15.40 0.68 0.67
query22 3.98 7.35 2.12
query23 18.25 1.44 1.32
query24 2.12 0.23 0.23
query25 0.15 0.08 0.08
query26 0.26 0.19 0.18
query27 0.08 0.08 0.08
query28 13.22 1.03 1.02
query29 12.66 3.37 3.36
query30 0.42 0.24 0.24
query31 2.80 0.42 0.41
query32 3.24 0.49 0.48
query33 2.99 2.99 2.98
query34 16.99 4.40 4.36
query35 4.42 4.42 4.45
query36 0.68 0.50 0.49
query37 0.21 0.18 0.17
query38 0.17 0.18 0.17
query39 0.07 0.06 0.05
query40 0.19 0.16 0.16
query41 0.12 0.06 0.07
query42 0.08 0.07 0.07
query43 0.08 0.06 0.06
Total cold run time: 109.7 s
Total hot run time: 31.6 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2298372481
<details>
<summary>TPC-H: <b>Total hot run time: 38269 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 1d63b327147196a6029b3421305f1eed1a00dc18, data reload: false
------ Round 1 ----------------------------------
q1 18209 4465 4317 4317
q2 2056 216 226 216
q3 11523 945 1169 945
q4 10537 775 665 665
q5 7805 2866 2785 2785
q6 267 161 158 158
q7 1015 660 660 660
q8 9397 2126 2107 2107
q9 7276 6613 6573 6573
q10 7102 2249 2271 2249
q11 492 271 270 270
q12 427 263 262 262
q13 18121 3055 3032 3032
q14 308 251 251 251
q15 564 533 554 533
q16 540 428 418 418
q17 988 646 753 646
q18 7562 6797 6824 6797
q19 6509 1076 1038 1038
q20 727 356 379 356
q21 4291 2948 2982 2948
q22 1172 1067 1043 1043
Total cold run time: 116888 ms
Total hot run time: 38269 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4606 4313 4268 4268
q2 411 318 318 318
q3 2848 2677 2676 2676
q4 2023 1757 1773 1757
q5 5708 5762 5699 5699
q6 247 152 152 152
q7 2154 1785 1791 1785
q8 3292 3479 3446 3446
q9 8830 8820 8820 8820
q10 3602 3375 3495 3375
q11 618 523 516 516
q12 839 679 690 679
q13 17259 3167 3029 3029
q14 328 304 306 304
q15 581 539 534 534
q16 531 466 473 466
q17 1859 1531 1531 1531
q18 8326 7697 7606 7606
q19 6439 1616 1739 1616
q20 2189 1902 1879 1879
q21 13268 5295 5399 5295
q22 1183 1098 1089 1089
Total cold run time: 87141 ms
Total hot run time: 56840 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2304898032
<details>
<summary>TPC-H: <b>Total hot run time: 38564 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 0b1e4a8f000eb4cf1faa30535e050f844fb38a05, data reload: false
------ Round 1 ----------------------------------
q1 18521 4576 4335 4335
q2 2038 187 180 180
q3 11866 1037 1103 1037
q4 10306 799 797 797
q5 7774 2856 2800 2800
q6 233 139 137 137
q7 993 620 611 611
q8 9342 2085 2093 2085
q9 7074 6528 6583 6528
q10 6997 2189 2170 2170
q11 461 252 244 244
q12 400 220 228 220
q13 17760 3093 3058 3058
q14 276 237 233 233
q15 526 493 498 493
q16 502 414 389 389
q17 999 716 692 692
q18 7482 6956 6910 6910
q19 1400 1100 1076 1076
q20 686 337 328 328
q21 3976 3312 3229 3229
q22 1123 1012 1036 1012
Total cold run time: 110735 ms
Total hot run time: 38564 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4468 4368 4330 4330
q2 382 284 275 275
q3 2896 2713 2662 2662
q4 1967 1724 1710 1710
q5 5718 5694 5844 5694
q6 227 137 142 137
q7 2302 1838 1825 1825
q8 3289 3473 3520 3473
q9 8803 8865 8885 8865
q10 3627 3422 3345 3345
q11 634 500 538 500
q12 854 703 656 656
q13 15429 3269 3317 3269
q14 333 285 293 285
q15 536 509 505 505
q16 504 440 456 440
q17 1841 1535 1534 1534
q18 8289 7847 7949 7847
q19 1734 1651 1630 1630
q20 2211 1898 1913 1898
q21 5934 5586 5467 5467
q22 1157 1052 1061 1052
Total cold run time: 73135 ms
Total hot run time: 57399 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2249275217
<details>
<summary>TPC-H: <b>Total hot run time: 40391 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit a7e2b1bd85dd3827c86fb9ead1aa462b016a3aba, data reload: false
------ Round 1 ----------------------------------
q1 18717 4643 4364 4364
q2 3105 197 207 197
q3 11146 1201 1118 1118
q4 10729 912 778 778
q5 8172 2730 2815 2730
q6 225 147 141 141
q7 985 624 597 597
q8 9222 2092 2099 2092
q9 8857 6571 6547 6547
q10 8787 3860 3764 3764
q11 466 238 236 236
q12 400 231 229 229
q13 17765 3019 3017 3017
q14 271 227 247 227
q15 516 486 500 486
q16 477 390 387 387
q17 976 690 650 650
q18 8162 7616 7586 7586
q19 6836 1477 1462 1462
q20 709 318 331 318
q21 4918 3274 3184 3184
q22 360 293 281 281
Total cold run time: 121801 ms
Total hot run time: 40391 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4458 4289 4290 4289
q2 367 269 266 266
q3 2996 2803 2694 2694
q4 1941 1599 1601 1599
q5 5291 5358 5332 5332
q6 223 131 135 131
q7 2176 1731 1724 1724
q8 3211 3373 3316 3316
q9 8447 8466 8401 8401
q10 3891 3762 3651 3651
q11 573 494 476 476
q12 793 664 591 591
q13 16348 2984 3023 2984
q14 288 269 272 269
q15 506 485 482 482
q16 484 419 422 419
q17 1781 1502 1501 1501
q18 7633 7493 7484 7484
q19 3342 1543 1580 1543
q20 2019 1787 1783 1783
q21 4925 4707 4860 4707
q22 576 516 502 502
Total cold run time: 72269 ms
Total hot run time: 54144 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2262170374
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2261786135
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2262321636
<details>
<summary>TPC-DS: <b>Total hot run time: 170685 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit f40d3af909e3a4ce446ee5217827a6811bce34d1, data reload: false
query1 919 381 370 370
query2 6455 1708 1670 1670
query3 6649 224 221 221
query4 20265 17544 17285 17285
query5 3664 517 520 517
query6 284 172 178 172
query7 4598 305 305 305
query8 274 201 205 201
query9 8506 2369 2356 2356
query10 434 282 278 278
query11 10519 10016 10112 10016
query12 122 88 97 88
query13 1646 384 366 366
query14 8846 7889 7857 7857
query15 210 199 163 163
query16 6672 462 423 423
query17 943 586 542 542
query18 1888 287 277 277
query19 194 142 159 142
query20 94 85 84 84
query21 204 104 99 99
query22 4261 4124 3928 3928
query23 34031 33736 33739 33736
query24 10288 3146 3129 3129
query25 679 415 403 403
query26 1706 154 157 154
query27 3160 282 285 282
query28 7380 2025 1997 1997
query29 1187 441 447 441
query30 240 155 154 154
query31 955 791 808 791
query32 102 59 57 57
query33 672 328 329 328
query34 913 497 503 497
query35 855 736 773 736
query36 1054 890 891 890
query37 272 83 81 81
query38 2987 2849 2781 2781
query39 861 805 855 805
query40 249 118 111 111
query41 49 45 45 45
query42 130 97 100 97
query43 469 434 414 414
query44 1167 712 744 712
query45 215 185 180 180
query46 1102 823 768 768
query47 1816 1739 1711 1711
query48 360 298 287 287
query49 924 420 403 403
query50 910 429 424 424
query51 6840 6802 6678 6678
query52 95 88 88 88
query53 251 181 184 181
query54 621 456 441 441
query55 77 74 74 74
query56 273 266 258 258
query57 1124 1076 1041 1041
query58 278 257 299 257
query59 2764 2382 2281 2281
query60 302 261 275 261
query61 96 94 94 94
query62 887 667 677 667
query63 211 188 186 186
query64 5712 1902 1899 1899
query65 3193 3097 3080 3080
query66 1321 331 334 331
query67 15391 14910 14715 14715
query68 5484 560 575 560
query69 701 379 307 307
query70 1109 1096 1044 1044
query71 468 282 272 272
query72 7551 2732 2504 2504
query73 929 333 326 326
query74 6115 5737 5697 5697
query75 3620 2735 2725 2725
query76 3217 1367 1395 1367
query77 538 301 302 301
query78 9488 8883 8886 8883
query79 1686 533 528 528
query80 1908 507 491 491
query81 570 225 225 225
query82 478 132 127 127
query83 275 172 165 165
query84 277 77 77 77
query85 1162 355 426 355
query86 448 308 309 308
query87 3321 3168 3133 3133
query88 3691 2384 2386 2384
query89 379 284 291 284
query90 1688 186 186 186
query91 125 99 99 99
query92 65 51 50 50
query93 2016 621 632 621
query94 807 286 297 286
query95 381 270 266 266
query96 595 280 276 276
query97 3207 3115 3059 3059
query98 246 204 196 196
query99 1628 1291 1277 1277
Total cold run time: 265989 ms
Total hot run time: 170685 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1708566284
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -387,10 +410,28 @@ void MetaServiceImpl::batch_get_version(::google::protobuf::RpcController* contr
msg = "malformed version value";
break;
}
+ if (version_pb.has_txn_id()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer_->submit(instance_id, version_pb.txn_id());
+ std::tie(code, msg) = task->wait();
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "wait txn lazy commit failed, txn_id="
+ << version_pb.txn_id();
+ break;
+ }
+ goto TRY_AGAIN;
+ }
response->add_versions(version_pb.version());
response->add_version_update_time_ms(version_pb.update_time_ms());
}
}
+ if (code != MetaServiceCode::OK) {
+ break;
+ }
+ }
+ if (code != MetaServiceCode::OK) {
+ break;
Review Comment:
> Delete the useless code
done
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -387,10 +410,28 @@ void MetaServiceImpl::batch_get_version(::google::protobuf::RpcController* contr
msg = "malformed version value";
break;
}
+ if (version_pb.has_txn_id()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer_->submit(instance_id, version_pb.txn_id());
+ std::tie(code, msg) = task->wait();
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "wait txn lazy commit failed, txn_id="
+ << version_pb.txn_id();
+ break;
+ }
+ goto TRY_AGAIN;
Review Comment:
> We don't need to retry again, just like the `get_version`, returning the version directly is enough.
done
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2275070120
<details>
<summary>TPC-H: <b>Total hot run time: 39821 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 1ac8d3c9b6c996a098b4d7ff79645541deefde05, data reload: false
------ Round 1 ----------------------------------
q1 17670 5316 4296 4296
q2 2031 185 181 181
q3 10521 1175 1095 1095
q4 10190 811 705 705
q5 7511 2527 2510 2510
q6 218 138 135 135
q7 974 590 593 590
q8 9210 1920 1931 1920
q9 8820 6595 6591 6591
q10 7051 2166 2143 2143
q11 525 245 252 245
q12 390 219 221 219
q13 17946 2947 2972 2947
q14 293 247 232 232
q15 527 464 464 464
q16 643 519 526 519
q17 985 709 653 653
q18 8301 7503 7473 7473
q19 3272 997 1128 997
q20 769 411 422 411
q21 5387 4586 4476 4476
q22 1099 1019 1020 1019
Total cold run time: 114333 ms
Total hot run time: 39821 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4394 4297 4293 4293
q2 394 284 281 281
q3 2890 2670 2636 2636
q4 1906 1604 1631 1604
q5 5251 5317 5319 5317
q6 222 136 130 130
q7 2070 1699 1676 1676
q8 3161 3310 3361 3310
q9 8425 8441 8406 8406
q10 3376 3101 3175 3101
q11 605 514 513 513
q12 782 633 585 585
q13 17639 2979 2963 2963
q14 325 268 274 268
q15 513 474 474 474
q16 620 551 549 549
q17 1787 1493 1485 1485
q18 7797 7648 7299 7299
q19 1710 1605 1685 1605
q20 2095 1881 1873 1873
q21 5390 5174 5212 5174
q22 1070 1021 1012 1012
Total cold run time: 72422 ms
Total hot run time: 54554 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2285272777
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2297034258
<details>
<summary>TPC-H: <b>Total hot run time: 38448 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 26c7330ea2ca69f58795f6cc0b7821111e82c0d5, data reload: false
------ Round 1 ----------------------------------
q1 18361 4986 4315 4315
q2 2059 215 242 215
q3 11074 964 1081 964
q4 10525 803 788 788
q5 7791 2887 2843 2843
q6 266 161 162 161
q7 1042 656 664 656
q8 9568 2136 2119 2119
q9 8660 6596 6623 6596
q10 7077 2353 2254 2254
q11 529 274 279 274
q12 431 257 264 257
q13 17794 3010 3001 3001
q14 310 268 257 257
q15 557 536 537 536
q16 538 431 420 420
q17 1000 687 716 687
q18 7578 6773 6898 6773
q19 6459 1121 1127 1121
q20 727 352 365 352
q21 3870 2984 2827 2827
q22 1143 1054 1032 1032
Total cold run time: 117359 ms
Total hot run time: 38448 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4605 4295 4294 4294
q2 420 323 322 322
q3 2881 2649 2747 2649
q4 1989 1773 1724 1724
q5 5634 5774 5637 5637
q6 253 152 153 152
q7 2137 1768 1736 1736
q8 3302 3527 3457 3457
q9 8759 8721 8728 8721
q10 3581 3357 3327 3327
q11 599 528 528 528
q12 838 684 633 633
q13 17174 3181 3174 3174
q14 322 298 296 296
q15 546 523 508 508
q16 491 469 467 467
q17 1871 1552 1525 1525
q18 8197 8036 7874 7874
q19 7830 1645 1628 1628
q20 2209 1916 1884 1884
q21 14189 5365 5354 5354
q22 1203 1098 1063 1063
Total cold run time: 89030 ms
Total hot run time: 56953 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "gavinchou (via GitHub)" <gi...@apache.org>.
gavinchou commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1730626928
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
msg = ss.str();
return;
}
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
- std::string_view ver_key = i.first;
- ver_key.remove_prefix(1); // Remove key space
- // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- int ret = decode_key(&ver_key, &out);
- if (ret != 0) [[unlikely]] {
- // decode version key error means this is something wrong,
- // we can not continue this txn
- LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = "decode version key error";
- return;
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
}
- int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
- int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
- VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+ // save versions for partition
+ int64_t version_update_time_ms =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ response->set_version_update_time_ms(version_update_time_ms);
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_txn_id(txn_id);
+ version_pb.set_update_time_ms(version_update_time_ms);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- response->add_table_ids(table_id);
- response->add_partition_ids(partition_id);
- response->add_versions(i.second);
- }
+ txn->put(i.first, ver_val);
+ LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
+ << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+
+ std::string_view ver_key = i.first;
+ ver_key.remove_prefix(1); // Remove key space
+ // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
+ int ret = decode_key(&ver_key, &out);
+ if (ret != 0) [[unlikely]] {
+ // decode version key error means this is something wrong,
+ // we can not continue this txn
+ LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = "decode version key error";
+ return;
+ }
- // Save table versions
- for (auto& i : table_id_tablet_ids) {
- std::string ver_key = table_version_key({instance_id, db_id, i.first});
- txn->atomic_add(ver_key, 1);
- LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key) << " txn_id=" << txn_id;
- }
+ int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
+ int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
+ VLOG_DEBUG << "txn_id=" << txn_id << " table_id=" << table_id
+ << " partition_id=" << partition_id << " version=" << i.second;
- LOG(INFO) << " before update txn_info=" << txn_info.ShortDebugString();
+ response->add_table_ids(table_id);
+ response->add_partition_ids(partition_id);
+ response->add_versions(i.second);
+ }
- // Update txn_info
- txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ // process mow table, check lock and remove pending key
+ std::vector<std::string> lock_keys;
+ lock_keys.reserve(request->mow_table_ids().size());
+ for (auto table_id : request->mow_table_ids()) {
+ lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
+ }
+ std::vector<std::optional<std::string>> lock_values;
+ err = txn->batch_get(&lock_values, lock_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
+ << " err=" << err;
+ msg = ss.str();
+ code = cast_as<ErrCategory::READ>(err);
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- auto now_time = system_clock::now();
- uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
- if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
- LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
- << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
- return;
- }
- txn_info.set_commit_time(commit_time);
- txn_info.set_finish_time(commit_time);
- if (request->has_commit_attachment()) {
- txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
- }
- LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
- info_val.clear();
- if (!txn_info.SerializeToString(&info_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(info_key, info_val);
- LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+ for (size_t i = 0; i < lock_keys.size(); i++) {
+ int64_t table_id = request->mow_table_ids(i);
+ // When the key does not exist, it means the lock has been acquired
+ // by another transaction and successfully committed.
+ if (!lock_values[i].has_value()) {
+ ss << "get delete bitmap update lock info, lock is expired"
+ << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
+ code = MetaServiceCode::LOCK_EXPIRED;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- // Update stats of affected tablet
- for (auto& [tablet_id, stats] : tablet_stats) {
- DCHECK(tablet_ids.count(tablet_id));
- auto& tablet_idx = tablet_ids[tablet_id];
- StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
- tablet_idx.partition_id(), tablet_id};
- update_tablet_stats(info, stats, txn, code, msg);
- if (code != MetaServiceCode::OK) return;
- }
- // Remove tmp rowset meta
- for (auto& [k, _] : tmp_rowsets_meta) {
- txn->remove(k);
- LOG(INFO) << "xxx remove tmp_rowset_key=" << hex(k) << " txn_id=" << txn_id;
- }
+ DeleteBitmapUpdateLockPB lock_info;
+ if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "failed to parse DeleteBitmapUpdateLockPB";
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ if (lock_info.lock_id() != request->txn_id()) {
+ msg = "lock is expired";
+ code = MetaServiceCode::LOCK_EXPIRED;
+ return;
+ }
+ txn->remove(lock_keys[i]);
+ LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
+ << " txn_id=" << txn_id;
- const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
- LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
- txn->remove(running_key);
+ for (auto tablet_id : table_id_tablet_ids[table_id]) {
+ std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
+ txn->remove(pending_key);
+ LOG(INFO) << "xxx remove delete bitmap pending key, pending_key="
+ << hex(pending_key) << " txn_id=" << txn_id;
+ }
+ }
+ lock_keys.clear();
+ lock_values.clear();
- std::string recycle_val;
- std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
- RecycleTxnPB recycle_pb;
- recycle_pb.set_creation_time(commit_time);
- recycle_pb.set_label(txn_info.label());
+ // Save table versions
+ for (auto& i : table_id_tablet_ids) {
+ std::string ver_key = table_version_key({instance_id, db_id, i.first});
+ txn->atomic_add(ver_key, 1);
+ LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key)
+ << " txn_id=" << txn_id;
+ }
- if (!recycle_pb.SerializeToString(&recycle_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(recycle_key, recycle_val);
+ LOG(INFO) << "commit_txn_eventually put_size=" << txn->put_bytes()
+ << " del_size=" << txn->delete_bytes() << " num_put_keys=" << txn->num_put_keys()
+ << " num_del_keys=" << txn->num_del_keys()
+ << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
- if (txn_info.load_job_source_type() ==
- LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
- put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
- }
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
- LOG(INFO) << "xxx commit_txn put recycle_key key=" << hex(recycle_key) << " txn_id=" << txn_id;
- LOG(INFO) << "commit_txn put_size=" << txn->put_bytes() << " del_size=" << txn->delete_bytes()
- << " num_put_keys=" << txn->num_put_keys() << " num_del_keys=" << txn->num_del_keys()
- << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
+ std::shared_ptr<TxnLazyCommitTask> task = txn_lazy_committer->submit(instance_id, txn_id);
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ if (ret.first != MetaServiceCode::OK) {
+ LOG(WARNING) << "lazy commit txn failed txn_id=" << txn_id << " code=" << ret.first
Review Comment:
add more info in log to describe what it will do if st is not OK
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1732718352
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
msg = ss.str();
return;
}
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
- std::string_view ver_key = i.first;
- ver_key.remove_prefix(1); // Remove key space
- // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- int ret = decode_key(&ver_key, &out);
- if (ret != 0) [[unlikely]] {
- // decode version key error means this is something wrong,
- // we can not continue this txn
- LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = "decode version key error";
- return;
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
}
- int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
- int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
- VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+ // save versions for partition
+ int64_t version_update_time_ms =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ response->set_version_update_time_ms(version_update_time_ms);
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_txn_id(txn_id);
+ version_pb.set_update_time_ms(version_update_time_ms);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- response->add_table_ids(table_id);
- response->add_partition_ids(partition_id);
- response->add_versions(i.second);
- }
+ txn->put(i.first, ver_val);
+ LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
+ << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+
+ std::string_view ver_key = i.first;
+ ver_key.remove_prefix(1); // Remove key space
+ // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
+ int ret = decode_key(&ver_key, &out);
+ if (ret != 0) [[unlikely]] {
+ // decode version key error means this is something wrong,
+ // we can not continue this txn
+ LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = "decode version key error";
+ return;
+ }
- // Save table versions
- for (auto& i : table_id_tablet_ids) {
- std::string ver_key = table_version_key({instance_id, db_id, i.first});
- txn->atomic_add(ver_key, 1);
- LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key) << " txn_id=" << txn_id;
- }
+ int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
+ int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
+ VLOG_DEBUG << "txn_id=" << txn_id << " table_id=" << table_id
+ << " partition_id=" << partition_id << " version=" << i.second;
- LOG(INFO) << " before update txn_info=" << txn_info.ShortDebugString();
+ response->add_table_ids(table_id);
+ response->add_partition_ids(partition_id);
+ response->add_versions(i.second);
+ }
- // Update txn_info
- txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ // process mow table, check lock and remove pending key
+ std::vector<std::string> lock_keys;
+ lock_keys.reserve(request->mow_table_ids().size());
+ for (auto table_id : request->mow_table_ids()) {
+ lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
+ }
+ std::vector<std::optional<std::string>> lock_values;
+ err = txn->batch_get(&lock_values, lock_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
+ << " err=" << err;
+ msg = ss.str();
+ code = cast_as<ErrCategory::READ>(err);
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- auto now_time = system_clock::now();
- uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
- if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
- LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
- << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
- return;
- }
- txn_info.set_commit_time(commit_time);
- txn_info.set_finish_time(commit_time);
- if (request->has_commit_attachment()) {
- txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
- }
- LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
- info_val.clear();
- if (!txn_info.SerializeToString(&info_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(info_key, info_val);
- LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+ for (size_t i = 0; i < lock_keys.size(); i++) {
+ int64_t table_id = request->mow_table_ids(i);
+ // When the key does not exist, it means the lock has been acquired
+ // by another transaction and successfully committed.
+ if (!lock_values[i].has_value()) {
+ ss << "get delete bitmap update lock info, lock is expired"
+ << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
+ code = MetaServiceCode::LOCK_EXPIRED;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- // Update stats of affected tablet
- for (auto& [tablet_id, stats] : tablet_stats) {
- DCHECK(tablet_ids.count(tablet_id));
- auto& tablet_idx = tablet_ids[tablet_id];
- StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
- tablet_idx.partition_id(), tablet_id};
- update_tablet_stats(info, stats, txn, code, msg);
- if (code != MetaServiceCode::OK) return;
- }
- // Remove tmp rowset meta
- for (auto& [k, _] : tmp_rowsets_meta) {
- txn->remove(k);
- LOG(INFO) << "xxx remove tmp_rowset_key=" << hex(k) << " txn_id=" << txn_id;
- }
+ DeleteBitmapUpdateLockPB lock_info;
+ if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "failed to parse DeleteBitmapUpdateLockPB";
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ if (lock_info.lock_id() != request->txn_id()) {
+ msg = "lock is expired";
+ code = MetaServiceCode::LOCK_EXPIRED;
+ return;
+ }
+ txn->remove(lock_keys[i]);
+ LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
+ << " txn_id=" << txn_id;
- const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
- LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
- txn->remove(running_key);
+ for (auto tablet_id : table_id_tablet_ids[table_id]) {
+ std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
+ txn->remove(pending_key);
+ LOG(INFO) << "xxx remove delete bitmap pending key, pending_key="
+ << hex(pending_key) << " txn_id=" << txn_id;
+ }
+ }
+ lock_keys.clear();
+ lock_values.clear();
- std::string recycle_val;
- std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
- RecycleTxnPB recycle_pb;
- recycle_pb.set_creation_time(commit_time);
- recycle_pb.set_label(txn_info.label());
+ // Save table versions
+ for (auto& i : table_id_tablet_ids) {
+ std::string ver_key = table_version_key({instance_id, db_id, i.first});
+ txn->atomic_add(ver_key, 1);
+ LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key)
+ << " txn_id=" << txn_id;
+ }
- if (!recycle_pb.SerializeToString(&recycle_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(recycle_key, recycle_val);
+ LOG(INFO) << "commit_txn_eventually put_size=" << txn->put_bytes()
+ << " del_size=" << txn->delete_bytes() << " num_put_keys=" << txn->num_put_keys()
+ << " num_del_keys=" << txn->num_del_keys()
+ << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
- if (txn_info.load_job_source_type() ==
- LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
- put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
- }
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
- LOG(INFO) << "xxx commit_txn put recycle_key key=" << hex(recycle_key) << " txn_id=" << txn_id;
- LOG(INFO) << "commit_txn put_size=" << txn->put_bytes() << " del_size=" << txn->delete_bytes()
- << " num_put_keys=" << txn->num_put_keys() << " num_del_keys=" << txn->num_del_keys()
- << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
+ std::shared_ptr<TxnLazyCommitTask> task = txn_lazy_committer->submit(instance_id, txn_id);
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ if (ret.first != MetaServiceCode::OK) {
+ LOG(WARNING) << "lazy commit txn failed txn_id=" << txn_id << " code=" << ret.first
+ << "msg=" << ret.second;
+ }
- // Finally we are done...
- err = txn->commit();
- if (err != TxnErrorCode::TXN_OK) {
- if ((err == TxnErrorCode::TXN_VALUE_TOO_LARGE ||
- err == TxnErrorCode::TXN_BYTES_TOO_LARGE) &&
- !tmp_rowsets_meta.empty()) {
- size_t max_size = 0, max_idx = 0, max_num_segments = 0,
- min_num_segments = std::numeric_limits<size_t>::max(), avg_num_segments = 0;
- for (size_t i = 0; i < tmp_rowsets_meta.size(); i++) {
- auto& [k, v] = tmp_rowsets_meta[i];
- if (v.ByteSizeLong() > max_size) {
- max_size = v.ByteSizeLong();
- max_idx = i;
- }
- if (v.num_segments() > max_num_segments) {
- max_num_segments = v.num_segments();
- }
- if (v.num_segments() < min_num_segments) {
- min_num_segments = v.num_segments();
- }
- avg_num_segments += v.num_segments();
- }
- if (!tmp_rowsets_meta.empty()) {
- avg_num_segments /= tmp_rowsets_meta.size();
- }
- LOG(WARNING) << "failed to commit kv txn"
- << ", err=" << err << ", txn_id=" << txn_id
- << ", total_rowsets=" << tmp_rowsets_meta.size()
- << ", avg_num_segments=" << avg_num_segments
- << ", min_num_segments=" << min_num_segments
- << ", max_num_segments=" << max_num_segments
- << ", largest_rowset_size=" << max_size
- << ", largest_rowset_key=" << hex(tmp_rowsets_meta[max_idx].first)
- << ", largest_rowset_value="
- << tmp_rowsets_meta[max_idx].second.ShortDebugString();
+ std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ // Accumulate affected rows
+ auto& stats = tablet_stats[i.tablet_id()];
+ stats.data_size += i.data_disk_size();
+ stats.num_rows += i.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += i.num_segments();
}
- code = cast_as<ErrCategory::COMMIT>(err);
- ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- return;
- }
- // calculate table stats from tablets stats
- std::map<int64_t /*table_id*/, TableStats> table_stats;
- std::vector<int64_t> base_tablet_ids(request->base_tablet_ids().begin(),
- request->base_tablet_ids().end());
- calc_table_stats(tablet_ids, tablet_stats, table_stats, base_tablet_ids);
- for (const auto& pair : table_stats) {
- TableStatsPB* stats_pb = response->add_table_stats();
- auto table_id = pair.first;
- auto stats = pair.second;
- get_pb_from_tablestats(stats, stats_pb);
- stats_pb->set_table_id(table_id);
- VLOG_DEBUG << "Add TableStats to CommitTxnResponse. txn_id=" << txn_id
- << " table_id=" << table_id
- << " updated_row_count=" << stats_pb->updated_row_count();
- }
+ // calculate table stats from tablets stats
+ std::map<int64_t /*table_id*/, TableStats> table_stats;
+ std::vector<int64_t> base_tablet_ids(request->base_tablet_ids().begin(),
+ request->base_tablet_ids().end());
+ calc_table_stats(tablet_ids, tablet_stats, table_stats, base_tablet_ids);
+ for (const auto& pair : table_stats) {
+ TableStatsPB* stats_pb = response->add_table_stats();
+ auto table_id = pair.first;
+ auto stats = pair.second;
+ get_pb_from_tablestats(stats, stats_pb);
+ stats_pb->set_table_id(table_id);
+ VLOG_DEBUG << "Add TableStats to CommitTxnResponse. txn_id=" << txn_id
+ << " table_id=" << table_id
+ << " updated_row_count=" << stats_pb->updated_row_count();
+ }
- response->mutable_txn_info()->CopyFrom(txn_info);
-} // end commit_txn
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
Review Comment:
> is it VISIBLE even if `task->wait()` failed?
yes, committed txn must be advanced
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2314649999
<details>
<summary>TPC-DS: <b>Total hot run time: 192851 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 0f6412f7fa9a90fc50e6af06a04d4e9b42655491, data reload: false
query1 1246 897 880 880
query2 6377 1979 1930 1930
query3 10770 4109 4024 4024
query4 59530 23957 23403 23403
query5 5439 497 493 493
query6 407 166 159 159
query7 5847 298 305 298
query8 292 204 220 204
query9 9045 2477 2491 2477
query10 501 272 262 262
query11 16900 15114 15206 15114
query12 159 109 106 106
query13 1623 400 396 396
query14 11171 7094 7481 7094
query15 234 171 183 171
query16 7618 447 477 447
query17 1157 551 558 551
query18 2098 307 298 298
query19 285 150 149 149
query20 122 115 110 110
query21 205 105 105 105
query22 4664 4582 4606 4582
query23 34223 33521 33123 33123
query24 5927 2826 2825 2825
query25 527 385 388 385
query26 683 150 151 150
query27 1811 272 274 272
query28 3816 2114 2100 2100
query29 690 408 407 407
query30 235 155 154 154
query31 927 725 782 725
query32 88 57 62 57
query33 471 300 291 291
query34 870 480 486 480
query35 863 725 723 723
query36 1057 902 960 902
query37 152 93 96 93
query38 3907 3845 3922 3845
query39 1457 1372 1394 1372
query40 193 114 111 111
query41 47 48 45 45
query42 112 94 93 93
query43 516 486 481 481
query44 1077 743 756 743
query45 194 163 163 163
query46 1086 743 757 743
query47 1906 1801 1833 1801
query48 359 287 300 287
query49 752 415 429 415
query50 818 418 409 409
query51 7243 7063 7089 7063
query52 95 87 84 84
query53 252 182 180 180
query54 556 446 452 446
query55 81 80 76 76
query56 281 241 241 241
query57 1208 1083 1062 1062
query58 224 222 225 222
query59 2970 2870 2743 2743
query60 305 268 260 260
query61 103 95 97 95
query62 736 664 643 643
query63 214 179 179 179
query64 2835 657 686 657
query65 3213 3161 3132 3132
query66 663 328 327 327
query67 15548 15320 15191 15191
query68 2966 569 576 569
query69 407 274 289 274
query70 1223 1089 1074 1074
query71 354 278 266 266
query72 5169 4035 3932 3932
query73 745 332 332 332
query74 9089 8856 8846 8846
query75 3351 2647 2671 2647
query76 1465 1009 1033 1009
query77 544 317 313 313
query78 9706 9374 10068 9374
query79 1088 532 538 532
query80 678 498 504 498
query81 463 237 228 228
query82 247 148 145 145
query83 172 153 148 148
query84 256 74 77 74
query85 675 271 361 271
query86 304 303 287 287
query87 4461 4199 4299 4199
query88 3296 2312 2337 2312
query89 386 282 281 281
query90 1932 194 189 189
query91 121 98 99 98
query92 60 55 52 52
query93 1049 536 542 536
query94 692 287 304 287
query95 329 258 267 258
query96 595 270 273 270
query97 3204 3041 3044 3041
query98 212 197 198 197
query99 1500 1315 1263 1263
Total cold run time: 303720 ms
Total hot run time: 192851 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1732025419
##########
cloud/src/common/config.h:
##########
@@ -206,4 +206,8 @@ CONF_Validator(s3_client_http_scheme, [](const std::string& config) -> bool {
// Max retry times for object storage request
CONF_mInt64(max_s3_client_retry, "10");
+CONF_Bool(enable_txn_lazy_commit, "true");
+CONF_Int32(txn_lazy_commit_rowsets_thresold, "2048");
+CONF_Int32(txn_lazy_commit_num_threads, "8");
+CONF_Int32(txn_lazy_max_rowsets_per_batch, "2048");
Review Comment:
> what the relation between `txn_lazy_max_rowsets_per_batch` and `txn_lazy_max_rowsets_per_batch`
"txn_lazy_max_rowsets_per_batch" the max num for convert tmp rowsets
"txn_lazy_commit_rowsets_thresold" the num to determine whether lazy commit
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2303643068
<details>
<summary>TPC-H: <b>Total hot run time: 39019 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 740144c09664bd5fcc4a77551e5f4fdf659aa12d, data reload: false
------ Round 1 ----------------------------------
q1 18495 4994 4431 4431
q2 2069 219 225 219
q3 11493 1004 1169 1004
q4 10379 752 801 752
q5 7761 2931 2869 2869
q6 272 160 160 160
q7 1030 658 651 651
q8 9414 2172 2176 2172
q9 7223 6615 6629 6615
q10 7094 2186 2266 2186
q11 499 277 278 277
q12 439 269 265 265
q13 18948 3056 3149 3056
q14 318 257 275 257
q15 557 519 520 519
q16 535 422 412 412
q17 1027 749 803 749
q18 7547 6838 7078 6838
q19 1444 1054 1052 1052
q20 728 359 361 359
q21 4234 3144 3457 3144
q22 1131 1069 1032 1032
Total cold run time: 112637 ms
Total hot run time: 39019 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4443 4404 4343 4343
q2 415 297 308 297
q3 2897 2661 2799 2661
q4 2012 1791 1725 1725
q5 5715 5693 5832 5693
q6 242 150 146 146
q7 2279 1872 1835 1835
q8 3330 3484 3532 3484
q9 8901 8900 8795 8795
q10 3590 3442 3420 3420
q11 645 555 533 533
q12 847 670 702 670
q13 16021 3238 3254 3238
q14 339 300 301 300
q15 573 522 530 522
q16 514 478 477 477
q17 1888 1573 1559 1559
q18 8231 7971 7940 7940
q19 1805 1618 1495 1495
q20 2136 1942 1959 1942
q21 5669 5581 5379 5379
q22 1205 1130 1103 1103
Total cold run time: 73697 ms
Total hot run time: 57557 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2301568583
PR approved by at least one committer and no changes requested.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2285789380
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1714982367
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,455 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(recycle_key, recycle_val);
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+ }
+}
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
Review Comment:
warning: function 'commit' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void TxnLazyCommitTask::commit() {
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:292:** 122 lines including whitespace and comments (threshold 80)
```cpp
void TxnLazyCommitTask::commit() {
^
```
</details>
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,455 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
Review Comment:
warning: function 'convert_tmp_rowsets' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void convert_tmp_rowsets(
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:40:** 152 lines including whitespace and comments (threshold 80)
```cpp
void convert_tmp_rowsets(
^
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2312273940
<details>
<summary>ClickBench: <b>Total hot run time: 30.49 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit fb825b12499087f8dea29592d393d5582d3623c3, data reload: false
query1 0.04 0.04 0.04
query2 0.08 0.04 0.04
query3 0.22 0.05 0.05
query4 1.67 0.07 0.08
query5 0.50 0.49 0.51
query6 1.13 0.74 0.73
query7 0.02 0.01 0.02
query8 0.05 0.05 0.05
query9 0.54 0.48 0.49
query10 0.55 0.55 0.54
query11 0.15 0.11 0.11
query12 0.15 0.12 0.12
query13 0.60 0.61 0.59
query14 0.75 0.79 0.79
query15 0.85 0.82 0.84
query16 0.36 0.38 0.35
query17 1.05 1.01 1.06
query18 0.22 0.20 0.21
query19 1.89 1.74 1.87
query20 0.02 0.01 0.01
query21 15.43 0.66 0.65
query22 4.51 6.35 1.88
query23 18.26 1.33 1.26
query24 2.08 0.23 0.21
query25 0.15 0.08 0.08
query26 0.26 0.17 0.18
query27 0.08 0.08 0.07
query28 13.27 1.01 0.99
query29 12.63 3.27 3.22
query30 0.24 0.06 0.06
query31 2.88 0.40 0.39
query32 3.23 0.47 0.48
query33 3.00 3.00 3.04
query34 17.27 4.39 4.37
query35 4.45 4.37 4.45
query36 0.66 0.45 0.49
query37 0.18 0.15 0.16
query38 0.15 0.16 0.16
query39 0.05 0.04 0.04
query40 0.16 0.14 0.13
query41 0.10 0.05 0.04
query42 0.06 0.05 0.05
query43 0.04 0.04 0.04
Total cold run time: 109.98 s
Total hot run time: 30.49 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "gavinchou (via GitHub)" <gi...@apache.org>.
gavinchou merged PR #38243:
URL: https://github.com/apache/doris/pull/38243
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2314491020
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1732724162
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
Review Comment:
> what if the commit returns errors like
>
> 1. value exceeds max bytes
> 2. transaction too old
return error to ms client
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2304159370
<details>
<summary>ClickBench: <b>Total hot run time: 31.27 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 20e25bf51ae7f01a6fff2f9704c155a8c059045a, data reload: false
query1 0.05 0.05 0.04
query2 0.08 0.04 0.04
query3 0.22 0.05 0.05
query4 1.66 0.08 0.08
query5 0.52 0.48 0.48
query6 1.13 0.75 0.72
query7 0.02 0.02 0.02
query8 0.06 0.04 0.04
query9 0.57 0.49 0.48
query10 0.55 0.54 0.54
query11 0.15 0.12 0.11
query12 0.16 0.12 0.12
query13 0.61 0.58 0.59
query14 0.78 0.76 0.81
query15 0.84 0.83 0.81
query16 0.37 0.36 0.36
query17 1.05 1.01 1.05
query18 0.22 0.20 0.21
query19 1.85 1.78 1.73
query20 0.01 0.02 0.01
query21 15.41 0.66 0.67
query22 3.95 7.00 2.54
query23 18.32 1.41 1.28
query24 2.17 0.22 0.21
query25 0.14 0.08 0.08
query26 0.27 0.18 0.18
query27 0.07 0.08 0.07
query28 13.22 1.02 1.00
query29 12.63 3.33 3.30
query30 0.24 0.06 0.06
query31 2.87 0.40 0.39
query32 3.29 0.48 0.48
query33 2.96 3.00 3.00
query34 17.12 4.36 4.41
query35 4.42 4.41 4.42
query36 0.65 0.48 0.49
query37 0.19 0.16 0.17
query38 0.16 0.14 0.16
query39 0.05 0.04 0.04
query40 0.15 0.12 0.12
query41 0.09 0.06 0.05
query42 0.06 0.05 0.04
query43 0.05 0.05 0.04
Total cold run time: 109.38 s
Total hot run time: 31.27 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2297056462
<details>
<summary>TPC-DS: <b>Total hot run time: 195462 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 26c7330ea2ca69f58795f6cc0b7821111e82c0d5, data reload: false
query1 1328 904 896 896
query2 6630 2082 1939 1939
query3 10736 3805 3803 3803
query4 58330 25176 23404 23404
query5 5830 737 728 728
query6 542 209 209 209
query7 6403 332 336 332
query8 538 437 459 437
query9 9152 2537 2513 2513
query10 602 349 338 338
query11 18363 15018 15463 15018
query12 227 151 141 141
query13 1688 438 472 438
query14 11553 7240 6909 6909
query15 246 194 208 194
query16 7668 522 537 522
query17 1201 638 623 623
query18 2129 346 336 336
query19 302 170 165 165
query20 154 138 139 138
query21 245 166 148 148
query22 4482 4352 4634 4352
query23 34193 33918 33690 33690
query24 5702 3030 3077 3030
query25 588 439 449 439
query26 717 185 205 185
query27 1861 300 314 300
query28 4252 2172 2152 2152
query29 731 452 453 452
query30 232 184 186 184
query31 1024 847 819 819
query32 98 77 79 77
query33 499 359 339 339
query34 890 511 494 494
query35 859 795 773 773
query36 1062 979 953 953
query37 156 103 106 103
query38 3998 3837 3781 3781
query39 1525 1472 1457 1457
query40 238 158 157 157
query41 138 135 135 135
query42 137 117 115 115
query43 561 511 507 507
query44 1154 784 795 784
query45 227 196 196 196
query46 1114 779 747 747
query47 1909 1821 1854 1821
query48 419 338 333 333
query49 905 583 589 583
query50 858 466 476 466
query51 6890 6770 6722 6722
query52 126 111 108 108
query53 304 225 244 225
query54 628 529 492 492
query55 91 88 91 88
query56 339 330 315 315
query57 1224 1135 1128 1128
query58 307 313 296 296
query59 3016 2878 2833 2833
query60 356 331 330 330
query61 152 146 145 145
query62 796 712 694 694
query63 262 229 228 228
query64 3426 1841 1822 1822
query65 3237 3182 3203 3182
query66 1022 732 670 670
query67 15239 15049 14920 14920
query68 4918 564 575 564
query69 536 318 311 311
query70 1222 1152 1171 1152
query71 496 315 305 305
query72 7494 2272 2055 2055
query73 795 351 362 351
query74 9491 8754 8781 8754
query75 3529 2744 2726 2726
query76 2764 1033 1036 1033
query77 873 430 433 430
query78 9632 9177 9069 9069
query79 7151 561 550 550
query80 1131 599 611 599
query81 606 260 254 254
query82 917 164 158 158
query83 419 209 208 208
query84 307 94 105 94
query85 983 355 352 352
query86 399 317 322 317
query87 4362 4123 4200 4123
query88 4584 2464 2507 2464
query89 444 318 326 318
query90 2137 229 222 222
query91 151 130 125 125
query92 89 74 73 73
query93 5986 539 554 539
query94 938 307 318 307
query95 385 297 293 293
query96 635 281 287 281
query97 3218 3069 3081 3069
query98 246 225 218 218
query99 1723 1295 1311 1295
Total cold run time: 330372 ms
Total hot run time: 195462 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2284304022
<details>
<summary>TPC-H: <b>Total hot run time: 39994 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 1ee23142cdd036222be1b6f5f0645252c6951fd9, data reload: false
------ Round 1 ----------------------------------
q1 18257 4662 4393 4393
q2 2729 185 192 185
q3 11755 1154 1167 1154
q4 10660 748 670 670
q5 8234 2615 2530 2530
q6 232 141 144 141
q7 992 588 594 588
q8 9223 1912 1909 1909
q9 8713 6574 6571 6571
q10 7044 2254 2251 2251
q11 470 240 241 240
q12 390 221 221 221
q13 17753 2954 2964 2954
q14 284 239 237 237
q15 524 482 464 464
q16 631 521 521 521
q17 977 765 779 765
q18 8101 7432 7505 7432
q19 5698 1078 1139 1078
q20 741 423 422 422
q21 5374 4285 4708 4285
q22 1085 1042 983 983
Total cold run time: 119867 ms
Total hot run time: 39994 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4532 4273 4265 4265
q2 380 274 273 273
q3 2862 2619 2612 2612
q4 1862 1604 1579 1579
q5 5276 5220 5277 5220
q6 225 133 131 131
q7 2027 1625 1659 1625
q8 3166 3343 3331 3331
q9 8451 8327 8317 8317
q10 3363 3116 3099 3099
q11 594 475 490 475
q12 782 599 603 599
q13 16979 2980 2957 2957
q14 292 264 269 264
q15 509 488 477 477
q16 598 571 559 559
q17 1793 1481 1473 1473
q18 7725 7509 7493 7493
q19 1670 1473 1520 1473
q20 2113 1916 1896 1896
q21 5132 5042 5140 5042
q22 1089 1001 1003 1001
Total cold run time: 71420 ms
Total hot run time: 54161 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2285206704
run cloud_p0
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2312205190
<details>
<summary>TPC-H: <b>Total hot run time: 38102 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit fb825b12499087f8dea29592d393d5582d3623c3, data reload: false
------ Round 1 ----------------------------------
q1 18034 5219 4293 4293
q2 2026 184 182 182
q3 11744 970 1178 970
q4 10524 793 776 776
q5 7793 2912 2760 2760
q6 222 134 134 134
q7 964 621 608 608
q8 9325 2095 2093 2093
q9 7048 6537 6570 6537
q10 7015 2212 2232 2212
q11 473 242 245 242
q12 402 219 221 219
q13 17757 3071 3009 3009
q14 282 237 235 235
q15 521 486 494 486
q16 497 389 393 389
q17 995 677 667 667
q18 7490 6802 6843 6802
q19 1395 1020 985 985
q20 681 331 333 331
q21 3915 3167 3151 3151
q22 1098 1021 1031 1021
Total cold run time: 110201 ms
Total hot run time: 38102 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4321 4292 4254 4254
q2 390 261 284 261
q3 2929 2672 2634 2634
q4 1992 1630 1635 1630
q5 5726 5722 5779 5722
q6 239 139 139 139
q7 2217 1862 1830 1830
q8 3320 3452 3543 3452
q9 8890 8881 8833 8833
q10 3608 3382 3356 3356
q11 620 500 500 500
q12 817 671 645 645
q13 16458 3068 3250 3068
q14 325 287 287 287
q15 544 514 494 494
q16 503 446 436 436
q17 1830 1513 1546 1513
q18 8191 7944 7995 7944
q19 1712 1527 1604 1527
q20 2159 1899 1898 1898
q21 5821 5470 5641 5470
q22 1153 1009 1010 1009
Total cold run time: 73765 ms
Total hot run time: 56902 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2312960925
<details>
<summary>TPC-DS: <b>Total hot run time: 192287 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 40557e2131ead7df254d700743017f557f0777e6, data reload: false
query1 1265 891 888 888
query2 6329 1912 1920 1912
query3 10584 3856 3863 3856
query4 59555 27470 23284 23284
query5 5387 499 510 499
query6 404 163 159 159
query7 5786 295 296 295
query8 280 212 216 212
query9 9076 2487 2496 2487
query10 505 267 263 263
query11 18530 14935 15357 14935
query12 155 99 101 99
query13 1568 388 381 381
query14 10750 7337 7335 7335
query15 220 172 176 172
query16 7575 477 470 470
query17 1136 586 585 585
query18 2048 312 304 304
query19 288 151 154 151
query20 119 107 111 107
query21 206 104 106 104
query22 4615 4410 4377 4377
query23 34423 33096 33491 33096
query24 6026 2825 2860 2825
query25 531 391 379 379
query26 689 155 154 154
query27 1767 284 277 277
query28 3749 2055 2045 2045
query29 691 401 402 401
query30 237 152 161 152
query31 963 755 768 755
query32 85 54 56 54
query33 468 289 275 275
query34 867 480 481 480
query35 840 698 715 698
query36 1087 922 932 922
query37 138 85 79 79
query38 3983 3863 3937 3863
query39 1455 1377 1497 1377
query40 198 116 111 111
query41 46 45 44 44
query42 119 97 96 96
query43 494 471 472 471
query44 1086 749 755 749
query45 193 168 165 165
query46 1105 759 777 759
query47 1878 1800 1806 1800
query48 376 292 295 292
query49 767 439 443 439
query50 826 427 414 414
query51 7066 7099 7031 7031
query52 101 87 88 87
query53 253 181 192 181
query54 570 477 468 468
query55 77 78 79 78
query56 302 271 274 271
query57 1188 1094 1042 1042
query58 230 234 229 229
query59 3148 2747 2942 2747
query60 310 273 290 273
query61 131 119 123 119
query62 778 667 669 667
query63 225 184 190 184
query64 2928 766 726 726
query65 3246 3167 3143 3143
query66 699 347 359 347
query67 15335 15116 15146 15116
query68 3494 586 562 562
query69 414 276 281 276
query70 1200 1088 1121 1088
query71 364 279 276 276
query72 6499 4034 3934 3934
query73 750 336 345 336
query74 9482 8793 8900 8793
query75 3364 2683 2717 2683
query76 1499 925 948 925
query77 530 327 328 327
query78 10338 9128 9029 9029
query79 1086 546 544 544
query80 874 499 524 499
query81 556 228 225 225
query82 239 135 136 135
query83 224 147 148 147
query84 261 77 75 75
query85 836 285 283 283
query86 364 293 298 293
query87 4387 4317 4202 4202
query88 3184 2386 2370 2370
query89 400 291 281 281
query90 1997 192 195 192
query91 122 100 100 100
query92 63 53 55 53
query93 1882 541 548 541
query94 778 285 306 285
query95 347 272 268 268
query96 642 278 274 274
query97 3203 3078 3075 3075
query98 220 202 203 202
query99 1577 1258 1299 1258
Total cold run time: 309231 ms
Total hot run time: 192287 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2245098501
<details>
<summary>TPC-DS: <b>Total hot run time: 174099 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit d47f33a15e68079183da96a15302b529dc1c36a2, data reload: false
query1 910 371 363 363
query2 6448 1891 1811 1811
query3 6647 208 218 208
query4 25909 17478 17392 17392
query5 3724 479 493 479
query6 278 185 178 178
query7 4592 293 298 293
query8 253 206 199 199
query9 8468 2457 2417 2417
query10 444 307 260 260
query11 10654 10192 10091 10091
query12 115 91 88 88
query13 1637 373 365 365
query14 10227 7665 7243 7243
query15 224 165 167 165
query16 7511 458 493 458
query17 1130 547 530 530
query18 1362 277 266 266
query19 190 153 142 142
query20 87 82 81 81
query21 206 131 125 125
query22 4349 4098 4047 4047
query23 34032 33717 33673 33673
query24 10979 2981 2938 2938
query25 611 387 396 387
query26 709 152 158 152
query27 2188 278 280 278
query28 6181 2093 2104 2093
query29 884 661 648 648
query30 264 155 153 153
query31 994 753 759 753
query32 101 56 56 56
query33 657 338 336 336
query34 895 485 493 485
query35 876 748 731 731
query36 1133 958 972 958
query37 142 80 81 80
query38 2893 2882 2838 2838
query39 918 875 850 850
query40 225 126 130 126
query41 49 46 52 46
query42 108 105 104 104
query43 488 478 465 465
query44 1096 737 739 737
query45 202 169 167 167
query46 1098 790 719 719
query47 1919 1789 1826 1789
query48 368 289 286 286
query49 828 403 402 402
query50 780 386 386 386
query51 6863 6778 6631 6631
query52 101 90 87 87
query53 358 290 281 281
query54 877 451 446 446
query55 77 74 74 74
query56 283 263 267 263
query57 1145 1042 1074 1042
query58 248 253 249 249
query59 2786 2582 2573 2573
query60 310 272 282 272
query61 99 95 94 94
query62 806 640 627 627
query63 324 290 279 279
query64 9211 2192 1658 1658
query65 3169 3086 3131 3086
query66 745 325 333 325
query67 15638 15206 14964 14964
query68 4463 542 555 542
query69 455 331 339 331
query70 1213 1152 1116 1116
query71 369 276 271 271
query72 7272 5836 5618 5618
query73 762 329 327 327
query74 6198 5753 5724 5724
query75 3428 2668 2695 2668
query76 2234 921 1001 921
query77 468 295 298 295
query78 9537 9167 11057 9167
query79 3232 528 533 528
query80 1523 541 466 466
query81 596 221 225 221
query82 668 135 134 134
query83 290 167 165 165
query84 279 91 85 85
query85 1915 315 340 315
query86 477 325 310 310
query87 3307 3163 3122 3122
query88 4141 2394 2406 2394
query89 467 381 376 376
query90 1742 192 192 192
query91 127 101 102 101
query92 56 48 50 48
query93 3595 522 512 512
query94 1125 297 290 290
query95 416 314 333 314
query96 611 275 280 275
query97 3225 3033 3104 3033
query98 220 201 198 198
query99 1617 1263 1252 1252
Total cold run time: 276051 ms
Total hot run time: 174099 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2249218049
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1690977477
##########
cloud/src/meta-service/txn_lazy_committer.h:
##########
@@ -0,0 +1,65 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <gen_cpp/cloud.pb.h>
Review Comment:
warning: 'gen_cpp/cloud.pb.h' file not found [clang-diagnostic-error]
```cpp
#include <gen_cpp/cloud.pb.h>
^
```
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,208 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+extern void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+extern void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+extern void make_committed_txn_visible(const std::string& instance_id, int64_t db_id,
+ int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
Review Comment:
warning: function 'TxnLazyCommitTask' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:41:** 130 lines including whitespace and comments (threshold 80)
```cpp
TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
^
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2250325145
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2249285153
<details>
<summary>TPC-DS: <b>Total hot run time: 172476 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit a7e2b1bd85dd3827c86fb9ead1aa462b016a3aba, data reload: false
query1 920 379 371 371
query2 6462 1907 1803 1803
query3 6674 209 216 209
query4 24802 17722 17341 17341
query5 4173 481 495 481
query6 269 172 159 159
query7 4605 288 288 288
query8 244 197 198 197
query9 8453 2423 2398 2398
query10 454 308 295 295
query11 11869 10009 10177 10009
query12 134 87 80 80
query13 1631 372 368 368
query14 10274 6930 7830 6930
query15 226 176 171 171
query16 7840 484 473 473
query17 1579 586 553 553
query18 2007 287 292 287
query19 206 155 156 155
query20 89 85 84 84
query21 207 130 127 127
query22 4263 4156 4062 4062
query23 33805 33118 33094 33094
query24 11108 2884 2933 2884
query25 659 393 393 393
query26 1501 157 156 156
query27 2853 275 284 275
query28 7292 2029 2011 2011
query29 1004 645 644 644
query30 288 146 151 146
query31 971 733 756 733
query32 97 55 57 55
query33 793 359 341 341
query34 897 478 498 478
query35 847 741 736 736
query36 1102 917 934 917
query37 151 80 82 80
query38 2909 2801 2760 2760
query39 914 821 817 817
query40 290 121 122 121
query41 46 46 45 45
query42 125 106 102 102
query43 498 476 454 454
query44 1237 730 729 729
query45 203 174 175 174
query46 1097 718 745 718
query47 1886 1779 1805 1779
query48 370 293 305 293
query49 1178 435 421 421
query50 777 394 391 391
query51 6973 6628 6663 6628
query52 106 94 97 94
query53 361 293 297 293
query54 1047 457 460 457
query55 77 75 76 75
query56 309 293 295 293
query57 1184 1011 1031 1011
query58 263 253 282 253
query59 2886 2708 2559 2559
query60 314 275 279 275
query61 95 93 103 93
query62 850 643 671 643
query63 330 292 293 292
query64 10598 2222 1707 1707
query65 3169 3107 3096 3096
query66 1377 346 331 331
query67 15696 14833 14889 14833
query68 8798 548 542 542
query69 754 489 370 370
query70 1427 1147 1099 1099
query71 522 281 279 279
query72 9281 5564 5564 5564
query73 2262 326 326 326
query74 6088 5671 5619 5619
query75 5023 2711 2654 2654
query76 5417 978 960 960
query77 813 306 305 305
query78 10359 9366 8956 8956
query79 10962 543 538 538
query80 1076 479 489 479
query81 589 219 232 219
query82 339 139 132 132
query83 328 168 166 166
query84 274 83 86 83
query85 1029 315 306 306
query86 349 297 342 297
query87 3380 3195 3117 3117
query88 4900 2358 2370 2358
query89 513 386 392 386
query90 2125 196 196 196
query91 132 99 102 99
query92 60 48 48 48
query93 6731 532 525 525
query94 1458 300 296 296
query95 414 317 322 317
query96 622 271 275 271
query97 3189 3057 3000 3000
query98 228 208 195 195
query99 1582 1253 1271 1253
Total cold run time: 308938 ms
Total hot run time: 172476 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1708566029
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,208 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
+ std::stringstream ss;
+ do {
+ code_ = MetaServiceCode::OK;
+ msg_.clear();
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id_, txn_id_, txn_kv_, code_, msg_, &db_id, &tmp_rowset_metas);
+ if (code_ != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id_ << " code=" << code_;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id_
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id_;
+ break;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t, std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
+ partition_to_tmp_rowset_metas;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].emplace_back();
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().first =
+ tmp_rowset_key;
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().second =
+ tmp_rowset_pb;
+ }
+
+ // tablet_id -> TabletIndexPB
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ for (auto& [partition_id, tmp_rowset_metas] : partition_to_tmp_rowset_metas) {
+ for (size_t i = 0; i < tmp_rowset_metas.size();
+ i += config::txn_lazy_max_rowsets_per_batch) {
+ size_t end = (i + config::txn_lazy_max_rowsets_per_batch) > tmp_rowset_metas.size()
+ ? tmp_rowset_metas.size()
+ : i + config::txn_lazy_max_rowsets_per_batch;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>
+ sub_partition_tmp_rowset_metas(tmp_rowset_metas.begin() + i,
+ tmp_rowset_metas.begin() + end);
+ convert_tmp_rowsets(instance_id_, txn_id_, txn_kv_, code_, msg_, db_id,
+ sub_partition_tmp_rowset_metas, tablet_ids);
+ if (code_ != MetaServiceCode::OK) break;
+ }
+ if (code_ != MetaServiceCode::OK) break;
+
+ DCHECK(tmp_rowset_metas.size() > 0);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code_ = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id_ << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+
+ int64_t table_id = -1;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ if (table_id <= 0) {
+ table_id = tablet_ids[tmp_rowset_pb.tablet_id()].table_id();
+ }
+ txn->remove(tmp_rowset_key);
+ }
+
+ DCHECK(table_id > 0);
+ DCHECK(partition_id > 0);
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id_, db_id, table_id, partition_id});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code_ = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id_
+ << " key=" << hex(ver_key) << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id_ << " key=" << hex(ver_key);
+ msg_ = ss.str();
+ break;
+ }
+
+ if (version_pb.has_txn_id() && version_pb.txn_id() == txn_id_) {
+ version_pb.clear_txn_id();
+ ver_val.clear();
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id_;
+ msg_ = ss.str();
+ return;
+ }
+ txn->put(ver_key, ver_val);
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
Review Comment:
> Handle `TxnErrorCode::TXN_CONFLICT` too.
Add a retry for lazy task `commit` method
##########
cloud/src/recycler/recycler_service.cpp:
##########
@@ -42,8 +42,12 @@ extern int reset_s3_rate_limiter(S3RateLimitType type, size_t max_speed, size_t
extern std::tuple<int, std::string_view> convert_ms_code_to_http_code(MetaServiceCode ret);
RecyclerServiceImpl::RecyclerServiceImpl(std::shared_ptr<TxnKv> txn_kv, Recycler* recycler,
- Checker* checker)
- : txn_kv_(std::move(txn_kv)), recycler_(recycler), checker_(checker) {}
+ Checker* checker,
+ std::shared_ptr<TxnLazyCommitter> txn_lazy_committer)
+ : txn_kv_(std::move(txn_kv)),
+ recycler_(recycler),
+ checker_(checker),
+ txn_lazy_committer_(txn_lazy_committer) {}
Review Comment:
>
done
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2297935290
<details>
<summary>TPC-DS: <b>Total hot run time: 196645 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 43feec09f2a80e3fe7f3b07ebc1b5b49bdf0e0bf, data reload: false
query1 1365 911 893 893
query2 6614 1945 1962 1945
query3 10789 3964 3900 3900
query4 56317 23837 23261 23261
query5 5707 705 707 705
query6 544 215 232 215
query7 6347 321 319 319
query8 546 438 443 438
query9 9007 2531 2519 2519
query10 575 341 329 329
query11 17100 15216 15086 15086
query12 205 144 165 144
query13 1645 455 423 423
query14 11458 7570 7320 7320
query15 288 191 194 191
query16 7595 547 532 532
query17 1154 640 622 622
query18 1984 385 369 369
query19 329 170 171 170
query20 146 137 139 137
query21 251 143 143 143
query22 4602 4636 4384 4384
query23 34553 33655 34015 33655
query24 5696 2957 2989 2957
query25 578 435 432 432
query26 702 179 179 179
query27 1746 311 310 310
query28 3793 2187 2163 2163
query29 722 472 449 449
query30 230 189 201 189
query31 1063 879 830 830
query32 100 84 83 83
query33 510 358 344 344
query34 904 508 492 492
query35 841 787 785 785
query36 1094 966 954 954
query37 159 103 99 99
query38 3967 3904 3789 3789
query39 1532 1474 1473 1473
query40 232 155 154 154
query41 141 158 140 140
query42 144 118 116 116
query43 523 501 507 501
query44 1125 776 791 776
query45 228 195 197 195
query46 1121 764 771 764
query47 1986 1902 1887 1887
query48 418 344 334 334
query49 922 584 584 584
query50 860 460 469 460
query51 6791 6810 6865 6810
query52 127 107 115 107
query53 297 225 227 225
query54 614 510 501 501
query55 90 89 89 89
query56 334 320 306 306
query57 1224 1156 1187 1156
query58 302 302 299 299
query59 2952 2757 2908 2757
query60 346 324 324 324
query61 152 145 146 145
query62 775 711 719 711
query63 255 230 230 230
query64 3339 1922 1887 1887
query65 3252 3199 3183 3183
query66 1034 692 678 678
query67 15579 15088 15010 15010
query68 6810 584 616 584
query69 605 425 328 328
query70 1179 1111 1166 1111
query71 501 313 310 310
query72 6713 2277 2090 2090
query73 809 353 354 353
query74 9166 8853 8851 8851
query75 3742 2780 2766 2766
query76 3464 1039 1011 1011
query77 675 431 436 431
query78 10075 9111 9229 9111
query79 5121 548 552 548
query80 2623 604 602 602
query81 619 259 264 259
query82 856 162 159 159
query83 359 217 215 215
query84 303 101 98 98
query85 1393 370 365 365
query86 487 301 322 301
query87 4544 4341 4277 4277
query88 4583 2476 2480 2476
query89 441 318 321 318
query90 2118 225 233 225
query91 151 131 126 126
query92 85 78 75 75
query93 5158 550 551 550
query94 994 332 320 320
query95 397 298 333 298
query96 613 286 292 286
query97 3224 3132 3113 3113
query98 265 226 230 226
query99 1808 1334 1305 1305
Total cold run time: 327802 ms
Total hot run time: 196645 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2303703071
<details>
<summary>ClickBench: <b>Total hot run time: 30.69 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 740144c09664bd5fcc4a77551e5f4fdf659aa12d, data reload: false
query1 0.05 0.05 0.04
query2 0.08 0.04 0.04
query3 0.22 0.06 0.05
query4 1.67 0.10 0.09
query5 0.52 0.49 0.49
query6 1.15 0.74 0.72
query7 0.02 0.01 0.01
query8 0.06 0.05 0.05
query9 0.55 0.49 0.49
query10 0.55 0.55 0.55
query11 0.16 0.12 0.12
query12 0.16 0.12 0.14
query13 0.61 0.60 0.59
query14 0.77 0.80 0.79
query15 0.83 0.83 0.84
query16 0.37 0.37 0.38
query17 1.06 1.06 1.01
query18 0.22 0.21 0.20
query19 1.88 1.76 1.78
query20 0.02 0.01 0.01
query21 15.43 0.67 0.65
query22 4.20 7.79 1.49
query23 18.28 1.48 1.25
query24 2.07 0.27 0.22
query25 0.17 0.09 0.09
query26 0.27 0.18 0.19
query27 0.08 0.09 0.08
query28 13.23 1.03 1.01
query29 12.70 3.37 3.33
query30 0.43 0.25 0.24
query31 2.80 0.41 0.41
query32 3.23 0.49 0.49
query33 2.94 2.95 2.98
query34 16.96 4.36 4.40
query35 4.48 4.47 4.37
query36 0.67 0.49 0.51
query37 0.21 0.18 0.17
query38 0.17 0.16 0.17
query39 0.06 0.06 0.05
query40 0.19 0.16 0.16
query41 0.12 0.07 0.07
query42 0.07 0.07 0.08
query43 0.07 0.07 0.07
Total cold run time: 109.78 s
Total hot run time: 30.69 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "gavinchou (via GitHub)" <gi...@apache.org>.
gavinchou commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1730411458
##########
cloud/src/recycler/recycler.cpp:
##########
@@ -1119,6 +1200,12 @@ int InstanceRecycler::recycle_tablets(int64_t table_id, int64_t index_id, int64_
return -1;
}
int64_t tablet_id = tablet_meta_pb.tablet_id();
+
+ if (!check_lazy_txn_finished(txn_kv_, instance_id_, tablet_meta_pb.tablet_id())) {
+ LOG(WARNING) << "lazy txn not finished tablet_id=" << tablet_meta_pb.tablet_id();
Review Comment:
LOG
"lazy txn not finished, skip recycling. tablet_id= ... txn_id ..."
and add a bvar to monitor `skip_recyle_tablet_lazy_txn`
##########
cloud/src/recycler/recycler.cpp:
##########
@@ -1222,6 +1309,10 @@ int InstanceRecycler::recycle_tablets(int64_t table_id, int64_t index_id, int64_
int ret = scan_and_recycle(tablet_key_begin, tablet_key_end, std::move(recycle_func),
std::move(loop_done));
+ if (ret != 0) {
+ LOG(WARNING) << "failed to scan_and_recycle, instance_id=" << instance_id_;
Review Comment:
also log table id index_id partition id and db id (if has)
##########
cloud/src/recycler/recycler.cpp:
##########
@@ -1707,6 +1798,64 @@ int InstanceRecycler::recycle_rowsets() {
return ret;
}
+bool check_txn_abort(std::shared_ptr<TxnKv> txn_kv, const std::string& instance_id,
Review Comment:
add comment for to describe the behavior
##########
cloud/src/recycler/recycler.cpp:
##########
@@ -824,6 +831,78 @@ int InstanceRecycler::recycle_indexes() {
return scan_and_recycle(index_key0, index_key1, std::move(recycle_func), std::move(loop_done));
}
+bool check_lazy_txn_finished(std::shared_ptr<TxnKv> txn_kv, const std::string instance_id,
+ int64_t tablet_id) {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ LOG(WARNING) << "failed to create txn, instance_id=" << instance_id
+ << " tablet_id=" << tablet_id << " err=" << err;
+ return false;
+ }
+
+ std::string tablet_idx_key = meta_tablet_idx_key({instance_id, tablet_id});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ LOG(WARNING) << "failed to get tablet index, instance_id=" << instance_id
+ << " tablet_id=" << tablet_id << " err=" << err
+ << " key=" << hex(tablet_idx_key);
+ return false;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ LOG(WARNING) << "failed to parse tablet_idx_pb, instance_id=" << instance_id
+ << " tablet_id=" << tablet_id;
+ return false;
+ }
+
+ if (!tablet_idx_pb.has_db_id()) {
+ return true;
+ }
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id, tablet_idx_pb.db_id(), tablet_idx_pb.table_id(),
+ tablet_idx_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ return true;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ LOG(WARNING) << "failed to get partition version, instance_id=" << instance_id
+ << " db_id=" << tablet_idx_pb.db_id()
+ << " table_id=" << tablet_idx_pb.table_id()
+ << " partition_id=" << tablet_idx_pb.partition_id()
+ << " tablet_id=" << tablet_id << " key=" << hex(ver_key) << " err=" << err;
+ return false;
+ }
+
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ LOG(WARNING) << "failed to parse version_pb, instance_id=" << instance_id
+ << " db_id=" << tablet_idx_pb.db_id()
+ << " table_id=" << tablet_idx_pb.table_id()
+ << " partition_id=" << tablet_idx_pb.partition_id()
+ << " tablet_id=" << tablet_id << " key=" << hex(ver_key);
+ return false;
+ }
+
+ if (version_pb.has_txn_id()) {
+ LOG(WARNING) << "lazy txn not finished, instance_id=" << instance_id
Review Comment:
it seems to be an INFO
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1732234447
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
msg = ss.str();
return;
}
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
- std::string_view ver_key = i.first;
- ver_key.remove_prefix(1); // Remove key space
- // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- int ret = decode_key(&ver_key, &out);
- if (ret != 0) [[unlikely]] {
- // decode version key error means this is something wrong,
- // we can not continue this txn
- LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = "decode version key error";
- return;
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
}
- int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
- int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
- VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+ // save versions for partition
+ int64_t version_update_time_ms =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ response->set_version_update_time_ms(version_update_time_ms);
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_txn_id(txn_id);
+ version_pb.set_update_time_ms(version_update_time_ms);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- response->add_table_ids(table_id);
- response->add_partition_ids(partition_id);
- response->add_versions(i.second);
- }
+ txn->put(i.first, ver_val);
+ LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
+ << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+
+ std::string_view ver_key = i.first;
+ ver_key.remove_prefix(1); // Remove key space
+ // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
+ int ret = decode_key(&ver_key, &out);
Review Comment:
in order to check `decode_key` bug
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2259512593
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2260228866
<details>
<summary>TPC-DS: <b>Total hot run time: 169394 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit ae48134efcfe7887d2b0b6f2d645e9c4fac57e59, data reload: false
query1 916 366 366 366
query2 6454 1687 1579 1579
query3 6665 210 226 210
query4 20233 17151 17102 17102
query5 3666 515 513 513
query6 274 164 165 164
query7 4602 307 291 291
query8 266 200 193 193
query9 8499 2403 2384 2384
query10 449 282 265 265
query11 10473 9989 9921 9921
query12 124 89 87 87
query13 1642 382 380 380
query14 10035 7426 7738 7426
query15 200 168 160 160
query16 6770 449 493 449
query17 962 568 559 559
query18 1824 286 290 286
query19 194 150 147 147
query20 93 83 82 82
query21 210 101 97 97
query22 4261 3995 3887 3887
query23 34028 33760 33757 33757
query24 10000 3134 3046 3046
query25 677 418 422 418
query26 1665 155 152 152
query27 2945 295 291 291
query28 7387 2035 2023 2023
query29 1128 457 410 410
query30 238 154 158 154
query31 952 769 770 769
query32 104 53 57 53
query33 711 324 339 324
query34 944 492 513 492
query35 885 753 733 733
query36 1026 894 876 876
query37 164 78 79 78
query38 2863 2756 2723 2723
query39 870 848 798 798
query40 252 118 112 112
query41 47 45 46 45
query42 124 97 106 97
query43 450 404 419 404
query44 1193 728 739 728
query45 222 175 174 174
query46 1086 827 789 789
query47 1798 1684 1713 1684
query48 361 301 297 297
query49 911 417 413 413
query50 893 439 436 436
query51 6735 6717 6663 6663
query52 104 91 101 91
query53 258 181 184 181
query54 641 444 446 444
query55 73 74 75 74
query56 279 259 250 250
query57 1138 1036 991 991
query58 293 259 269 259
query59 2535 2316 2304 2304
query60 291 288 302 288
query61 109 92 93 92
query62 889 652 641 641
query63 207 189 177 177
query64 5635 1892 1873 1873
query65 3148 3089 3069 3069
query66 1043 397 335 335
query67 15145 14843 14737 14737
query68 4287 564 577 564
query69 451 308 295 295
query70 1089 1034 1087 1034
query71 395 274 282 274
query72 7077 2697 2468 2468
query73 762 329 328 328
query74 5960 5652 5565 5565
query75 3355 2710 2740 2710
query76 2207 1355 1397 1355
query77 474 320 326 320
query78 9431 9207 8865 8865
query79 2129 528 544 528
query80 860 517 521 517
query81 542 225 225 225
query82 773 128 131 128
query83 189 170 177 170
query84 278 81 81 81
query85 1426 311 300 300
query86 456 316 312 312
query87 3217 3065 3099 3065
query88 3722 2429 2416 2416
query89 397 305 281 281
query90 1819 191 193 191
query91 126 102 101 101
query92 60 50 50 50
query93 1791 623 626 623
query94 758 279 295 279
query95 385 266 261 261
query96 603 284 281 281
query97 3191 3035 3061 3035
query98 218 242 197 197
query99 1693 1309 1282 1282
Total cold run time: 261380 ms
Total hot run time: 169394 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2260682341
<details>
<summary>TPC-H: <b>Total hot run time: 41756 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit f23de131c772e5e5b480379dddd6cae001bf04a6, data reload: false
------ Round 1 ----------------------------------
q1 17683 4293 4089 4089
q2 2021 210 222 210
q3 10514 1328 1328 1328
q4 10222 849 994 849
q5 7669 2997 3009 2997
q6 221 134 134 134
q7 1032 607 608 607
q8 9438 1890 1953 1890
q9 8521 6640 6632 6632
q10 8723 3894 3832 3832
q11 429 247 255 247
q12 409 220 223 220
q13 17770 2941 2968 2941
q14 271 244 244 244
q15 529 481 498 481
q16 525 394 390 390
q17 985 951 920 920
q18 8124 7265 7217 7217
q19 1476 1231 1231 1231
q20 573 337 340 337
q21 5279 4676 4710 4676
q22 356 284 284 284
Total cold run time: 112770 ms
Total hot run time: 41756 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4093 4023 3985 3985
q2 324 222 219 219
q3 2995 2981 3226 2981
q4 2048 2025 1978 1978
q5 5676 5513 5466 5466
q6 218 132 152 132
q7 2148 1844 1821 1821
q8 3349 3425 3376 3376
q9 8737 8768 8802 8768
q10 3990 4100 3901 3901
q11 563 447 461 447
q12 779 622 650 622
q13 16510 3123 3121 3121
q14 317 275 270 270
q15 531 493 483 483
q16 471 430 422 422
q17 1777 1743 1749 1743
q18 8421 7802 7804 7802
q19 1724 1716 1781 1716
q20 2053 1878 1858 1858
q21 5787 5532 5303 5303
q22 543 489 455 455
Total cold run time: 73054 ms
Total hot run time: 56869 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1732029358
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -265,6 +267,20 @@ void MetaServiceImpl::get_version(::google::protobuf::RpcController* controller,
msg = "malformed version value";
return;
}
+
+ if (version_pb.has_txn_id()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer_->submit(instance_id, version_pb.txn_id());
Review Comment:
> how do we deal with the "duplicated" submmits to to the commiter add comment here.
txn_lazy_committer_ has a map indent by txn_id used for deduplicate
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2312460807
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2312974858
<details>
<summary>ClickBench: <b>Total hot run time: 30.99 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 40557e2131ead7df254d700743017f557f0777e6, data reload: false
query1 0.04 0.05 0.03
query2 0.08 0.04 0.04
query3 0.22 0.04 0.05
query4 1.67 0.07 0.08
query5 0.52 0.51 0.51
query6 1.12 0.74 0.73
query7 0.02 0.01 0.01
query8 0.05 0.04 0.04
query9 0.56 0.51 0.50
query10 0.54 0.54 0.55
query11 0.15 0.11 0.12
query12 0.15 0.13 0.13
query13 0.62 0.60 0.59
query14 0.74 0.82 0.78
query15 0.83 0.82 0.82
query16 0.38 0.38 0.38
query17 1.07 1.06 1.04
query18 0.20 0.20 0.20
query19 1.95 1.85 1.89
query20 0.01 0.02 0.01
query21 15.41 0.65 0.65
query22 3.95 8.06 2.03
query23 18.28 1.33 1.28
query24 2.16 0.20 0.21
query25 0.16 0.08 0.07
query26 0.26 0.17 0.18
query27 0.07 0.07 0.07
query28 13.22 1.01 0.99
query29 12.63 3.37 3.37
query30 0.24 0.06 0.06
query31 2.89 0.39 0.39
query32 3.28 0.48 0.48
query33 3.01 3.02 3.01
query34 17.00 4.34 4.38
query35 4.45 4.41 4.38
query36 0.65 0.51 0.48
query37 0.20 0.15 0.15
query38 0.15 0.15 0.14
query39 0.04 0.04 0.04
query40 0.15 0.14 0.14
query41 0.10 0.04 0.04
query42 0.07 0.05 0.05
query43 0.05 0.04 0.04
Total cold run time: 109.34 s
Total hot run time: 30.99 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1732710627
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -862,94 +863,485 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
*/
void commit_txn_immediately(
const CommitTxnRequest* request, CommitTxnResponse* response,
- std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
- const std::string& instance_id, int64_t db_id,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
std::stringstream ss;
int64_t txn_id = request->txn_id();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // Get txn info with db_id and txn_id
- std::string info_val; // Will be reused when saving updated txn
- const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
- err = txn->get(info_key, &info_val);
- if (err != TxnErrorCode::TXN_OK) {
- code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
- : cast_as<ErrCategory::READ>(err);
- if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
- ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
- } else {
- ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
- << " err=" << err;
+ // Get txn info with db_id and txn_id
+ std::string info_val; // Will be reused when saving updated txn
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
+ } else {
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
+ }
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
- TxnInfoPB txn_info;
- if (!txn_info.ParseFromString(info_val)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // TODO: do more check like txn state, 2PC etc.
- DCHECK(txn_info.txn_id() == txn_id);
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
- code = MetaServiceCode::TXN_ALREADY_ABORTED;
- ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ // TODO: do more check like txn state, 2PC etc.
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
- if (request->has_is_2pc() && request->is_2pc()) {
- code = MetaServiceCode::TXN_ALREADY_VISIBLE;
- ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(INFO) << msg;
response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- code = MetaServiceCode::OK;
- ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(INFO) << msg;
- response->mutable_txn_info()->CopyFrom(txn_info);
- return;
- }
- if (request->has_is_2pc() && request->is_2pc() &&
- txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
- code = MetaServiceCode::TXN_INVALID_STATUS;
- ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Prepare rowset meta and new_versions
+ // Prepare rowset meta and new_versions
+ // Read tablet indexes in batch.
+ std::vector<std::string> tablet_idx_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
+ }
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ size_t total_rowsets = tmp_rowsets_meta.size();
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ for (size_t i = 0; i < total_rowsets; i++) {
+ uint64_t tablet_id = tmp_rowsets_meta[i].second.tablet_id();
+ if (!tablet_idx_values[i].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " tablet_id=" << tablet_id << " key=" << hex(tablet_idx_keys[i]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "malformed tablet index value tablet_id=" << tablet_id
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ VLOG_DEBUG << "tablet_id:" << tablet_id
+ << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ }
+
+ tablet_idx_keys.clear();
+ tablet_idx_values.clear();
+
+ // {table/partition} -> version
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
+ }
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ size_t total_versions = version_keys.size();
+ for (size_t i = 0; i < total_versions; i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
Review Comment:
done
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2312652072
<details>
<summary>TPC-H: <b>Total hot run time: 38057 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 5f3b5ea8bfb6214887e8d1bb42d8f87233ccc8a0, data reload: false
------ Round 1 ----------------------------------
q1 18300 4642 4298 4298
q2 2049 190 176 176
q3 11534 953 1155 953
q4 10498 741 668 668
q5 7772 2912 2821 2821
q6 225 137 140 137
q7 969 630 601 601
q8 9325 2067 2122 2067
q9 7211 6523 6553 6523
q10 7002 2171 2180 2171
q11 452 251 249 249
q12 403 234 232 232
q13 18836 3080 3030 3030
q14 276 238 243 238
q15 518 480 499 480
q16 511 390 391 390
q17 999 715 757 715
q18 7423 7041 6928 6928
q19 1393 1055 989 989
q20 691 342 335 335
q21 4141 3044 3145 3044
q22 1087 1033 1012 1012
Total cold run time: 111615 ms
Total hot run time: 38057 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4327 4278 4279 4278
q2 377 281 278 278
q3 2901 2677 2683 2677
q4 1914 1695 1680 1680
q5 5700 5723 5833 5723
q6 226 135 138 135
q7 2210 1888 1902 1888
q8 3298 3454 3544 3454
q9 8868 8868 8851 8851
q10 3656 3418 3367 3367
q11 625 519 505 505
q12 834 705 670 670
q13 14293 3137 3267 3137
q14 334 281 283 281
q15 556 518 499 499
q16 493 445 442 442
q17 1856 1557 1570 1557
q18 8302 7890 7960 7890
q19 1763 1538 1721 1538
q20 2181 1911 1922 1911
q21 5724 5504 5413 5413
q22 1183 1033 1031 1031
Total cold run time: 71621 ms
Total hot run time: 57205 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2244960031
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "w41ter (via GitHub)" <gi...@apache.org>.
w41ter commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1692571333
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -237,46 +238,65 @@ void MetaServiceImpl::get_version(::google::protobuf::RpcController* controller,
partition_version_key({instance_id, db_id, table_id, partition_id}, &ver_key);
}
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv_->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- msg = "failed to create txn";
- code = cast_as<ErrCategory::CREATE>(err);
- return;
- }
+ do {
+ code = MetaServiceCode::OK;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ msg = "failed to create txn";
+ code = cast_as<ErrCategory::CREATE>(err);
+ return;
+ }
- std::string ver_val;
- // 0 for success get a key, 1 for key not found, negative for error
- err = txn->get(ver_key, &ver_val);
- VLOG_DEBUG << "xxx get version_key=" << hex(ver_key);
- if (err == TxnErrorCode::TXN_OK) {
- if (is_table_version) {
- int64_t version = 0;
- if (!txn->decode_atomic_int(ver_val, &version)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "malformed table version value";
- return;
- }
- response->set_version(version);
- } else {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(ver_val)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "malformed version value";
- return;
+ std::string ver_val;
+ // 0 for success get a key, 1 for key not found, negative for error
+ err = txn->get(ver_key, &ver_val);
+ VLOG_DEBUG << "xxx get version_key=" << hex(ver_key);
+ if (err == TxnErrorCode::TXN_OK) {
+ if (is_table_version) {
+ int64_t version = 0;
+ if (!txn->decode_atomic_int(ver_val, &version)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "malformed table version value";
+ return;
+ }
+ response->set_version(version);
+ } else {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "malformed version value";
+ return;
+ }
+
+ if (version_pb.has_txn_id()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer_->submit(instance_id, version_pb.txn_id());
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ code = ret.first;
+ msg = ret.second;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING)
+ << "wait txn lazy commit failed, txn_id=" << version_pb.txn_id();
+ return;
+ }
+ continue;
Review Comment:
This can be simplified a bit. After the `wait()` ends, the transaction has already been committed, and the corresponding version is visible. We can return this version directly without retrying.
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -387,10 +412,30 @@ void MetaServiceImpl::batch_get_version(::google::protobuf::RpcController* contr
msg = "malformed version value";
break;
}
+ if (version_pb.has_txn_id()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer_->submit(instance_id, version_pb.txn_id());
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ code = ret.first;
+ msg = ret.second;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "wait txn lazy commit failed, txn_id="
+ << version_pb.txn_id();
+ break;
+ }
+ goto TRY_AGAIN;
Review Comment:
Directly fetching all versions and then waiting for all transactions at once is a simpler approach. For now, let's keep the current method to push the PR merge, and we can address this improvement in another PR.
##########
cloud/src/meta-service/txn_lazy_committer.h:
##########
@@ -0,0 +1,65 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <gen_cpp/cloud.pb.h>
+
+#include <atomic>
+
+#include "common/simple_thread_pool.h"
+#include "meta-service/txn_kv.h"
+
+namespace doris::cloud {
+
+class TxnLazyCommitter;
+
+class TxnLazyCommitTask {
+public:
+ TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer_);
Review Comment:
```suggestion
TxnLazyCommitter* txn_lazy_committer);
```
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,209 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+extern void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+extern void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+extern void make_committed_txn_visible(const std::string& instance_id, int64_t db_id,
+ int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg);
Review Comment:
`extern` is not required here.
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,209 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+extern void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+extern void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+extern void make_committed_txn_visible(const std::string& instance_id, int64_t db_id,
+ int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id,
+ int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+ DCHECK(txn_lazy_committer != nullptr);
+ txn_id_ = txn_id;
+ txn_lazy_committer_ = txn_lazy_committer;
Review Comment:
Initialize in member initializer list, likes:
```c++
TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
std::shared_ptr<TxnKv> txn_kv, TxnLazyCommitter* txn_lazy_committer)
: instance_id_(instance_id),
txn_id_(txn_id),
txn_kv_(std::move(txn_id)),
txn_lazy_committer_(txn_lazy_committer) {
DCHECK(txn_id > 0);
// ...
}
```
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,209 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+extern void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+extern void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+extern void make_committed_txn_visible(const std::string& instance_id, int64_t db_id,
+ int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id,
+ int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+ DCHECK(txn_lazy_committer != nullptr);
+ txn_id_ = txn_id;
+ txn_lazy_committer_ = txn_lazy_committer;
+ task_func_ = [=, this]() {
+ MetaServiceCode code;
+ std::stringstream ss;
+ std::string msg;
+
+ do {
+ code = MetaServiceCode::OK;
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id, txn_id, txn_kv, code, msg, &db_id, &tmp_rowset_metas);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id << " code=" << code;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id;
+ break;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
+ partition_to_tmp_rowset_metas;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].emplace_back();
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().first =
+ tmp_rowset_key;
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().second =
+ tmp_rowset_pb;
+ }
+
+ // tablet_id -> TabletIndexPB
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ for (auto& [partition_id, tmp_rowset_metas] : partition_to_tmp_rowset_metas) {
+ for (size_t i = 0; i < tmp_rowset_metas.size();
+ i += config::txn_lazy_max_rowsets_per_batch) {
+ size_t end =
+ (i + config::txn_lazy_max_rowsets_per_batch) > tmp_rowset_metas.size()
+ ? tmp_rowset_metas.size()
+ : i + config::txn_lazy_max_rowsets_per_batch;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>
+ sub_partition_tmp_rowset_metas(tmp_rowset_metas.begin() + i,
+ tmp_rowset_metas.begin() + end);
+ convert_tmp_rowsets(instance_id, txn_id, txn_kv, code, msg, db_id,
+ sub_partition_tmp_rowset_metas, tablet_ids);
+ if (code != MetaServiceCode::OK) break;
+ }
+ if (code != MetaServiceCode::OK) break;
+
+ DCHECK(tmp_rowset_metas.size() > 0);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ break;
+ }
+
+ int64_t table_id = -1;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ if (table_id <= 0) {
+ table_id = tablet_ids[tmp_rowset_pb.tablet_id()].table_id();
+ }
+ txn->remove(tmp_rowset_key);
+ }
+
+ DCHECK(table_id > 0);
+ DCHECK(partition_id > 0);
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND
+ ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id
+ << " key=" << hex(ver_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ break;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ break;
+ }
+
+ if (version_pb.has_txn_id() && version_pb.txn_id() == txn_id) {
+ version_pb.clear_txn_id();
+ ver_val.clear();
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(ver_key, ver_val);
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ break;
+ }
+ }
+ make_committed_txn_visible(instance_id, db_id, txn_id, txn_kv, code, msg);
+ } while (false);
+
+ std::unique_lock<std::mutex> lock(mutex_);
+ this->code_ = code;
+ this->msg_ = std::move(msg);
+ this->finished_ = true;
+ this->cond_.notify_all();
+ };
+}
+
+std::pair<MetaServiceCode, std::string> TxnLazyCommitTask::wait() {
+ std::unique_lock<std::mutex> lock(mutex_);
+ cond_.wait(lock, [this]() { return this->finished_ == true; });
+ txn_lazy_committer_->remove(txn_id_);
+ return std::make_pair(this->code_, this->msg_);
+}
+
+TxnLazyCommitter::TxnLazyCommitter(std::shared_ptr<TxnKv> txn_kv) {
+ txn_kv_ = txn_kv;
+ worker_pool_ = std::make_unique<SimpleThreadPool>(config::txn_lazy_commit_worker_num);
+ worker_pool_->start();
+}
+
+std::shared_ptr<TxnLazyCommitTask> TxnLazyCommitter::submit(const std::string& instance_id,
+ int64_t txn_id) {
+ std::unique_lock<std::mutex> lock(mutex_);
+ auto iter = running_tasks_.find(txn_id);
+ if (iter != running_tasks_.end()) {
+ return iter->second;
+ }
+
+ auto task = std::make_shared<TxnLazyCommitTask>(instance_id, txn_id, txn_kv_, this);
+ running_tasks_.emplace(txn_id, task);
+ worker_pool_->submit(task->task_func_);
+ return task;
Review Comment:
The use of locks here can be further optimized. For example, it can be modified as follows:
```suggestion
std::shared_ptr<TxnLazyCommitTask> task;
{
std::unique_lock<std::mutex> lock(mutex_);
auto iter = running_tasks_.find(txn_id);
if (iter != running_tasks_.end()) {
return iter->second;
}
task = std::make_shared<TxnLazyCommitTask>(instance_id, txn_id, txn_kv_, this);
running_tasks_.emplace(txn_id, task);
}
worker_pool_->submit(task->task_func_);
return task;
```
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,209 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+extern void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+extern void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+extern void make_committed_txn_visible(const std::string& instance_id, int64_t db_id,
+ int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id,
+ int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+ DCHECK(txn_lazy_committer != nullptr);
+ txn_id_ = txn_id;
+ txn_lazy_committer_ = txn_lazy_committer;
+ task_func_ = [=, this]() {
+ MetaServiceCode code;
+ std::stringstream ss;
+ std::string msg;
+
+ do {
+ code = MetaServiceCode::OK;
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id, txn_id, txn_kv, code, msg, &db_id, &tmp_rowset_metas);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id << " code=" << code;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id;
+ break;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
+ partition_to_tmp_rowset_metas;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].emplace_back();
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().first =
+ tmp_rowset_key;
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().second =
+ tmp_rowset_pb;
Review Comment:
```suggestion
for (auto& rowset_pair : tmp_rowset_metas) {
int64_t partition_id = rowset_pair.second.partition_id();
partition_to_tmp_rowset_metas[partition_id].push_back(std::move(rowset_pair));
```
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -788,6 +788,164 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
txn->put(key, val);
}
}
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (tablet_ids.find(tmp_rowset_pb.tablet_id()) == tablet_ids.end()) {
+ std::string tablet_idx_key;
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()}, &tablet_idx_key);
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (partition_versions.find(tmp_rowset_pb.partition_id()) == partition_versions.end()) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
Review Comment:
There may be conflicts caused by concurrent commits. According to our design expectations, TXN_CONFLICT also needs to be handled. One simple solution is to consider the data already converted if TXN_CONFLICT occurs (this requires that each task uses the same split batch method). Another solution is to retry once if TXN_CONFLICT occurs.
It's essential to manage the competition between transactions properly here.
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -913,320 +1458,420 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
- msg = ss.str();
- return;
- }
- version = version_pb.version();
- } else {
- version = 1;
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
}
- new_versions[version_keys[i]] = version + 1;
+ txn->put(recycle_key, recycle_val);
}
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
Review Comment:
Handle `TXN_CONFLICT`.
##########
cloud/src/meta-service/txn_lazy_committer.h:
##########
@@ -0,0 +1,65 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <gen_cpp/cloud.pb.h>
+
+#include <atomic>
+
+#include "common/simple_thread_pool.h"
+#include "meta-service/txn_kv.h"
+
+namespace doris::cloud {
+
+class TxnLazyCommitter;
+
+class TxnLazyCommitTask {
+public:
+ TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer_);
+
+ std::pair<MetaServiceCode, std::string> wait();
Review Comment:
How about adding a comment?
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -804,91 +962,483 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
*/
void commit_txn_immediately(
const CommitTxnRequest* request, CommitTxnResponse* response,
- std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
- const std::string& instance_id, int64_t db_id,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
Review Comment:
`std::shared_ptr` inherently carries ownership semantics. If `commit_txn_immediately` does not need to transfer the `shared_ptr` (eg, inc reference count), then using a reference would be more appropriate (making the semantics more accurate). For example, `shared_ptr<TxnKv>&` can be changed to `TxnKv&`.
##########
cloud/src/meta-service/txn_lazy_committer.h:
##########
@@ -0,0 +1,65 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <gen_cpp/cloud.pb.h>
+
+#include <atomic>
+
+#include "common/simple_thread_pool.h"
+#include "meta-service/txn_kv.h"
+
+namespace doris::cloud {
+
+class TxnLazyCommitter;
+
+class TxnLazyCommitTask {
+public:
+ TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer_);
+
+ std::pair<MetaServiceCode, std::string> wait();
+
+private:
+ friend class TxnLazyCommitter;
+ int64_t txn_id_;
Review Comment:
```suggestion
friend class TxnLazyCommitter;
int64_t txn_id_;
```
##########
cloud/src/meta-service/txn_lazy_committer.h:
##########
@@ -0,0 +1,65 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <gen_cpp/cloud.pb.h>
+
+#include <atomic>
+
+#include "common/simple_thread_pool.h"
+#include "meta-service/txn_kv.h"
+
+namespace doris::cloud {
+
+class TxnLazyCommitter;
+
+class TxnLazyCommitTask {
Review Comment:
`TxnLazyCommitTask` doesn't need to be exposed to external users, so it can be defined in the cpp file to speed up compilation. This will introduce the issue of `TxnLazyCommitter` not finding the `TxnLazyCommitTask` definition during destruction, which can be resolved by adding `TxnLazyCommitter::~TxnLazyCommitter() = default;` in the cpp file.
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -788,6 +788,164 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
txn->put(key, val);
}
}
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
Review Comment:
Add a debug log.
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -788,6 +788,164 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
txn->put(key, val);
}
}
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (tablet_ids.find(tmp_rowset_pb.tablet_id()) == tablet_ids.end()) {
+ std::string tablet_idx_key;
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()}, &tablet_idx_key);
Review Comment:
```suggestion
std::string tablet_idx_key = meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
```
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,209 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+extern void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+extern void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+extern void make_committed_txn_visible(const std::string& instance_id, int64_t db_id,
+ int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id,
+ int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+ DCHECK(txn_lazy_committer != nullptr);
+ txn_id_ = txn_id;
+ txn_lazy_committer_ = txn_lazy_committer;
+ task_func_ = [=, this]() {
+ MetaServiceCode code;
+ std::stringstream ss;
+ std::string msg;
+
+ do {
+ code = MetaServiceCode::OK;
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id, txn_id, txn_kv, code, msg, &db_id, &tmp_rowset_metas);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id << " code=" << code;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id;
+ break;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
+ partition_to_tmp_rowset_metas;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].emplace_back();
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().first =
+ tmp_rowset_key;
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().second =
+ tmp_rowset_pb;
+ }
+
+ // tablet_id -> TabletIndexPB
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ for (auto& [partition_id, tmp_rowset_metas] : partition_to_tmp_rowset_metas) {
+ for (size_t i = 0; i < tmp_rowset_metas.size();
+ i += config::txn_lazy_max_rowsets_per_batch) {
+ size_t end =
+ (i + config::txn_lazy_max_rowsets_per_batch) > tmp_rowset_metas.size()
+ ? tmp_rowset_metas.size()
+ : i + config::txn_lazy_max_rowsets_per_batch;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>
+ sub_partition_tmp_rowset_metas(tmp_rowset_metas.begin() + i,
+ tmp_rowset_metas.begin() + end);
+ convert_tmp_rowsets(instance_id, txn_id, txn_kv, code, msg, db_id,
+ sub_partition_tmp_rowset_metas, tablet_ids);
+ if (code != MetaServiceCode::OK) break;
+ }
+ if (code != MetaServiceCode::OK) break;
+
+ DCHECK(tmp_rowset_metas.size() > 0);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ break;
+ }
+
+ int64_t table_id = -1;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ if (table_id <= 0) {
+ table_id = tablet_ids[tmp_rowset_pb.tablet_id()].table_id();
+ }
+ txn->remove(tmp_rowset_key);
+ }
+
+ DCHECK(table_id > 0);
+ DCHECK(partition_id > 0);
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND
+ ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id
+ << " key=" << hex(ver_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ break;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ break;
+ }
+
+ if (version_pb.has_txn_id() && version_pb.txn_id() == txn_id) {
+ version_pb.clear_txn_id();
+ ver_val.clear();
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(ver_key, ver_val);
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ break;
+ }
+ }
+ make_committed_txn_visible(instance_id, db_id, txn_id, txn_kv, code, msg);
+ } while (false);
+
+ std::unique_lock<std::mutex> lock(mutex_);
+ this->code_ = code;
+ this->msg_ = std::move(msg);
+ this->finished_ = true;
+ this->cond_.notify_all();
+ };
+}
+
+std::pair<MetaServiceCode, std::string> TxnLazyCommitTask::wait() {
+ std::unique_lock<std::mutex> lock(mutex_);
+ cond_.wait(lock, [this]() { return this->finished_ == true; });
+ txn_lazy_committer_->remove(txn_id_);
+ return std::make_pair(this->code_, this->msg_);
+}
+
+TxnLazyCommitter::TxnLazyCommitter(std::shared_ptr<TxnKv> txn_kv) {
Review Comment:
Initialize in the member initializer list too
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,209 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+extern void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+extern void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+extern void make_committed_txn_visible(const std::string& instance_id, int64_t db_id,
+ int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id,
+ int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+ DCHECK(txn_lazy_committer != nullptr);
+ txn_id_ = txn_id;
+ txn_lazy_committer_ = txn_lazy_committer;
+ task_func_ = [=, this]() {
Review Comment:
Declare this as a member function of `TxnLazyCommitTask`, eg: `TxnLazyCommiter::commit` then change `TxnLazyCommitter::submit` to:
```c++
auto task = std::make_shared<TxnLazyCommitTask>(instance_id, txn_id, txn_kv_, this);
running_tasks_.emplace(txn_id, task);
worker_pool_->submit([task]() { task->commit(); });
```
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -788,6 +788,164 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
txn->put(key, val);
}
}
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (tablet_ids.find(tmp_rowset_pb.tablet_id()) == tablet_ids.end()) {
Review Comment:
```suggestion
if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
```
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -1810,8 +2455,17 @@ void MetaServiceImpl::commit_txn(::google::protobuf::RpcController* controller,
LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id << " code=" << code;
return;
}
- commit_txn_immediately(request, response, txn_kv_, code, msg, instance_id, db_id,
- tmp_rowsets_meta);
+ VLOG_DEBUG << "txn_id=" << txn_id << " tmp_rowset size=" << tmp_rowsets_meta.size();
+ if (config::enable_txn_lazy_commit &&
+ tmp_rowsets_meta.size() >= config::txn_lazy_commit_rowsets_thresold) {
+ commit_txn_eventually(request, response, txn_kv_, txn_lazy_committer_, code, msg,
+ instance_id, db_id, tmp_rowsets_meta);
+ return;
+ }
+
+ commit_txn_immediately(request, response, txn_kv_, txn_lazy_committer_, code, msg, instance_id,
+ db_id, tmp_rowsets_meta);
+ return;
Review Comment:
Redundant `return`.
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,209 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+extern void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+extern void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+extern void make_committed_txn_visible(const std::string& instance_id, int64_t db_id,
+ int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id,
+ int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+ DCHECK(txn_lazy_committer != nullptr);
+ txn_id_ = txn_id;
+ txn_lazy_committer_ = txn_lazy_committer;
+ task_func_ = [=, this]() {
+ MetaServiceCode code;
+ std::stringstream ss;
+ std::string msg;
+
+ do {
+ code = MetaServiceCode::OK;
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id, txn_id, txn_kv, code, msg, &db_id, &tmp_rowset_metas);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id << " code=" << code;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id;
+ break;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
+ partition_to_tmp_rowset_metas;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].emplace_back();
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().first =
+ tmp_rowset_key;
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().second =
+ tmp_rowset_pb;
+ }
+
+ // tablet_id -> TabletIndexPB
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ for (auto& [partition_id, tmp_rowset_metas] : partition_to_tmp_rowset_metas) {
+ for (size_t i = 0; i < tmp_rowset_metas.size();
+ i += config::txn_lazy_max_rowsets_per_batch) {
+ size_t end =
+ (i + config::txn_lazy_max_rowsets_per_batch) > tmp_rowset_metas.size()
+ ? tmp_rowset_metas.size()
+ : i + config::txn_lazy_max_rowsets_per_batch;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>
+ sub_partition_tmp_rowset_metas(tmp_rowset_metas.begin() + i,
+ tmp_rowset_metas.begin() + end);
+ convert_tmp_rowsets(instance_id, txn_id, txn_kv, code, msg, db_id,
+ sub_partition_tmp_rowset_metas, tablet_ids);
+ if (code != MetaServiceCode::OK) break;
+ }
+ if (code != MetaServiceCode::OK) break;
+
+ DCHECK(tmp_rowset_metas.size() > 0);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ break;
+ }
+
+ int64_t table_id = -1;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ if (table_id <= 0) {
+ table_id = tablet_ids[tmp_rowset_pb.tablet_id()].table_id();
+ }
+ txn->remove(tmp_rowset_key);
+ }
+
+ DCHECK(table_id > 0);
+ DCHECK(partition_id > 0);
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND
+ ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id
+ << " key=" << hex(ver_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ break;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ break;
+ }
+
+ if (version_pb.has_txn_id() && version_pb.txn_id() == txn_id) {
+ version_pb.clear_txn_id();
+ ver_val.clear();
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(ver_key, ver_val);
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
Review Comment:
Handle `TXN_CONFLICT` too.
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,209 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+extern void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+extern void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+extern void make_committed_txn_visible(const std::string& instance_id, int64_t db_id,
+ int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id,
+ int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+ DCHECK(txn_lazy_committer != nullptr);
+ txn_id_ = txn_id;
+ txn_lazy_committer_ = txn_lazy_committer;
+ task_func_ = [=, this]() {
+ MetaServiceCode code;
+ std::stringstream ss;
+ std::string msg;
+
+ do {
+ code = MetaServiceCode::OK;
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id, txn_id, txn_kv, code, msg, &db_id, &tmp_rowset_metas);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id << " code=" << code;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id;
+ break;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
+ partition_to_tmp_rowset_metas;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].emplace_back();
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().first =
+ tmp_rowset_key;
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().second =
+ tmp_rowset_pb;
+ }
+
+ // tablet_id -> TabletIndexPB
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ for (auto& [partition_id, tmp_rowset_metas] : partition_to_tmp_rowset_metas) {
+ for (size_t i = 0; i < tmp_rowset_metas.size();
+ i += config::txn_lazy_max_rowsets_per_batch) {
+ size_t end =
+ (i + config::txn_lazy_max_rowsets_per_batch) > tmp_rowset_metas.size()
+ ? tmp_rowset_metas.size()
+ : i + config::txn_lazy_max_rowsets_per_batch;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>
+ sub_partition_tmp_rowset_metas(tmp_rowset_metas.begin() + i,
+ tmp_rowset_metas.begin() + end);
+ convert_tmp_rowsets(instance_id, txn_id, txn_kv, code, msg, db_id,
+ sub_partition_tmp_rowset_metas, tablet_ids);
+ if (code != MetaServiceCode::OK) break;
+ }
+ if (code != MetaServiceCode::OK) break;
+
+ DCHECK(tmp_rowset_metas.size() > 0);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ break;
+ }
+
+ int64_t table_id = -1;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ if (table_id <= 0) {
+ table_id = tablet_ids[tmp_rowset_pb.tablet_id()].table_id();
+ }
+ txn->remove(tmp_rowset_key);
+ }
+
+ DCHECK(table_id > 0);
+ DCHECK(partition_id > 0);
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND
+ ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id
+ << " key=" << hex(ver_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ break;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ break;
+ }
+
+ if (version_pb.has_txn_id() && version_pb.txn_id() == txn_id) {
+ version_pb.clear_txn_id();
+ ver_val.clear();
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(ver_key, ver_val);
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ break;
+ }
+ }
+ make_committed_txn_visible(instance_id, db_id, txn_id, txn_kv, code, msg);
+ } while (false);
+
+ std::unique_lock<std::mutex> lock(mutex_);
+ this->code_ = code;
+ this->msg_ = std::move(msg);
+ this->finished_ = true;
+ this->cond_.notify_all();
+ };
+}
+
+std::pair<MetaServiceCode, std::string> TxnLazyCommitTask::wait() {
+ std::unique_lock<std::mutex> lock(mutex_);
+ cond_.wait(lock, [this]() { return this->finished_ == true; });
+ txn_lazy_committer_->remove(txn_id_);
+ return std::make_pair(this->code_, this->msg_);
Review Comment:
`txn_lazy_committer_->remove(txn_id_)` has lock, try:
```suggestion
{
std::unique_lock<std::mutex> lock(mutex_);
cond_.wait(lock, [this]() { return this->finished_ == true; });
}
txn_lazy_committer_->remove(txn_id_);
// The lock has memory barriers, so access code_, msg_ without lock is safety.
return std::make_pair(this->code_, this->msg_);
```
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -788,6 +788,164 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
txn->put(key, val);
}
}
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
Review Comment:
`partition_versions` is not needed here, since all rowsets belong to the same partition. Read the partition version in here directly.
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -788,6 +788,164 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
txn->put(key, val);
}
}
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (tablet_ids.find(tmp_rowset_pb.tablet_id()) == tablet_ids.end()) {
+ std::string tablet_idx_key;
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()}, &tablet_idx_key);
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val);
Review Comment:
Would using snapshot semantics be sufficient?
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -788,6 +788,164 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
txn->put(key, val);
}
}
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (tablet_ids.find(tmp_rowset_pb.tablet_id()) == tablet_ids.end()) {
+ std::string tablet_idx_key;
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()}, &tablet_idx_key);
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (partition_versions.find(tmp_rowset_pb.partition_id()) == partition_versions.end()) {
Review Comment:
ditto
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2249608295
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2244670548
<details>
<summary>ClickBench: <b>Total hot run time: 30.71 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 0cac9c57dfbabd3aa3c3d90819462ad7e839f881, data reload: false
query1 0.04 0.03 0.03
query2 0.08 0.04 0.05
query3 0.22 0.05 0.05
query4 1.68 0.07 0.07
query5 0.51 0.48 0.50
query6 1.14 0.72 0.72
query7 0.02 0.02 0.01
query8 0.05 0.04 0.04
query9 0.56 0.50 0.49
query10 0.54 0.55 0.55
query11 0.16 0.10 0.12
query12 0.14 0.12 0.12
query13 0.59 0.58 0.58
query14 0.76 0.78 0.81
query15 0.85 0.82 0.83
query16 0.36 0.36 0.37
query17 0.99 1.02 1.03
query18 0.23 0.21 0.22
query19 1.93 1.84 1.74
query20 0.01 0.01 0.01
query21 15.39 0.77 0.68
query22 4.09 7.48 1.93
query23 18.33 1.33 1.29
query24 2.10 0.23 0.22
query25 0.14 0.09 0.08
query26 0.31 0.22 0.20
query27 0.46 0.23 0.23
query28 13.26 1.02 0.99
query29 12.61 3.32 3.29
query30 0.25 0.06 0.05
query31 2.88 0.40 0.39
query32 3.26 0.49 0.46
query33 2.87 2.89 2.88
query34 17.03 4.37 4.36
query35 4.44 4.43 4.41
query36 0.65 0.46 0.48
query37 0.19 0.15 0.16
query38 0.15 0.14 0.16
query39 0.04 0.04 0.03
query40 0.16 0.12 0.13
query41 0.10 0.04 0.06
query42 0.06 0.05 0.05
query43 0.05 0.04 0.04
Total cold run time: 109.68 s
Total hot run time: 30.71 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2244499494
Thank you for your contribution to Apache Doris.
Don't know what should be done next? See [How to process your PR](https://cwiki.apache.org/confluence/display/DORIS/How+to+process+your+PR)
Since 2024-03-18, the Document has been moved to [doris-website](https://github.com/apache/doris-website).
See [Doris Document](https://cwiki.apache.org/confluence/display/DORIS/Doris+Document).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2298409527
<details>
<summary>ClickBench: <b>Total hot run time: 30.87 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 1d63b327147196a6029b3421305f1eed1a00dc18, data reload: false
query1 0.05 0.04 0.04
query2 0.08 0.04 0.04
query3 0.23 0.05 0.06
query4 1.67 0.07 0.08
query5 0.51 0.49 0.50
query6 1.14 0.74 0.73
query7 0.02 0.02 0.02
query8 0.06 0.05 0.06
query9 0.54 0.49 0.49
query10 0.56 0.56 0.55
query11 0.17 0.12 0.12
query12 0.15 0.13 0.13
query13 0.61 0.60 0.60
query14 0.76 0.77 0.80
query15 0.86 0.83 0.83
query16 0.38 0.38 0.38
query17 1.05 1.06 1.05
query18 0.22 0.20 0.21
query19 1.80 1.77 1.84
query20 0.01 0.01 0.01
query21 15.40 0.67 0.66
query22 4.44 7.97 1.51
query23 18.28 1.34 1.30
query24 2.12 0.23 0.23
query25 0.16 0.09 0.09
query26 0.28 0.19 0.19
query27 0.09 0.08 0.08
query28 13.27 1.03 1.02
query29 12.66 3.36 3.30
query30 0.43 0.24 0.24
query31 2.91 0.41 0.40
query32 3.80 0.49 0.50
query33 2.98 2.94 3.00
query34 17.01 4.37 4.41
query35 4.37 4.49 4.44
query36 0.67 0.49 0.51
query37 0.21 0.18 0.17
query38 0.17 0.16 0.18
query39 0.07 0.05 0.06
query40 0.18 0.15 0.16
query41 0.12 0.07 0.07
query42 0.08 0.08 0.07
query43 0.06 0.06 0.06
Total cold run time: 110.63 s
Total hot run time: 30.87 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2302092292
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2301232335
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2306018891
run cloud_p0
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2283201473
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2285289203
<details>
<summary>TPC-H: <b>Total hot run time: 40582 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 1e1cd3f4d183656b41f4319a5380401fc4759cff, data reload: false
------ Round 1 ----------------------------------
q1 17610 4422 4349 4349
q2 2034 189 184 184
q3 11983 1020 1100 1020
q4 10542 761 765 761
q5 7787 2819 2869 2819
q6 227 142 142 142
q7 981 599 594 594
q8 9389 2088 2095 2088
q9 8830 6615 6629 6615
q10 7040 2196 2193 2193
q11 482 252 257 252
q12 401 232 229 229
q13 17763 3021 2992 2992
q14 274 243 240 240
q15 526 470 495 470
q16 635 523 516 516
q17 1013 680 685 680
q18 8213 7387 7555 7387
q19 1388 1029 983 983
q20 794 423 419 419
q21 5456 4655 4665 4655
q22 1156 1011 994 994
Total cold run time: 114524 ms
Total hot run time: 40582 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4404 4342 4356 4342
q2 394 279 283 279
q3 2901 2698 2801 2698
q4 2055 1756 1744 1744
q5 5750 5648 5629 5629
q6 229 140 147 140
q7 2102 1779 1829 1779
q8 3368 3564 3471 3471
q9 8883 8882 8921 8882
q10 3583 3341 3284 3284
q11 595 512 531 512
q12 814 655 643 643
q13 15902 3237 3198 3198
q14 321 285 301 285
q15 582 509 491 491
q16 643 582 586 582
q17 1867 1572 1534 1534
q18 8180 8019 7829 7829
q19 6785 1586 1595 1586
q20 2285 1980 1944 1944
q21 5681 5524 5067 5067
q22 1175 1101 1083 1083
Total cold run time: 78499 ms
Total hot run time: 57002 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2291220320
<details>
<summary>TPC-H: <b>Total hot run time: 38245 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 758fe123926a613e6c373d8d814829c22a99a16a, data reload: false
------ Round 1 ----------------------------------
q1 19093 4869 4309 4309
q2 2073 213 223 213
q3 11670 1107 1083 1083
q4 10502 752 715 715
q5 7814 2882 2860 2860
q6 271 153 154 153
q7 997 644 641 641
q8 9374 2085 2106 2085
q9 7267 6568 6584 6568
q10 7081 2267 2194 2194
q11 485 266 262 262
q12 418 245 243 243
q13 17787 3029 3019 3019
q14 293 257 257 257
q15 557 524 520 520
q16 514 405 411 405
q17 987 708 713 708
q18 7496 6797 7037 6797
q19 5723 1084 1040 1040
q20 745 362 366 362
q21 4252 2770 3118 2770
q22 1138 1068 1041 1041
Total cold run time: 116537 ms
Total hot run time: 38245 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4486 4333 4263 4263
q2 415 306 307 306
q3 2853 2659 2644 2644
q4 1955 1702 1708 1702
q5 5718 5754 5708 5708
q6 244 152 161 152
q7 2225 1794 1759 1759
q8 3335 3555 3494 3494
q9 8870 8874 8770 8770
q10 3580 3412 3350 3350
q11 626 571 532 532
q12 830 663 642 642
q13 16047 3199 3212 3199
q14 337 300 287 287
q15 558 507 503 503
q16 495 456 446 446
q17 1865 1575 1566 1566
q18 8247 7913 7701 7701
q19 7784 1675 1546 1546
q20 2158 1876 1907 1876
q21 12767 5356 5371 5356
q22 1216 1080 1093 1080
Total cold run time: 86611 ms
Total hot run time: 56882 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "gavinchou (via GitHub)" <gi...@apache.org>.
gavinchou commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1730627524
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
msg = ss.str();
return;
}
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
- std::string_view ver_key = i.first;
- ver_key.remove_prefix(1); // Remove key space
- // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- int ret = decode_key(&ver_key, &out);
- if (ret != 0) [[unlikely]] {
- // decode version key error means this is something wrong,
- // we can not continue this txn
- LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = "decode version key error";
- return;
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
}
- int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
- int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
- VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+ // save versions for partition
+ int64_t version_update_time_ms =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ response->set_version_update_time_ms(version_update_time_ms);
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_txn_id(txn_id);
+ version_pb.set_update_time_ms(version_update_time_ms);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- response->add_table_ids(table_id);
- response->add_partition_ids(partition_id);
- response->add_versions(i.second);
- }
+ txn->put(i.first, ver_val);
+ LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
+ << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+
+ std::string_view ver_key = i.first;
+ ver_key.remove_prefix(1); // Remove key space
+ // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
+ int ret = decode_key(&ver_key, &out);
+ if (ret != 0) [[unlikely]] {
+ // decode version key error means this is something wrong,
+ // we can not continue this txn
+ LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = "decode version key error";
+ return;
+ }
- // Save table versions
- for (auto& i : table_id_tablet_ids) {
- std::string ver_key = table_version_key({instance_id, db_id, i.first});
- txn->atomic_add(ver_key, 1);
- LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key) << " txn_id=" << txn_id;
- }
+ int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
+ int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
+ VLOG_DEBUG << "txn_id=" << txn_id << " table_id=" << table_id
+ << " partition_id=" << partition_id << " version=" << i.second;
- LOG(INFO) << " before update txn_info=" << txn_info.ShortDebugString();
+ response->add_table_ids(table_id);
+ response->add_partition_ids(partition_id);
+ response->add_versions(i.second);
+ }
- // Update txn_info
- txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ // process mow table, check lock and remove pending key
+ std::vector<std::string> lock_keys;
+ lock_keys.reserve(request->mow_table_ids().size());
+ for (auto table_id : request->mow_table_ids()) {
+ lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
+ }
+ std::vector<std::optional<std::string>> lock_values;
+ err = txn->batch_get(&lock_values, lock_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
+ << " err=" << err;
+ msg = ss.str();
+ code = cast_as<ErrCategory::READ>(err);
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- auto now_time = system_clock::now();
- uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
- if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
- LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
- << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
- return;
- }
- txn_info.set_commit_time(commit_time);
- txn_info.set_finish_time(commit_time);
- if (request->has_commit_attachment()) {
- txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
- }
- LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
- info_val.clear();
- if (!txn_info.SerializeToString(&info_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(info_key, info_val);
- LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+ for (size_t i = 0; i < lock_keys.size(); i++) {
+ int64_t table_id = request->mow_table_ids(i);
+ // When the key does not exist, it means the lock has been acquired
+ // by another transaction and successfully committed.
+ if (!lock_values[i].has_value()) {
+ ss << "get delete bitmap update lock info, lock is expired"
+ << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
+ code = MetaServiceCode::LOCK_EXPIRED;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- // Update stats of affected tablet
- for (auto& [tablet_id, stats] : tablet_stats) {
- DCHECK(tablet_ids.count(tablet_id));
- auto& tablet_idx = tablet_ids[tablet_id];
- StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
- tablet_idx.partition_id(), tablet_id};
- update_tablet_stats(info, stats, txn, code, msg);
- if (code != MetaServiceCode::OK) return;
- }
- // Remove tmp rowset meta
- for (auto& [k, _] : tmp_rowsets_meta) {
- txn->remove(k);
- LOG(INFO) << "xxx remove tmp_rowset_key=" << hex(k) << " txn_id=" << txn_id;
- }
+ DeleteBitmapUpdateLockPB lock_info;
+ if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "failed to parse DeleteBitmapUpdateLockPB";
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ if (lock_info.lock_id() != request->txn_id()) {
+ msg = "lock is expired";
+ code = MetaServiceCode::LOCK_EXPIRED;
+ return;
+ }
+ txn->remove(lock_keys[i]);
+ LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
+ << " txn_id=" << txn_id;
- const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
- LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
- txn->remove(running_key);
+ for (auto tablet_id : table_id_tablet_ids[table_id]) {
+ std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
+ txn->remove(pending_key);
+ LOG(INFO) << "xxx remove delete bitmap pending key, pending_key="
+ << hex(pending_key) << " txn_id=" << txn_id;
+ }
+ }
+ lock_keys.clear();
+ lock_values.clear();
- std::string recycle_val;
- std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
- RecycleTxnPB recycle_pb;
- recycle_pb.set_creation_time(commit_time);
- recycle_pb.set_label(txn_info.label());
+ // Save table versions
+ for (auto& i : table_id_tablet_ids) {
+ std::string ver_key = table_version_key({instance_id, db_id, i.first});
+ txn->atomic_add(ver_key, 1);
+ LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key)
+ << " txn_id=" << txn_id;
+ }
- if (!recycle_pb.SerializeToString(&recycle_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(recycle_key, recycle_val);
+ LOG(INFO) << "commit_txn_eventually put_size=" << txn->put_bytes()
+ << " del_size=" << txn->delete_bytes() << " num_put_keys=" << txn->num_put_keys()
+ << " num_del_keys=" << txn->num_del_keys()
+ << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
- if (txn_info.load_job_source_type() ==
- LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
- put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
- }
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
- LOG(INFO) << "xxx commit_txn put recycle_key key=" << hex(recycle_key) << " txn_id=" << txn_id;
- LOG(INFO) << "commit_txn put_size=" << txn->put_bytes() << " del_size=" << txn->delete_bytes()
- << " num_put_keys=" << txn->num_put_keys() << " num_del_keys=" << txn->num_del_keys()
- << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
+ std::shared_ptr<TxnLazyCommitTask> task = txn_lazy_committer->submit(instance_id, txn_id);
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ if (ret.first != MetaServiceCode::OK) {
+ LOG(WARNING) << "lazy commit txn failed txn_id=" << txn_id << " code=" << ret.first
+ << "msg=" << ret.second;
+ }
- // Finally we are done...
- err = txn->commit();
- if (err != TxnErrorCode::TXN_OK) {
- if ((err == TxnErrorCode::TXN_VALUE_TOO_LARGE ||
- err == TxnErrorCode::TXN_BYTES_TOO_LARGE) &&
- !tmp_rowsets_meta.empty()) {
- size_t max_size = 0, max_idx = 0, max_num_segments = 0,
- min_num_segments = std::numeric_limits<size_t>::max(), avg_num_segments = 0;
- for (size_t i = 0; i < tmp_rowsets_meta.size(); i++) {
- auto& [k, v] = tmp_rowsets_meta[i];
- if (v.ByteSizeLong() > max_size) {
- max_size = v.ByteSizeLong();
- max_idx = i;
- }
- if (v.num_segments() > max_num_segments) {
- max_num_segments = v.num_segments();
- }
- if (v.num_segments() < min_num_segments) {
- min_num_segments = v.num_segments();
- }
- avg_num_segments += v.num_segments();
- }
- if (!tmp_rowsets_meta.empty()) {
- avg_num_segments /= tmp_rowsets_meta.size();
- }
- LOG(WARNING) << "failed to commit kv txn"
- << ", err=" << err << ", txn_id=" << txn_id
- << ", total_rowsets=" << tmp_rowsets_meta.size()
- << ", avg_num_segments=" << avg_num_segments
- << ", min_num_segments=" << min_num_segments
- << ", max_num_segments=" << max_num_segments
- << ", largest_rowset_size=" << max_size
- << ", largest_rowset_key=" << hex(tmp_rowsets_meta[max_idx].first)
- << ", largest_rowset_value="
- << tmp_rowsets_meta[max_idx].second.ShortDebugString();
+ std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ // Accumulate affected rows
+ auto& stats = tablet_stats[i.tablet_id()];
+ stats.data_size += i.data_disk_size();
+ stats.num_rows += i.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += i.num_segments();
}
- code = cast_as<ErrCategory::COMMIT>(err);
- ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- return;
- }
- // calculate table stats from tablets stats
- std::map<int64_t /*table_id*/, TableStats> table_stats;
- std::vector<int64_t> base_tablet_ids(request->base_tablet_ids().begin(),
- request->base_tablet_ids().end());
- calc_table_stats(tablet_ids, tablet_stats, table_stats, base_tablet_ids);
- for (const auto& pair : table_stats) {
- TableStatsPB* stats_pb = response->add_table_stats();
- auto table_id = pair.first;
- auto stats = pair.second;
- get_pb_from_tablestats(stats, stats_pb);
- stats_pb->set_table_id(table_id);
- VLOG_DEBUG << "Add TableStats to CommitTxnResponse. txn_id=" << txn_id
- << " table_id=" << table_id
- << " updated_row_count=" << stats_pb->updated_row_count();
- }
+ // calculate table stats from tablets stats
+ std::map<int64_t /*table_id*/, TableStats> table_stats;
+ std::vector<int64_t> base_tablet_ids(request->base_tablet_ids().begin(),
+ request->base_tablet_ids().end());
+ calc_table_stats(tablet_ids, tablet_stats, table_stats, base_tablet_ids);
+ for (const auto& pair : table_stats) {
+ TableStatsPB* stats_pb = response->add_table_stats();
+ auto table_id = pair.first;
+ auto stats = pair.second;
+ get_pb_from_tablestats(stats, stats_pb);
+ stats_pb->set_table_id(table_id);
+ VLOG_DEBUG << "Add TableStats to CommitTxnResponse. txn_id=" << txn_id
+ << " table_id=" << table_id
+ << " updated_row_count=" << stats_pb->updated_row_count();
+ }
- response->mutable_txn_info()->CopyFrom(txn_info);
-} // end commit_txn
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
Review Comment:
add comment to describe why it is OK to set VISIBLE
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1730953469
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
Review Comment:
> is it a unrecoverable error?
后续展开处理错误
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2275256551
<details>
<summary>TPC-H: <b>Total hot run time: 39663 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 53d56cfa3a39f18ab858f88c2903d1b32d180eff, data reload: false
------ Round 1 ----------------------------------
q1 17820 4496 4354 4354
q2 2663 182 179 179
q3 12196 1158 1105 1105
q4 10313 778 730 730
q5 7578 2503 2555 2503
q6 226 141 137 137
q7 975 602 589 589
q8 9226 1910 1885 1885
q9 8586 6517 6522 6517
q10 7056 2211 2143 2143
q11 466 245 250 245
q12 393 220 220 220
q13 17779 2943 2986 2943
q14 284 234 229 229
q15 525 496 484 484
q16 652 511 528 511
q17 973 617 706 617
q18 7994 7586 7459 7459
q19 5031 1004 1058 1004
q20 738 407 420 407
q21 5230 4438 4567 4438
q22 1064 964 1004 964
Total cold run time: 117768 ms
Total hot run time: 39663 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4520 4253 4273 4253
q2 382 279 275 275
q3 2797 2644 2588 2588
q4 1886 1635 1655 1635
q5 5297 5262 5284 5262
q6 218 128 133 128
q7 2013 1671 1679 1671
q8 3129 3304 3315 3304
q9 8440 8390 8452 8390
q10 3345 3181 3150 3150
q11 581 487 499 487
q12 766 611 619 611
q13 16414 2960 2971 2960
q14 307 279 273 273
q15 520 471 489 471
q16 600 542 543 542
q17 1758 1506 1449 1449
q18 7780 7463 7483 7463
q19 1640 1486 1540 1486
q20 2080 1896 1850 1850
q21 7512 5179 5039 5039
q22 1098 1029 993 993
Total cold run time: 73083 ms
Total hot run time: 54280 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2285221089
run compile
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2283476073
run cloud_p0
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2291039722
<details>
<summary>TPC-H: <b>Total hot run time: 38603 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 30e688d087e1d5277dbe34e2cdc7bfa4aa723733, data reload: false
------ Round 1 ----------------------------------
q1 18361 4453 4296 4296
q2 2067 233 248 233
q3 11145 1087 1145 1087
q4 10506 789 730 730
q5 7790 2860 2882 2860
q6 263 154 156 154
q7 1005 649 638 638
q8 9395 2136 2110 2110
q9 6925 6559 6617 6559
q10 7088 2260 2269 2260
q11 494 273 275 273
q12 430 265 254 254
q13 17785 3013 3011 3011
q14 309 259 262 259
q15 579 529 557 529
q16 539 420 427 420
q17 992 730 728 728
q18 7571 6884 6723 6723
q19 6280 1112 1151 1112
q20 725 357 375 357
q21 3851 2974 3070 2974
q22 1138 1036 1055 1036
Total cold run time: 115238 ms
Total hot run time: 38603 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4520 4299 4306 4299
q2 411 315 315 315
q3 2898 2691 2663 2663
q4 1974 1781 1715 1715
q5 5704 5667 5737 5667
q6 240 147 150 147
q7 2179 1823 1785 1785
q8 3309 3532 3468 3468
q9 8739 8750 8734 8734
q10 3625 3369 3330 3330
q11 612 510 537 510
q12 854 666 646 646
q13 16299 3160 3138 3138
q14 315 299 296 296
q15 560 517 515 515
q16 504 457 452 452
q17 1882 1551 1519 1519
q18 8178 7883 7825 7825
q19 10017 1635 1620 1620
q20 3449 1893 1889 1889
q21 14010 5344 5372 5344
q22 1185 1081 1062 1062
Total cold run time: 91464 ms
Total hot run time: 56939 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2244499674
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1687601725
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -387,11 +412,27 @@ void MetaServiceImpl::batch_get_version(::google::protobuf::RpcController* contr
msg = "malformed version value";
break;
}
+ if (version_pb.has_txn_id()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task = txn_lazy_committer_->submit(
+ instance_id, version_pb.txn_id());
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ code = ret.first;
+ msg = ret.second;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "wait txn lazy commit failed, txn_id="
+ << version_pb.txn_id();
+ break;
+ }
+ goto TRY_AGAIN;
+ }
response->add_versions(version_pb.version());
response->add_version_update_time_ms(version_pb.update_time_ms());
}
}
+ if (code != MetaServiceCode::OK) break;
Review Comment:
warning: statement should be inside braces [readability-braces-around-statements]
```suggestion
if (code != MetaServiceCode::OK) { break;
}
```
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -387,11 +412,27 @@
msg = "malformed version value";
break;
}
+ if (version_pb.has_txn_id()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task = txn_lazy_committer_->submit(
+ instance_id, version_pb.txn_id());
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ code = ret.first;
+ msg = ret.second;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "wait txn lazy commit failed, txn_id="
+ << version_pb.txn_id();
+ break;
+ }
+ goto TRY_AGAIN;
+ }
response->add_versions(version_pb.version());
response->add_version_update_time_ms(version_pb.update_time_ms());
}
}
+ if (code != MetaServiceCode::OK) break;
}
+ if (code != MetaServiceCode::OK) break;
Review Comment:
warning: statement should be inside braces [readability-braces-around-statements]
```suggestion
if (code != MetaServiceCode::OK) { break;
}
```
##########
cloud/src/meta-service/txn_lazy_committer.h:
##########
@@ -0,0 +1,65 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <atomic>
+
+#include "common/config.h"
Review Comment:
warning: 'common/config.h' file not found [clang-diagnostic-error]
```cpp
#include "common/config.h"
^
```
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,208 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "meta-service/txn_lazy_committer.h"
Review Comment:
warning: 'meta-service/txn_lazy_committer.h' file not found [clang-diagnostic-error]
```cpp
#include "meta-service/txn_lazy_committer.h"
^
```
##########
cloud/src/recycler/recycler_service.h:
##########
@@ -20,6 +20,7 @@
#include <gen_cpp/cloud.pb.h>
Review Comment:
warning: 'gen_cpp/cloud.pb.h' file not found [clang-diagnostic-error]
```cpp
#include <gen_cpp/cloud.pb.h>
^
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2259875139
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2249765436
<details>
<summary>TPC-DS: <b>Total hot run time: 173437 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit bf6aad6e7d1b3229f6fdc1b41de15dc9b7d01bfc, data reload: false
query1 906 365 362 362
query2 6420 2050 1947 1947
query3 6633 206 227 206
query4 26326 17597 17202 17202
query5 3582 485 478 478
query6 286 176 179 176
query7 4585 297 286 286
query8 250 193 191 191
query9 8529 2417 2385 2385
query10 438 291 276 276
query11 12568 10058 9939 9939
query12 120 91 84 84
query13 1654 372 370 370
query14 10167 7406 7671 7406
query15 208 161 164 161
query16 7673 462 443 443
query17 1378 532 543 532
query18 1933 281 273 273
query19 199 146 162 146
query20 94 87 79 79
query21 209 128 123 123
query22 4407 4008 4078 4008
query23 34386 33495 33531 33495
query24 11288 3014 2979 2979
query25 593 384 448 384
query26 774 157 158 157
query27 2210 285 274 274
query28 6128 2087 2073 2073
query29 917 632 638 632
query30 260 160 150 150
query31 979 783 777 777
query32 100 56 54 54
query33 767 331 347 331
query34 933 488 487 487
query35 867 749 754 749
query36 1135 1006 957 957
query37 140 81 82 81
query38 2968 2903 2809 2809
query39 901 874 829 829
query40 202 123 116 116
query41 48 45 46 45
query42 118 98 93 93
query43 527 470 483 470
query44 1191 727 758 727
query45 210 172 172 172
query46 1083 732 728 728
query47 1857 1785 1768 1768
query48 365 292 287 287
query49 819 403 412 403
query50 783 387 390 387
query51 6813 6626 6693 6626
query52 102 89 91 89
query53 356 290 292 290
query54 901 446 447 446
query55 76 77 74 74
query56 278 292 263 263
query57 1137 1060 1042 1042
query58 248 245 254 245
query59 2920 2654 2730 2654
query60 302 279 272 272
query61 99 105 96 96
query62 824 655 634 634
query63 319 283 286 283
query64 9137 2206 1623 1623
query65 3170 3121 3096 3096
query66 741 333 337 333
query67 15501 15031 15108 15031
query68 5317 561 540 540
query69 654 433 366 366
query70 1112 1158 1087 1087
query71 455 283 274 274
query72 7331 5968 5302 5302
query73 769 322 330 322
query74 6182 5706 5665 5665
query75 3682 2697 2689 2689
query76 3156 963 875 875
query77 640 319 292 292
query78 10358 9141 9095 9095
query79 1633 539 529 529
query80 2441 563 486 486
query81 595 227 227 227
query82 427 137 144 137
query83 305 169 165 165
query84 265 86 95 86
query85 1061 309 300 300
query86 438 338 313 313
query87 3269 3099 3147 3099
query88 3368 2386 2364 2364
query89 471 391 412 391
query90 1637 197 200 197
query91 137 100 102 100
query92 65 51 50 50
query93 1951 535 525 525
query94 796 305 298 298
query95 415 332 323 323
query96 596 274 279 274
query97 3187 3042 3030 3030
query98 228 196 195 195
query99 1568 1281 1257 1257
Total cold run time: 278547 ms
Total hot run time: 173437 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1698220600
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,208 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
Review Comment:
warning: function 'commit' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void TxnLazyCommitTask::commit() {
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:51:** 117 lines including whitespace and comments (threshold 80)
```cpp
void TxnLazyCommitTask::commit() {
^
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2260238093
<details>
<summary>ClickBench: <b>Total hot run time: 30.67 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit ae48134efcfe7887d2b0b6f2d645e9c4fac57e59, data reload: false
query1 0.04 0.04 0.04
query2 0.07 0.04 0.04
query3 0.22 0.05 0.05
query4 1.69 0.06 0.06
query5 0.49 0.48 0.49
query6 1.14 0.72 0.71
query7 0.02 0.01 0.01
query8 0.06 0.04 0.04
query9 0.60 0.52 0.54
query10 0.58 0.59 0.60
query11 0.17 0.12 0.12
query12 0.15 0.13 0.12
query13 0.62 0.60 0.59
query14 0.78 0.79 0.80
query15 0.90 0.85 0.84
query16 0.36 0.35 0.36
query17 1.00 0.99 1.00
query18 0.22 0.22 0.21
query19 1.79 1.72 1.80
query20 0.01 0.03 0.01
query21 15.40 0.78 0.66
query22 4.32 7.24 2.00
query23 18.03 1.34 1.30
query24 2.26 0.22 0.22
query25 0.19 0.09 0.08
query26 0.31 0.22 0.22
query27 0.46 0.24 0.23
query28 13.16 0.97 0.97
query29 12.59 3.29 3.26
query30 0.26 0.06 0.06
query31 2.86 0.41 0.40
query32 3.28 0.48 0.48
query33 2.96 2.94 2.98
query34 15.50 4.26 4.26
query35 4.27 4.26 4.27
query36 0.68 0.48 0.48
query37 0.19 0.17 0.16
query38 0.16 0.15 0.15
query39 0.05 0.03 0.03
query40 0.15 0.12 0.12
query41 0.09 0.04 0.05
query42 0.06 0.05 0.04
query43 0.04 0.03 0.04
Total cold run time: 108.18 s
Total hot run time: 30.67 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2261893023
<details>
<summary>TPC-H: <b>Total hot run time: 41784 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit c0a6c5ac10a4aa5587bfabcd3b74e29aa97bef62, data reload: false
------ Round 1 ----------------------------------
q1 17655 4190 4122 4122
q2 2036 198 208 198
q3 10547 1315 1378 1315
q4 10181 808 948 808
q5 7606 3002 2989 2989
q6 226 143 143 143
q7 1037 618 607 607
q8 9442 1922 1952 1922
q9 8504 6621 6656 6621
q10 8738 3838 3856 3838
q11 436 255 251 251
q12 415 233 234 233
q13 17776 2911 2951 2911
q14 272 243 246 243
q15 524 490 497 490
q16 522 401 380 380
q17 972 951 939 939
q18 8104 7395 7248 7248
q19 1778 1196 1228 1196
q20 566 333 334 333
q21 5335 4823 4721 4721
q22 351 282 276 276
Total cold run time: 113023 ms
Total hot run time: 41784 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4082 4003 4027 4003
q2 334 240 219 219
q3 3020 3023 3165 3023
q4 2008 2028 1932 1932
q5 5676 5463 5412 5412
q6 220 130 133 130
q7 2137 1804 1810 1804
q8 3331 3416 3365 3365
q9 8664 8739 8862 8739
q10 3971 4068 3952 3952
q11 563 465 472 465
q12 763 612 629 612
q13 16323 3106 3149 3106
q14 308 268 291 268
q15 531 501 486 486
q16 467 419 402 402
q17 1796 1732 1726 1726
q18 8344 7833 8055 7833
q19 3398 1773 1760 1760
q20 2055 1824 1827 1824
q21 5740 5553 5205 5205
q22 547 494 463 463
Total cold run time: 74278 ms
Total hot run time: 56729 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2297924866
<details>
<summary>TPC-H: <b>Total hot run time: 38216 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 43feec09f2a80e3fe7f3b07ebc1b5b49bdf0e0bf, data reload: false
------ Round 1 ----------------------------------
q1 19389 5455 4311 4311
q2 2085 210 207 207
q3 11730 980 1146 980
q4 10491 803 772 772
q5 7763 2878 2790 2790
q6 262 157 154 154
q7 1037 657 653 653
q8 9396 2101 2107 2101
q9 7347 6562 6604 6562
q10 7044 2140 2196 2140
q11 454 260 268 260
q12 429 243 250 243
q13 18818 3027 3000 3000
q14 304 254 251 251
q15 553 508 540 508
q16 514 415 402 402
q17 987 653 691 653
q18 7593 7015 7000 7000
q19 6247 1145 1100 1100
q20 689 349 355 349
q21 3888 3081 2760 2760
q22 1133 1073 1020 1020
Total cold run time: 118153 ms
Total hot run time: 38216 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4555 4333 4289 4289
q2 403 309 291 291
q3 2835 2739 2727 2727
q4 2023 1723 1758 1723
q5 5661 5780 5681 5681
q6 245 153 153 153
q7 2211 1767 1771 1767
q8 3348 3451 3454 3451
q9 8852 8739 8773 8739
q10 3652 3372 3334 3334
q11 640 529 523 523
q12 830 700 649 649
q13 17211 3213 3074 3074
q14 320 294 288 288
q15 554 510 527 510
q16 510 449 461 449
q17 1845 1562 1530 1530
q18 8274 8057 7697 7697
q19 3869 1488 1663 1488
q20 2288 1907 1876 1876
q21 14662 5351 5314 5314
q22 1206 1120 1092 1092
Total cold run time: 85994 ms
Total hot run time: 56645 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2297864583
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1714974008
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,455 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
Review Comment:
warning: function 'convert_tmp_rowsets' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void convert_tmp_rowsets(
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:36:** 152 lines including whitespace and comments (threshold 80)
```cpp
void convert_tmp_rowsets(
^
```
</details>
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,455 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
Review Comment:
warning: function 'commit' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void TxnLazyCommitTask::commit() {
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:208:** 122 lines including whitespace and comments (threshold 80)
```cpp
void TxnLazyCommitTask::commit() {
^
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "w41ter (via GitHub)" <gi...@apache.org>.
w41ter commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1716269904
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -969,320 +1356,345 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
- msg = ss.str();
- return;
- }
- version = version_pb.version();
- } else {
- version = 1;
- }
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
-
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
+ }
+
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ if (request->has_is_2pc() && request->is_2pc()) {
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
-
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
-
- std::string_view ver_key = i.first;
- ver_key.remove_prefix(1); // Remove key space
- // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- int ret = decode_key(&ver_key, &out);
- if (ret != 0) [[unlikely]] {
- // decode version key error means this is something wrong,
- // we can not continue this txn
- LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
code = MetaServiceCode::UNDEFINED_ERR;
- msg = "decode version key error";
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
return;
}
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
- int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
- VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- response->add_table_ids(table_id);
- response->add_partition_ids(partition_id);
- response->add_versions(i.second);
- }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
- // Save table versions
- for (auto& i : table_id_tablet_ids) {
- std::string ver_key = table_version_key({instance_id, db_id, i.first});
- txn->atomic_add(ver_key, 1);
- LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key) << " txn_id=" << txn_id;
- }
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
+ }
- LOG(INFO) << " before update txn_info=" << txn_info.ShortDebugString();
+ // save versions for partition
+ response->clear_table_ids();
+ response->clear_partition_ids();
+ response->clear_versions();
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_txn_id(txn_id);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- // Update txn_info
- txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ txn->put(i.first, ver_val);
+ LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
+ << " txn_id=" << txn_id;
- auto now_time = system_clock::now();
- uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
- if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
- LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
- << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
- return;
- }
- txn_info.set_commit_time(commit_time);
- txn_info.set_finish_time(commit_time);
- if (request->has_commit_attachment()) {
- txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
- }
- LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
- info_val.clear();
- if (!txn_info.SerializeToString(&info_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(info_key, info_val);
- LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+ std::string_view ver_key = i.first;
+ ver_key.remove_prefix(1); // Remove key space
+ // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
+ int ret = decode_key(&ver_key, &out);
+ if (ret != 0) [[unlikely]] {
+ // decode version key error means this is something wrong,
+ // we can not continue this txn
+ LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = "decode version key error";
+ return;
+ }
- // Update stats of affected tablet
- for (auto& [tablet_id, stats] : tablet_stats) {
- DCHECK(tablet_ids.count(tablet_id));
- auto& tablet_idx = tablet_ids[tablet_id];
- StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
- tablet_idx.partition_id(), tablet_id};
- update_tablet_stats(info, stats, txn, code, msg);
- if (code != MetaServiceCode::OK) return;
- }
- // Remove tmp rowset meta
- for (auto& [k, _] : tmp_rowsets_meta) {
- txn->remove(k);
- LOG(INFO) << "xxx remove tmp_rowset_key=" << hex(k) << " txn_id=" << txn_id;
- }
+ int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
+ int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
+ VLOG_DEBUG << "txn_id=" << txn_id << " table_id=" << table_id
+ << " partition_id=" << partition_id << " version=" << i.second;
- const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
- LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
- txn->remove(running_key);
+ response->add_table_ids(table_id);
+ response->add_partition_ids(partition_id);
+ response->add_versions(i.second);
+ }
- std::string recycle_val;
- std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
- RecycleTxnPB recycle_pb;
- recycle_pb.set_creation_time(commit_time);
- recycle_pb.set_label(txn_info.label());
+ // process mow table, check lock and remove pending key
+ std::vector<std::string> lock_keys;
+ lock_keys.reserve(request->mow_table_ids().size());
+ for (auto table_id : request->mow_table_ids()) {
+ lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
+ }
+ std::vector<std::optional<std::string>> lock_values;
+ err = txn->batch_get(&lock_values, lock_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
+ << " err=" << err;
+ msg = ss.str();
+ code = cast_as<ErrCategory::READ>(err);
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- if (!recycle_pb.SerializeToString(&recycle_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(recycle_key, recycle_val);
+ for (size_t i = 0; i < lock_keys.size(); i++) {
+ int64_t table_id = request->mow_table_ids(i);
+ // When the key does not exist, it means the lock has been acquired
+ // by another transaction and successfully committed.
+ if (!lock_values[i].has_value()) {
+ ss << "get delete bitmap update lock info, lock is expired"
+ << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
+ code = MetaServiceCode::LOCK_EXPIRED;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- if (txn_info.load_job_source_type() ==
- LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
- put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
- }
+ DeleteBitmapUpdateLockPB lock_info;
+ if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "failed to parse DeleteBitmapUpdateLockPB";
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ if (lock_info.lock_id() != request->txn_id()) {
+ msg = "lock is expired";
+ code = MetaServiceCode::LOCK_EXPIRED;
+ return;
+ }
+ txn->remove(lock_keys[i]);
+ LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
+ << " txn_id=" << txn_id;
- LOG(INFO) << "xxx commit_txn put recycle_key key=" << hex(recycle_key) << " txn_id=" << txn_id;
- LOG(INFO) << "commit_txn put_size=" << txn->put_bytes() << " del_size=" << txn->delete_bytes()
- << " num_put_keys=" << txn->num_put_keys() << " num_del_keys=" << txn->num_del_keys()
- << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
+ for (auto tablet_id : table_id_tablet_ids[table_id]) {
+ std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
+ txn->remove(pending_key);
+ LOG(INFO) << "xxx remove delete bitmap pending key, pending_key="
+ << hex(pending_key) << " txn_id=" << txn_id;
+ }
+ }
+ lock_keys.clear();
+ lock_values.clear();
- // Finally we are done...
- err = txn->commit();
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::COMMIT>(err);
- ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- return;
- }
+ // Save table versions
+ for (auto& i : table_id_tablet_ids) {
+ std::string ver_key = table_version_key({instance_id, db_id, i.first});
+ txn->atomic_add(ver_key, 1);
+ LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key)
+ << " txn_id=" << txn_id;
+ }
- // calculate table stats from tablets stats
- std::map<int64_t /*table_id*/, TableStats> table_stats;
- std::vector<int64_t> base_tablet_ids(request->base_tablet_ids().begin(),
- request->base_tablet_ids().end());
- calc_table_stats(tablet_ids, tablet_stats, table_stats, base_tablet_ids);
- for (const auto& pair : table_stats) {
- TableStatsPB* stats_pb = response->add_table_stats();
- auto table_id = pair.first;
- auto stats = pair.second;
- get_pb_from_tablestats(stats, stats_pb);
- stats_pb->set_table_id(table_id);
- VLOG_DEBUG << "Add TableStats to CommitTxnResponse. txn_id=" << txn_id
- << " table_id=" << table_id
- << " updated_row_count=" << stats_pb->updated_row_count();
- }
+ LOG(INFO) << "commit_txn_eventually put_size=" << txn->put_bytes()
+ << " del_size=" << txn->delete_bytes() << " num_put_keys=" << txn->num_put_keys()
+ << " num_del_keys=" << txn->num_del_keys()
+ << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
- response->mutable_txn_info()->CopyFrom(txn_info);
-} // end commit_txn
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+
+ std::shared_ptr<TxnLazyCommitTask> task = txn_lazy_committer->submit(instance_id, txn_id);
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
Review Comment:
Some fields of the `CommitTxnResponse` are missing.
- `version_update_time_ms`
- `table_stats`
- `txn_info`
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1706546958
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -788,6 +788,164 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
txn->put(key, val);
}
}
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
Review Comment:
> Add a debug log.
done
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2284135402
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2300412342
<details>
<summary>TPC-H: <b>Total hot run time: 38493 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 1d63b327147196a6029b3421305f1eed1a00dc18, data reload: false
------ Round 1 ----------------------------------
q1 18478 5211 4311 4311
q2 2066 218 225 218
q3 11699 974 1110 974
q4 10518 713 734 713
q5 7805 2868 2864 2864
q6 263 159 160 159
q7 1066 661 665 661
q8 9624 2135 2114 2114
q9 8478 6578 6579 6578
q10 7054 2265 2227 2227
q11 494 273 276 273
q12 435 279 260 260
q13 17783 2992 3034 2992
q14 291 268 273 268
q15 574 534 534 534
q16 537 420 417 417
q17 1004 808 746 746
q18 7650 6871 6793 6793
q19 6505 1055 1130 1055
q20 727 366 365 365
q21 4332 3019 2914 2914
q22 1157 1057 1087 1057
Total cold run time: 118540 ms
Total hot run time: 38493 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4617 4320 4307 4307
q2 414 324 309 309
q3 2866 2711 2741 2711
q4 2030 1817 1734 1734
q5 5611 5795 5605 5605
q6 241 159 149 149
q7 2168 1768 1777 1768
q8 3409 3489 3456 3456
q9 8853 8769 8863 8769
q10 3583 3326 3250 3250
q11 617 520 526 520
q12 876 688 667 667
q13 17378 3186 3111 3111
q14 332 327 305 305
q15 581 521 523 521
q16 534 464 494 464
q17 1865 1561 1544 1544
q18 8473 8044 7688 7688
q19 10079 1681 1604 1604
q20 2192 1915 1882 1882
q21 13459 5357 5385 5357
q22 1137 1114 1060 1060
Total cold run time: 91315 ms
Total hot run time: 56781 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2297939772
<details>
<summary>ClickBench: <b>Total hot run time: 30.75 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 43feec09f2a80e3fe7f3b07ebc1b5b49bdf0e0bf, data reload: false
query1 0.05 0.05 0.04
query2 0.07 0.05 0.05
query3 0.23 0.06 0.05
query4 1.67 0.07 0.07
query5 0.48 0.48 0.48
query6 1.13 0.73 0.73
query7 0.03 0.02 0.02
query8 0.05 0.05 0.06
query9 0.55 0.50 0.49
query10 0.56 0.55 0.57
query11 0.16 0.12 0.12
query12 0.16 0.13 0.12
query13 0.62 0.62 0.60
query14 0.78 0.79 0.79
query15 0.85 0.84 0.84
query16 0.35 0.39 0.36
query17 1.06 0.99 0.98
query18 0.22 0.21 0.21
query19 1.86 1.75 1.75
query20 0.02 0.01 0.01
query21 15.40 0.67 0.68
query22 4.19 8.02 1.56
query23 18.33 1.38 1.27
query24 2.06 0.22 0.24
query25 0.16 0.08 0.09
query26 0.27 0.19 0.18
query27 0.08 0.08 0.09
query28 13.22 1.03 1.00
query29 12.64 3.31 3.32
query30 0.43 0.24 0.23
query31 2.80 0.40 0.40
query32 3.25 0.48 0.49
query33 3.00 2.99 2.93
query34 16.82 4.40 4.40
query35 4.47 4.45 4.50
query36 0.67 0.48 0.48
query37 0.20 0.17 0.17
query38 0.18 0.16 0.17
query39 0.06 0.05 0.05
query40 0.17 0.14 0.15
query41 0.11 0.07 0.06
query42 0.07 0.06 0.07
query43 0.07 0.06 0.06
Total cold run time: 109.55 s
Total hot run time: 30.75 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2312021091
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2312692856
<details>
<summary>TPC-DS: <b>Total hot run time: 191755 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 5f3b5ea8bfb6214887e8d1bb42d8f87233ccc8a0, data reload: false
query1 1263 887 874 874
query2 6324 1975 1987 1975
query3 10599 3842 3974 3842
query4 59298 25088 23183 23183
query5 5434 500 509 500
query6 406 165 169 165
query7 5855 297 306 297
query8 298 212 201 201
query9 8981 2496 2446 2446
query10 486 294 269 269
query11 18335 15007 15251 15007
query12 156 101 103 101
query13 1573 418 383 383
query14 11066 6494 7551 6494
query15 256 178 183 178
query16 7517 465 483 465
query17 1132 560 555 555
query18 1897 294 303 294
query19 301 150 148 148
query20 122 109 121 109
query21 207 106 102 102
query22 4667 4361 4299 4299
query23 34328 33420 33373 33373
query24 5948 2881 2845 2845
query25 552 416 416 416
query26 688 165 167 165
query27 1785 285 282 282
query28 3702 2077 2063 2063
query29 712 425 434 425
query30 240 154 151 151
query31 917 754 763 754
query32 81 56 59 56
query33 464 292 293 292
query34 867 491 506 491
query35 846 712 720 712
query36 1083 899 969 899
query37 138 90 86 86
query38 4039 3882 3897 3882
query39 1444 1388 1413 1388
query40 190 113 116 113
query41 49 44 44 44
query42 113 96 93 93
query43 493 468 464 464
query44 1111 760 745 745
query45 200 167 166 166
query46 1108 739 747 739
query47 1861 1803 1792 1792
query48 385 303 304 303
query49 758 421 430 421
query50 828 416 433 416
query51 7102 7167 7076 7076
query52 100 86 87 86
query53 253 183 182 182
query54 588 452 461 452
query55 74 75 76 75
query56 284 262 264 262
query57 1179 1057 1096 1057
query58 227 258 230 230
query59 3140 2744 2738 2738
query60 316 278 296 278
query61 100 97 104 97
query62 754 662 672 662
query63 217 182 181 181
query64 2843 680 652 652
query65 3216 3169 3177 3169
query66 694 333 332 332
query67 15797 15109 15203 15109
query68 2989 576 575 575
query69 389 328 284 284
query70 1138 1107 1016 1016
query71 345 281 272 272
query72 6131 4019 4000 4000
query73 763 336 339 336
query74 9139 8796 8898 8796
query75 3357 2714 2727 2714
query76 1500 998 953 953
query77 527 325 317 317
query78 11320 9262 9015 9015
query79 1048 546 536 536
query80 704 518 521 518
query81 458 229 230 229
query82 226 136 133 133
query83 170 149 148 148
query84 264 78 82 78
query85 681 345 277 277
query86 304 297 307 297
query87 4380 4256 4231 4231
query88 3239 2403 2392 2392
query89 384 288 282 282
query90 1905 194 203 194
query91 122 97 102 97
query92 60 52 55 52
query93 1048 537 546 537
query94 593 301 309 301
query95 352 274 268 268
query96 598 276 272 272
query97 3158 3049 3071 3049
query98 219 206 200 200
query99 1514 1306 1285 1285
Total cold run time: 307012 ms
Total hot run time: 191755 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2302291594
<details>
<summary>TPC-H: <b>Total hot run time: 38859 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 3ecb308aa0ea6ae75918b441fcce5ed28f71c479, data reload: false
------ Round 1 ----------------------------------
q1 18559 4793 4337 4337
q2 2056 220 236 220
q3 11688 1016 1208 1016
q4 10488 754 742 742
q5 7787 2933 2863 2863
q6 273 159 162 159
q7 1039 700 660 660
q8 9394 2166 2162 2162
q9 7098 6564 6607 6564
q10 7079 2276 2265 2265
q11 501 283 286 283
q12 448 273 262 262
q13 18851 3030 3053 3030
q14 316 265 263 263
q15 578 534 524 524
q16 554 445 421 421
q17 1022 649 793 649
q18 7510 6855 6971 6855
q19 1465 1203 1127 1127
q20 755 367 365 365
q21 4127 3016 3155 3016
q22 1176 1091 1076 1076
Total cold run time: 112764 ms
Total hot run time: 38859 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4390 4359 4330 4330
q2 412 333 320 320
q3 2947 2745 2696 2696
q4 1970 1704 1806 1704
q5 5688 5708 5748 5708
q6 234 149 155 149
q7 2292 1894 1859 1859
q8 3280 3468 3536 3468
q9 8841 8869 8799 8799
q10 3612 3434 3419 3419
q11 633 521 555 521
q12 895 662 707 662
q13 15934 3278 3240 3240
q14 334 317 307 307
q15 561 525 513 513
q16 506 439 440 439
q17 1839 1560 1559 1559
q18 8364 7810 7879 7810
q19 1821 1637 1490 1490
q20 2135 1933 1958 1933
q21 5739 5666 5514 5514
q22 1186 1156 1114 1114
Total cold run time: 73613 ms
Total hot run time: 57554 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2274972042
<details>
<summary>TPC-H: <b>Total hot run time: 40202 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit faf1651134a2bd8b1faa3c32beaf000445742a69, data reload: false
------ Round 1 ----------------------------------
q1 19152 4713 4380 4380
q2 2024 184 181 181
q3 10534 1151 1117 1117
q4 10171 756 709 709
q5 7517 2592 2568 2568
q6 232 140 141 140
q7 984 628 593 593
q8 9231 1956 1956 1956
q9 8830 6601 6593 6593
q10 7071 2174 2203 2174
q11 467 246 255 246
q12 413 233 228 228
q13 18924 3000 3010 3000
q14 288 248 240 240
q15 531 484 502 484
q16 640 520 527 520
q17 1009 715 707 707
q18 8142 7629 7438 7438
q19 3670 1052 1094 1052
q20 757 433 435 433
q21 5629 4451 4623 4451
q22 1102 1005 992 992
Total cold run time: 117318 ms
Total hot run time: 40202 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4436 4285 4252 4252
q2 377 278 269 269
q3 2882 2585 2673 2585
q4 1915 1590 1593 1590
q5 5289 5269 5307 5269
q6 233 132 136 132
q7 2113 1676 1692 1676
q8 3206 3396 3361 3361
q9 8493 8488 8442 8442
q10 3435 3189 3104 3104
q11 589 498 498 498
q12 777 612 591 591
q13 16656 2987 2975 2975
q14 304 287 264 264
q15 523 476 476 476
q16 609 555 544 544
q17 1796 1515 1484 1484
q18 7721 7954 7529 7529
q19 1697 1671 1587 1587
q20 2085 1925 1871 1871
q21 8551 5133 5080 5080
q22 1089 1039 1079 1039
Total cold run time: 74776 ms
Total hot run time: 54618 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2275027140
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1730850089
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
Review Comment:
> and it should be a snapshot GET, concurrent updating does not matter, otherwise the update procedure may no succeed if there are other reads on tablet_idx.
it maybe conflict with recycler, cannot snapshot read
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2317507906
PR approved by at least one committer and no changes requested.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2272741527
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "w41ter (via GitHub)" <gi...@apache.org>.
w41ter commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1706688019
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -387,10 +410,28 @@ void MetaServiceImpl::batch_get_version(::google::protobuf::RpcController* contr
msg = "malformed version value";
break;
}
+ if (version_pb.has_txn_id()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer_->submit(instance_id, version_pb.txn_id());
+ std::tie(code, msg) = task->wait();
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "wait txn lazy commit failed, txn_id="
+ << version_pb.txn_id();
+ break;
+ }
+ goto TRY_AGAIN;
Review Comment:
We don't need to retry again, just like the `get_version`, returning the version directly is enough.
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -237,46 +238,63 @@ void MetaServiceImpl::get_version(::google::protobuf::RpcController* controller,
partition_version_key({instance_id, db_id, table_id, partition_id}, &ver_key);
}
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv_->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- msg = "failed to create txn";
- code = cast_as<ErrCategory::CREATE>(err);
- return;
- }
+ do {
+ code = MetaServiceCode::OK;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ msg = "failed to create txn";
+ code = cast_as<ErrCategory::CREATE>(err);
+ return;
+ }
- std::string ver_val;
- // 0 for success get a key, 1 for key not found, negative for error
- err = txn->get(ver_key, &ver_val);
- VLOG_DEBUG << "xxx get version_key=" << hex(ver_key);
- if (err == TxnErrorCode::TXN_OK) {
- if (is_table_version) {
- int64_t version = 0;
- if (!txn->decode_atomic_int(ver_val, &version)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "malformed table version value";
- return;
- }
- response->set_version(version);
- } else {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(ver_val)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "malformed version value";
- return;
+ std::string ver_val;
+ // 0 for success get a key, 1 for key not found, negative for error
+ err = txn->get(ver_key, &ver_val);
+ VLOG_DEBUG << "xxx get version_key=" << hex(ver_key);
+ if (err == TxnErrorCode::TXN_OK) {
+ if (is_table_version) {
+ int64_t version = 0;
+ if (!txn->decode_atomic_int(ver_val, &version)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "malformed table version value";
+ return;
+ }
+ response->set_version(version);
+ } else {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "malformed version value";
+ return;
+ }
+
+ if (version_pb.has_txn_id()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer_->submit(instance_id, version_pb.txn_id());
+
+ std::tie(code, msg) = task->wait();
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING)
+ << "wait txn lazy commit failed, txn_id=" << version_pb.txn_id();
+ return;
+ }
+ }
+
+ response->set_version(version_pb.version());
+ response->add_version_update_time_ms(version_pb.update_time_ms());
}
- response->set_version(version_pb.version());
- response->add_version_update_time_ms(version_pb.update_time_ms());
+ { TEST_SYNC_POINT_CALLBACK("get_version_code", &code); }
+ return;
+ } else if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ msg = "not found";
+ code = MetaServiceCode::VERSION_NOT_FOUND;
+ return;
}
- { TEST_SYNC_POINT_CALLBACK("get_version_code", &code); }
- return;
- } else if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
- msg = "not found";
- code = MetaServiceCode::VERSION_NOT_FOUND;
- return;
- }
- msg = fmt::format("failed to get txn, err={}", err);
- code = cast_as<ErrCategory::READ>(err);
+ msg = fmt::format("failed to get txn, err={}", err);
+ code = cast_as<ErrCategory::READ>(err);
+ } while (false);
Review Comment:
remove the `while`, since the `continue` are removed.
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,208 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
+ std::stringstream ss;
+ do {
+ code_ = MetaServiceCode::OK;
+ msg_.clear();
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id_, txn_id_, txn_kv_, code_, msg_, &db_id, &tmp_rowset_metas);
+ if (code_ != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id_ << " code=" << code_;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id_
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id_;
+ break;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t, std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
+ partition_to_tmp_rowset_metas;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].emplace_back();
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().first =
+ tmp_rowset_key;
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().second =
+ tmp_rowset_pb;
+ }
+
+ // tablet_id -> TabletIndexPB
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ for (auto& [partition_id, tmp_rowset_metas] : partition_to_tmp_rowset_metas) {
+ for (size_t i = 0; i < tmp_rowset_metas.size();
+ i += config::txn_lazy_max_rowsets_per_batch) {
+ size_t end = (i + config::txn_lazy_max_rowsets_per_batch) > tmp_rowset_metas.size()
+ ? tmp_rowset_metas.size()
+ : i + config::txn_lazy_max_rowsets_per_batch;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>
+ sub_partition_tmp_rowset_metas(tmp_rowset_metas.begin() + i,
+ tmp_rowset_metas.begin() + end);
+ convert_tmp_rowsets(instance_id_, txn_id_, txn_kv_, code_, msg_, db_id,
+ sub_partition_tmp_rowset_metas, tablet_ids);
+ if (code_ != MetaServiceCode::OK) break;
+ }
+ if (code_ != MetaServiceCode::OK) break;
+
+ DCHECK(tmp_rowset_metas.size() > 0);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code_ = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id_ << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+
+ int64_t table_id = -1;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ if (table_id <= 0) {
+ table_id = tablet_ids[tmp_rowset_pb.tablet_id()].table_id();
+ }
+ txn->remove(tmp_rowset_key);
+ }
+
+ DCHECK(table_id > 0);
+ DCHECK(partition_id > 0);
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id_, db_id, table_id, partition_id});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code_ = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id_
+ << " key=" << hex(ver_key) << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id_ << " key=" << hex(ver_key);
+ msg_ = ss.str();
+ break;
+ }
+
+ if (version_pb.has_txn_id() && version_pb.txn_id() == txn_id_) {
+ version_pb.clear_txn_id();
+ ver_val.clear();
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id_;
+ msg_ = ss.str();
+ return;
+ }
+ txn->put(ver_key, ver_val);
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
Review Comment:
Handle `TxnErrorCode::TXN_CONFLICT` too.
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -917,320 +1461,418 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
- msg = ss.str();
- return;
- }
- version = version_pb.version();
- } else {
- version = 1;
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
}
- new_versions[version_keys[i]] = version + 1;
+ txn->put(recycle_key, recycle_val);
}
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ err = txn->commit();
Review Comment:
No need to commit if this TXN is in TXN_STATUS_VISIBLE
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,208 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
+ std::stringstream ss;
+ do {
+ code_ = MetaServiceCode::OK;
+ msg_.clear();
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id_, txn_id_, txn_kv_, code_, msg_, &db_id, &tmp_rowset_metas);
+ if (code_ != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id_ << " code=" << code_;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id_
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id_;
+ break;
Review Comment:
Even if the tmp_rowset_metas is empty, the TXN might still not be visible. Consider call `make_committed_txn_visible` here.
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -387,10 +410,28 @@ void MetaServiceImpl::batch_get_version(::google::protobuf::RpcController* contr
msg = "malformed version value";
break;
}
+ if (version_pb.has_txn_id()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer_->submit(instance_id, version_pb.txn_id());
+ std::tie(code, msg) = task->wait();
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "wait txn lazy commit failed, txn_id="
+ << version_pb.txn_id();
+ break;
+ }
+ goto TRY_AGAIN;
+ }
response->add_versions(version_pb.version());
response->add_version_update_time_ms(version_pb.update_time_ms());
}
}
+ if (code != MetaServiceCode::OK) {
+ break;
+ }
+ }
+ if (code != MetaServiceCode::OK) {
+ break;
Review Comment:
Delete the useless code
##########
cloud/src/recycler/recycler_service.cpp:
##########
@@ -42,8 +42,12 @@ extern int reset_s3_rate_limiter(S3RateLimitType type, size_t max_speed, size_t
extern std::tuple<int, std::string_view> convert_ms_code_to_http_code(MetaServiceCode ret);
RecyclerServiceImpl::RecyclerServiceImpl(std::shared_ptr<TxnKv> txn_kv, Recycler* recycler,
- Checker* checker)
- : txn_kv_(std::move(txn_kv)), recycler_(recycler), checker_(checker) {}
+ Checker* checker,
+ std::shared_ptr<TxnLazyCommitter> txn_lazy_committer)
+ : txn_kv_(std::move(txn_kv)),
+ recycler_(recycler),
+ checker_(checker),
+ txn_lazy_committer_(txn_lazy_committer) {}
Review Comment:
```suggestion
txn_lazy_committer_(std::move(txn_lazy_committer)) {}
```
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -917,320 +1461,418 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
- msg = ss.str();
- return;
- }
- version = version_pb.version();
- } else {
- version = 1;
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
}
- new_versions[version_keys[i]] = version + 1;
+ txn->put(recycle_key, recycle_val);
}
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
Review Comment:
It seems that there is no need to read the tablet index again during retry.
Merge the PR first and then optimize this issue later.
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,208 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
+ std::stringstream ss;
+ do {
+ code_ = MetaServiceCode::OK;
+ msg_.clear();
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id_, txn_id_, txn_kv_, code_, msg_, &db_id, &tmp_rowset_metas);
+ if (code_ != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id_ << " code=" << code_;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id_
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id_;
+ break;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t, std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
+ partition_to_tmp_rowset_metas;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].emplace_back();
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().first =
+ tmp_rowset_key;
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().second =
+ tmp_rowset_pb;
+ }
+
+ // tablet_id -> TabletIndexPB
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ for (auto& [partition_id, tmp_rowset_metas] : partition_to_tmp_rowset_metas) {
+ for (size_t i = 0; i < tmp_rowset_metas.size();
+ i += config::txn_lazy_max_rowsets_per_batch) {
+ size_t end = (i + config::txn_lazy_max_rowsets_per_batch) > tmp_rowset_metas.size()
+ ? tmp_rowset_metas.size()
+ : i + config::txn_lazy_max_rowsets_per_batch;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>
+ sub_partition_tmp_rowset_metas(tmp_rowset_metas.begin() + i,
+ tmp_rowset_metas.begin() + end);
+ convert_tmp_rowsets(instance_id_, txn_id_, txn_kv_, code_, msg_, db_id,
+ sub_partition_tmp_rowset_metas, tablet_ids);
+ if (code_ != MetaServiceCode::OK) break;
+ }
+ if (code_ != MetaServiceCode::OK) break;
+
+ DCHECK(tmp_rowset_metas.size() > 0);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code_ = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id_ << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+
+ int64_t table_id = -1;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ if (table_id <= 0) {
+ table_id = tablet_ids[tmp_rowset_pb.tablet_id()].table_id();
+ }
+ txn->remove(tmp_rowset_key);
+ }
+
+ DCHECK(table_id > 0);
+ DCHECK(partition_id > 0);
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id_, db_id, table_id, partition_id});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code_ = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id_
+ << " key=" << hex(ver_key) << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id_ << " key=" << hex(ver_key);
+ msg_ = ss.str();
+ break;
+ }
+
+ if (version_pb.has_txn_id() && version_pb.txn_id() == txn_id_) {
+ version_pb.clear_txn_id();
+ ver_val.clear();
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id_;
+ msg_ = ss.str();
+ return;
+ }
+ txn->put(ver_key, ver_val);
+ }
+
+ err = txn->commit();
Review Comment:
No need to commit if `version_pb.has_txn_id() && version_pb.txn_id() == txn_id_` is false.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2275189325
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2291136442
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1732038003
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -862,94 +863,485 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
*/
void commit_txn_immediately(
const CommitTxnRequest* request, CommitTxnResponse* response,
- std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
- const std::string& instance_id, int64_t db_id,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
std::stringstream ss;
int64_t txn_id = request->txn_id();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // Get txn info with db_id and txn_id
- std::string info_val; // Will be reused when saving updated txn
- const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
- err = txn->get(info_key, &info_val);
- if (err != TxnErrorCode::TXN_OK) {
- code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
- : cast_as<ErrCategory::READ>(err);
- if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
- ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
- } else {
- ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
- << " err=" << err;
+ // Get txn info with db_id and txn_id
+ std::string info_val; // Will be reused when saving updated txn
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
+ } else {
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
+ }
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
- TxnInfoPB txn_info;
- if (!txn_info.ParseFromString(info_val)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // TODO: do more check like txn state, 2PC etc.
- DCHECK(txn_info.txn_id() == txn_id);
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
- code = MetaServiceCode::TXN_ALREADY_ABORTED;
- ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ // TODO: do more check like txn state, 2PC etc.
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
- if (request->has_is_2pc() && request->is_2pc()) {
- code = MetaServiceCode::TXN_ALREADY_VISIBLE;
- ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(INFO) << msg;
response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- code = MetaServiceCode::OK;
- ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(INFO) << msg;
- response->mutable_txn_info()->CopyFrom(txn_info);
- return;
- }
- if (request->has_is_2pc() && request->is_2pc() &&
- txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
- code = MetaServiceCode::TXN_INVALID_STATUS;
- ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Prepare rowset meta and new_versions
+ // Prepare rowset meta and new_versions
+ // Read tablet indexes in batch.
+ std::vector<std::string> tablet_idx_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
+ }
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ size_t total_rowsets = tmp_rowsets_meta.size();
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ for (size_t i = 0; i < total_rowsets; i++) {
+ uint64_t tablet_id = tmp_rowsets_meta[i].second.tablet_id();
+ if (!tablet_idx_values[i].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " tablet_id=" << tablet_id << " key=" << hex(tablet_idx_keys[i]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "malformed tablet index value tablet_id=" << tablet_id
Review Comment:
> do not change what you don't modify
for pipeline code format check
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "gavinchou (via GitHub)" <gi...@apache.org>.
gavinchou commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1713021124
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -265,6 +267,20 @@ void MetaServiceImpl::get_version(::google::protobuf::RpcController* controller,
msg = "malformed version value";
return;
}
+
+ if (version_pb.has_txn_id()) {
+ txn.reset();
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer_->submit(instance_id, version_pb.txn_id());
Review Comment:
how do we deal with the "duplicated" submmits to to the commiter
add comment here.
##########
gensrc/proto/cloud.proto:
##########
@@ -666,6 +667,7 @@ message CommitTxnRequest {
// for transaction load
optional bool is_txn_load = 9;
repeated SubTxnInfo sub_txn_infos = 10;
+ optional bool lazy_commit = 11;
Review Comment:
naming `enable_lazy_commit`
##########
be/src/cloud/config.h:
##########
@@ -94,4 +94,7 @@ DECLARE_mBool(save_load_error_log_to_s3);
// the theads which sync the datas which loaded in other clusters
DECLARE_mInt32(sync_load_for_tablets_thread);
+// enable large txn lazy commit in meta-service `commit_txn`
+DECLARE_mBool(cloud_txn_lazy_commit);
Review Comment:
naming `enable_cloud_txn_lazy_commit`
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -1420,104 +1454,152 @@ void MetaServiceImpl::get_rowset(::google::protobuf::RpcController* controller,
int64_t req_cc_cnt = request->cumulative_compaction_cnt();
int64_t req_cp = request->cumulative_point();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv_->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- msg = "failed to create txn";
- return;
- }
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ msg = "failed to create txn";
+ LOG(WARNING) << msg;
+ return;
+ }
- TabletIndexPB idx(request->idx());
- // Get tablet id index from kv
- if (!idx.has_table_id() || !idx.has_index_id() || !idx.has_partition_id()) {
+ TabletIndexPB idx;
+ // Get tablet id index from kv
get_tablet_idx(code, msg, txn.get(), instance_id, tablet_id, idx);
- if (code != MetaServiceCode::OK) return;
- }
- // TODO(plat1ko): Judge if tablet has been dropped (in dropped index/partition)
-
- TabletStatsPB tablet_stat;
- internal_get_tablet_stats(code, msg, txn.get(), instance_id, idx, tablet_stat, true);
- if (code != MetaServiceCode::OK) return;
- VLOG_DEBUG << "tablet_id=" << tablet_id << " stats=" << proto_to_json(tablet_stat);
+ if (code != MetaServiceCode::OK) {
+ return;
+ }
+ DCHECK(request->has_idx());
- int64_t bc_cnt = tablet_stat.base_compaction_cnt();
- int64_t cc_cnt = tablet_stat.cumulative_compaction_cnt();
- int64_t cp = tablet_stat.cumulative_point();
+ if (idx.has_db_id()) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, idx.db_id(), idx.table_id(), idx.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err && TxnErrorCode::TXN_KEY_NOT_FOUND != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, tablet_id=" << tablet_id
+ << " key=" << hex(ver_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- response->mutable_stats()->CopyFrom(tablet_stat);
+ if (TxnErrorCode::TXN_OK == err) {
Review Comment:
is there any chance we get other errors and do we have to deal with them?
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
Review Comment:
use constexpr instead of MACRO, and naming should be
`MAX_NUM_TABLET_INDEX`
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -862,94 +863,485 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
*/
void commit_txn_immediately(
const CommitTxnRequest* request, CommitTxnResponse* response,
- std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
- const std::string& instance_id, int64_t db_id,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
std::stringstream ss;
int64_t txn_id = request->txn_id();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // Get txn info with db_id and txn_id
- std::string info_val; // Will be reused when saving updated txn
- const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
- err = txn->get(info_key, &info_val);
- if (err != TxnErrorCode::TXN_OK) {
- code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
- : cast_as<ErrCategory::READ>(err);
- if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
- ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
- } else {
- ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
- << " err=" << err;
+ // Get txn info with db_id and txn_id
+ std::string info_val; // Will be reused when saving updated txn
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
+ } else {
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
+ }
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
- TxnInfoPB txn_info;
- if (!txn_info.ParseFromString(info_val)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // TODO: do more check like txn state, 2PC etc.
- DCHECK(txn_info.txn_id() == txn_id);
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
- code = MetaServiceCode::TXN_ALREADY_ABORTED;
- ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ // TODO: do more check like txn state, 2PC etc.
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
- if (request->has_is_2pc() && request->is_2pc()) {
- code = MetaServiceCode::TXN_ALREADY_VISIBLE;
- ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(INFO) << msg;
response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- code = MetaServiceCode::OK;
- ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(INFO) << msg;
- response->mutable_txn_info()->CopyFrom(txn_info);
- return;
- }
- if (request->has_is_2pc() && request->is_2pc() &&
- txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
- code = MetaServiceCode::TXN_INVALID_STATUS;
- ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Prepare rowset meta and new_versions
+ // Prepare rowset meta and new_versions
+ // Read tablet indexes in batch.
+ std::vector<std::string> tablet_idx_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
+ }
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ size_t total_rowsets = tmp_rowsets_meta.size();
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ for (size_t i = 0; i < total_rowsets; i++) {
+ uint64_t tablet_id = tmp_rowsets_meta[i].second.tablet_id();
+ if (!tablet_idx_values[i].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " tablet_id=" << tablet_id << " key=" << hex(tablet_idx_keys[i]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "malformed tablet index value tablet_id=" << tablet_id
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ VLOG_DEBUG << "tablet_id:" << tablet_id
+ << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ }
+
+ tablet_idx_keys.clear();
+ tablet_idx_values.clear();
+
+ // {table/partition} -> version
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
+ }
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ size_t total_versions = version_keys.size();
+ for (size_t i = 0; i < total_versions; i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+ version_keys.clear();
+ version_values.clear();
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
+ continue;
+ }
+
+ std::vector<std::pair<std::string, std::string>> rowsets;
+ std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
+ rowsets.reserve(tmp_rowsets_meta.size());
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions[ver_key] == 0) [[unlikely]] {
+ // it is impossible.
+ code = MetaServiceCode::UNDEFINED_ERR;
+ ss << "failed to get partition version key, the target version not exists in "
+ "new_versions."
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(ERROR) << msg;
+ return;
+ }
+
+ // Update rowset version
+ int64_t new_version = new_versions[ver_key];
+ i.set_start_version(new_version);
+ i.set_end_version(new_version);
+
+ std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
+ std::string val;
+ if (!i.SerializeToString(&val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ rowsets.emplace_back(std::move(key), std::move(val));
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tablet_id];
+ stats.data_size += i.data_disk_size();
+ stats.num_rows += i.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += i.num_segments();
+ } // for tmp_rowsets_meta
+
+ // process mow table, check lock and remove pending key
+ std::vector<std::string> lock_keys;
+ lock_keys.reserve(request->mow_table_ids().size());
+ for (auto table_id : request->mow_table_ids()) {
+ lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
+ }
+ std::vector<std::optional<std::string>> lock_values;
+ err = txn->batch_get(&lock_values, lock_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
+ << " err=" << err;
+ msg = ss.str();
+ code = cast_as<ErrCategory::READ>(err);
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ size_t total_locks = lock_keys.size();
+ for (size_t i = 0; i < total_locks; i++) {
+ int64_t table_id = request->mow_table_ids(i);
+ // When the key does not exist, it means the lock has been acquired
+ // by another transaction and successfully committed.
+ if (!lock_values[i].has_value()) {
+ ss << "get delete bitmap update lock info, lock is expired"
+ << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
+ code = MetaServiceCode::LOCK_EXPIRED;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ DeleteBitmapUpdateLockPB lock_info;
+ if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "failed to parse DeleteBitmapUpdateLockPB";
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ if (lock_info.lock_id() != request->txn_id()) {
+ msg = "lock is expired";
+ code = MetaServiceCode::LOCK_EXPIRED;
+ return;
+ }
+ txn->remove(lock_keys[i]);
+ LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
+ << " txn_id=" << txn_id;
+
+ for (auto tablet_id : table_id_tablet_ids[table_id]) {
+ std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
+ txn->remove(pending_key);
+ LOG(INFO) << "xxx remove delete bitmap pending key, pending_key="
Review Comment:
do not change what you don't modify
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
msg = ss.str();
return;
}
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
- std::string_view ver_key = i.first;
- ver_key.remove_prefix(1); // Remove key space
- // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- int ret = decode_key(&ver_key, &out);
- if (ret != 0) [[unlikely]] {
- // decode version key error means this is something wrong,
- // we can not continue this txn
- LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = "decode version key error";
- return;
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
}
- int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
- int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
- VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+ // save versions for partition
+ int64_t version_update_time_ms =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ response->set_version_update_time_ms(version_update_time_ms);
+ for (auto& i : new_versions) {
Review Comment:
use structured binding instead of dereference with `.first` `.second`
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
Review Comment:
also explain why
##########
cloud/src/common/config.h:
##########
@@ -201,4 +201,8 @@ CONF_Validator(s3_client_http_scheme, [](const std::string& config) -> bool {
// Max retry times for object storage request
CONF_mInt64(max_s3_client_retry, "10");
+CONF_Bool(enable_txn_lazy_commit, "true");
+CONF_Int32(txn_lazy_commit_rowsets_thresold, "1024");
Review Comment:
add comment for this config
e.g. "try to commit doris txn lazily if number of involved tablets of a single txn"
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
msg = ss.str();
return;
}
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
- std::string_view ver_key = i.first;
- ver_key.remove_prefix(1); // Remove key space
- // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- int ret = decode_key(&ver_key, &out);
- if (ret != 0) [[unlikely]] {
- // decode version key error means this is something wrong,
- // we can not continue this txn
- LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = "decode version key error";
- return;
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
}
- int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
- int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
- VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+ // save versions for partition
+ int64_t version_update_time_ms =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ response->set_version_update_time_ms(version_update_time_ms);
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_txn_id(txn_id);
+ version_pb.set_update_time_ms(version_update_time_ms);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- response->add_table_ids(table_id);
- response->add_partition_ids(partition_id);
- response->add_versions(i.second);
- }
+ txn->put(i.first, ver_val);
+ LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
+ << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+
+ std::string_view ver_key = i.first;
+ ver_key.remove_prefix(1); // Remove key space
+ // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
+ int ret = decode_key(&ver_key, &out);
+ if (ret != 0) [[unlikely]] {
+ // decode version key error means this is something wrong,
+ // we can not continue this txn
+ LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = "decode version key error";
+ return;
+ }
- // Save table versions
- for (auto& i : table_id_tablet_ids) {
- std::string ver_key = table_version_key({instance_id, db_id, i.first});
- txn->atomic_add(ver_key, 1);
- LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key) << " txn_id=" << txn_id;
- }
+ int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
+ int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
+ VLOG_DEBUG << "txn_id=" << txn_id << " table_id=" << table_id
+ << " partition_id=" << partition_id << " version=" << i.second;
- LOG(INFO) << " before update txn_info=" << txn_info.ShortDebugString();
+ response->add_table_ids(table_id);
+ response->add_partition_ids(partition_id);
+ response->add_versions(i.second);
+ }
- // Update txn_info
- txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ // process mow table, check lock and remove pending key
+ std::vector<std::string> lock_keys;
+ lock_keys.reserve(request->mow_table_ids().size());
+ for (auto table_id : request->mow_table_ids()) {
+ lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
+ }
+ std::vector<std::optional<std::string>> lock_values;
+ err = txn->batch_get(&lock_values, lock_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
+ << " err=" << err;
+ msg = ss.str();
+ code = cast_as<ErrCategory::READ>(err);
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- auto now_time = system_clock::now();
- uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
- if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
- LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
- << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
- return;
- }
- txn_info.set_commit_time(commit_time);
- txn_info.set_finish_time(commit_time);
- if (request->has_commit_attachment()) {
- txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
- }
- LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
- info_val.clear();
- if (!txn_info.SerializeToString(&info_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(info_key, info_val);
- LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+ for (size_t i = 0; i < lock_keys.size(); i++) {
+ int64_t table_id = request->mow_table_ids(i);
+ // When the key does not exist, it means the lock has been acquired
+ // by another transaction and successfully committed.
+ if (!lock_values[i].has_value()) {
+ ss << "get delete bitmap update lock info, lock is expired"
+ << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
+ code = MetaServiceCode::LOCK_EXPIRED;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- // Update stats of affected tablet
- for (auto& [tablet_id, stats] : tablet_stats) {
- DCHECK(tablet_ids.count(tablet_id));
- auto& tablet_idx = tablet_ids[tablet_id];
- StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
- tablet_idx.partition_id(), tablet_id};
- update_tablet_stats(info, stats, txn, code, msg);
- if (code != MetaServiceCode::OK) return;
- }
- // Remove tmp rowset meta
- for (auto& [k, _] : tmp_rowsets_meta) {
- txn->remove(k);
- LOG(INFO) << "xxx remove tmp_rowset_key=" << hex(k) << " txn_id=" << txn_id;
- }
+ DeleteBitmapUpdateLockPB lock_info;
+ if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "failed to parse DeleteBitmapUpdateLockPB";
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ if (lock_info.lock_id() != request->txn_id()) {
+ msg = "lock is expired";
+ code = MetaServiceCode::LOCK_EXPIRED;
+ return;
+ }
+ txn->remove(lock_keys[i]);
+ LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
+ << " txn_id=" << txn_id;
- const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
- LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
- txn->remove(running_key);
+ for (auto tablet_id : table_id_tablet_ids[table_id]) {
+ std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
+ txn->remove(pending_key);
+ LOG(INFO) << "xxx remove delete bitmap pending key, pending_key="
+ << hex(pending_key) << " txn_id=" << txn_id;
+ }
+ }
+ lock_keys.clear();
+ lock_values.clear();
- std::string recycle_val;
- std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
- RecycleTxnPB recycle_pb;
- recycle_pb.set_creation_time(commit_time);
- recycle_pb.set_label(txn_info.label());
+ // Save table versions
+ for (auto& i : table_id_tablet_ids) {
+ std::string ver_key = table_version_key({instance_id, db_id, i.first});
+ txn->atomic_add(ver_key, 1);
+ LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key)
+ << " txn_id=" << txn_id;
+ }
- if (!recycle_pb.SerializeToString(&recycle_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(recycle_key, recycle_val);
+ LOG(INFO) << "commit_txn_eventually put_size=" << txn->put_bytes()
+ << " del_size=" << txn->delete_bytes() << " num_put_keys=" << txn->num_put_keys()
+ << " num_del_keys=" << txn->num_del_keys()
+ << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
- if (txn_info.load_job_source_type() ==
- LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
- put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
- }
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
- LOG(INFO) << "xxx commit_txn put recycle_key key=" << hex(recycle_key) << " txn_id=" << txn_id;
- LOG(INFO) << "commit_txn put_size=" << txn->put_bytes() << " del_size=" << txn->delete_bytes()
- << " num_put_keys=" << txn->num_put_keys() << " num_del_keys=" << txn->num_del_keys()
- << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
+ std::shared_ptr<TxnLazyCommitTask> task = txn_lazy_committer->submit(instance_id, txn_id);
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ if (ret.first != MetaServiceCode::OK) {
+ LOG(WARNING) << "lazy commit txn failed txn_id=" << txn_id << " code=" << ret.first
Review Comment:
what can we do if we reach this branch?
##########
fe/fe-common/src/main/java/org/apache/doris/common/Config.java:
##########
@@ -3017,6 +3017,10 @@ public static int metaServiceRpcRetryTimes() {
@ConfField(mutable = true, description = {"存算分离模式下commit阶段等锁超时时间,默认5s"})
public static int try_commit_lock_timeout_seconds = 5;
+
+ @ConfField(mutable = true, description = {"存算分离模式下是否开启大事务提交,默认false"})
+ public static boolean cloud_txn_lazy_commit = false;
Review Comment:
naming `enable_cloud_txn_lazy_commit`
##########
cloud/src/common/config.h:
##########
@@ -206,4 +206,8 @@ CONF_Validator(s3_client_http_scheme, [](const std::string& config) -> bool {
// Max retry times for object storage request
CONF_mInt64(max_s3_client_retry, "10");
+CONF_Bool(enable_txn_lazy_commit, "true");
+CONF_Int32(txn_lazy_commit_rowsets_thresold, "2048");
+CONF_Int32(txn_lazy_commit_num_threads, "8");
+CONF_Int32(txn_lazy_max_rowsets_per_batch, "2048");
Review Comment:
what the relation between `txn_lazy_max_rowsets_per_batch` and `txn_lazy_max_rowsets_per_batch`
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -969,337 +1357,473 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
Review Comment:
constexpr MAX_TABLET_INDEX_NUM
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -1420,104 +1454,152 @@ void MetaServiceImpl::get_rowset(::google::protobuf::RpcController* controller,
int64_t req_cc_cnt = request->cumulative_compaction_cnt();
int64_t req_cp = request->cumulative_point();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv_->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- msg = "failed to create txn";
- return;
- }
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ msg = "failed to create txn";
+ LOG(WARNING) << msg;
+ return;
+ }
- TabletIndexPB idx(request->idx());
- // Get tablet id index from kv
- if (!idx.has_table_id() || !idx.has_index_id() || !idx.has_partition_id()) {
+ TabletIndexPB idx;
+ // Get tablet id index from kv
get_tablet_idx(code, msg, txn.get(), instance_id, tablet_id, idx);
- if (code != MetaServiceCode::OK) return;
- }
- // TODO(plat1ko): Judge if tablet has been dropped (in dropped index/partition)
-
- TabletStatsPB tablet_stat;
- internal_get_tablet_stats(code, msg, txn.get(), instance_id, idx, tablet_stat, true);
- if (code != MetaServiceCode::OK) return;
- VLOG_DEBUG << "tablet_id=" << tablet_id << " stats=" << proto_to_json(tablet_stat);
+ if (code != MetaServiceCode::OK) {
+ return;
+ }
+ DCHECK(request->has_idx());
- int64_t bc_cnt = tablet_stat.base_compaction_cnt();
- int64_t cc_cnt = tablet_stat.cumulative_compaction_cnt();
- int64_t cp = tablet_stat.cumulative_point();
+ if (idx.has_db_id()) {
Review Comment:
add comment what is this code block for. e.g. historical reason or compatibility reason or something else related to lazy commit
##########
cloud/src/meta-service/txn_lazy_committer.h:
##########
@@ -0,0 +1,68 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <gen_cpp/cloud.pb.h>
+
+#include <atomic>
+
+#include "common/simple_thread_pool.h"
+#include "meta-service/txn_kv.h"
+
+namespace doris::cloud {
+
+class TxnLazyCommitter;
+
+class TxnLazyCommitTask {
+public:
+ TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer);
+ void commit();
+
+ std::pair<MetaServiceCode, std::string> wait();
+
+private:
+ friend class TxnLazyCommitter;
+
+ std::string instance_id_;
+ int64_t txn_id_;
+ std::shared_ptr<TxnKv> txn_kv_;
+ std::mutex mutex_;
+ std::condition_variable cond_;
+ bool finished_ = false;
+ MetaServiceCode code_ = MetaServiceCode::OK;
+ std::string msg_;
+ TxnLazyCommitter* txn_lazy_committer_;
+};
+
+class TxnLazyCommitter {
+public:
+ TxnLazyCommitter(std::shared_ptr<TxnKv> txn_kv);
Review Comment:
Add comment for each function describing the behaviors and the parameters
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
Review Comment:
what if the commit returns errors like
1. value exceeds max bytes
2. transaction too old
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -862,94 +863,485 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
*/
void commit_txn_immediately(
const CommitTxnRequest* request, CommitTxnResponse* response,
- std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
- const std::string& instance_id, int64_t db_id,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
std::stringstream ss;
int64_t txn_id = request->txn_id();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // Get txn info with db_id and txn_id
- std::string info_val; // Will be reused when saving updated txn
- const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
- err = txn->get(info_key, &info_val);
- if (err != TxnErrorCode::TXN_OK) {
- code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
- : cast_as<ErrCategory::READ>(err);
- if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
- ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
- } else {
- ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
- << " err=" << err;
+ // Get txn info with db_id and txn_id
+ std::string info_val; // Will be reused when saving updated txn
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
+ } else {
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
+ }
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
- TxnInfoPB txn_info;
- if (!txn_info.ParseFromString(info_val)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // TODO: do more check like txn state, 2PC etc.
- DCHECK(txn_info.txn_id() == txn_id);
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
- code = MetaServiceCode::TXN_ALREADY_ABORTED;
- ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ // TODO: do more check like txn state, 2PC etc.
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
- if (request->has_is_2pc() && request->is_2pc()) {
- code = MetaServiceCode::TXN_ALREADY_VISIBLE;
- ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(INFO) << msg;
response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- code = MetaServiceCode::OK;
- ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(INFO) << msg;
- response->mutable_txn_info()->CopyFrom(txn_info);
- return;
- }
- if (request->has_is_2pc() && request->is_2pc() &&
- txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
- code = MetaServiceCode::TXN_INVALID_STATUS;
- ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Prepare rowset meta and new_versions
+ // Prepare rowset meta and new_versions
+ // Read tablet indexes in batch.
+ std::vector<std::string> tablet_idx_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
+ }
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ size_t total_rowsets = tmp_rowsets_meta.size();
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ for (size_t i = 0; i < total_rowsets; i++) {
+ uint64_t tablet_id = tmp_rowsets_meta[i].second.tablet_id();
+ if (!tablet_idx_values[i].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " tablet_id=" << tablet_id << " key=" << hex(tablet_idx_keys[i]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "malformed tablet index value tablet_id=" << tablet_id
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ VLOG_DEBUG << "tablet_id:" << tablet_id
+ << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ }
+
+ tablet_idx_keys.clear();
+ tablet_idx_values.clear();
+
+ // {table/partition} -> version
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
Review Comment:
do not change what you don't modify
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -1420,104 +1454,152 @@ void MetaServiceImpl::get_rowset(::google::protobuf::RpcController* controller,
int64_t req_cc_cnt = request->cumulative_compaction_cnt();
int64_t req_cp = request->cumulative_point();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv_->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- msg = "failed to create txn";
- return;
- }
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ msg = "failed to create txn";
+ LOG(WARNING) << msg;
+ return;
+ }
- TabletIndexPB idx(request->idx());
- // Get tablet id index from kv
- if (!idx.has_table_id() || !idx.has_index_id() || !idx.has_partition_id()) {
+ TabletIndexPB idx;
+ // Get tablet id index from kv
get_tablet_idx(code, msg, txn.get(), instance_id, tablet_id, idx);
- if (code != MetaServiceCode::OK) return;
- }
- // TODO(plat1ko): Judge if tablet has been dropped (in dropped index/partition)
-
- TabletStatsPB tablet_stat;
- internal_get_tablet_stats(code, msg, txn.get(), instance_id, idx, tablet_stat, true);
- if (code != MetaServiceCode::OK) return;
- VLOG_DEBUG << "tablet_id=" << tablet_id << " stats=" << proto_to_json(tablet_stat);
+ if (code != MetaServiceCode::OK) {
+ return;
+ }
+ DCHECK(request->has_idx());
- int64_t bc_cnt = tablet_stat.base_compaction_cnt();
- int64_t cc_cnt = tablet_stat.cumulative_compaction_cnt();
- int64_t cp = tablet_stat.cumulative_point();
+ if (idx.has_db_id()) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, idx.db_id(), idx.table_id(), idx.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err && TxnErrorCode::TXN_KEY_NOT_FOUND != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, tablet_id=" << tablet_id
+ << " key=" << hex(ver_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- response->mutable_stats()->CopyFrom(tablet_stat);
+ if (TxnErrorCode::TXN_OK == err) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb tablet_id=" << tablet_id
Review Comment:
also log partition id
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
Review Comment:
add comment what does it do and why
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -862,94 +863,485 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
*/
void commit_txn_immediately(
const CommitTxnRequest* request, CommitTxnResponse* response,
- std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
- const std::string& instance_id, int64_t db_id,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
std::stringstream ss;
int64_t txn_id = request->txn_id();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // Get txn info with db_id and txn_id
- std::string info_val; // Will be reused when saving updated txn
- const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
- err = txn->get(info_key, &info_val);
- if (err != TxnErrorCode::TXN_OK) {
- code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
- : cast_as<ErrCategory::READ>(err);
- if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
- ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
- } else {
- ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
- << " err=" << err;
+ // Get txn info with db_id and txn_id
+ std::string info_val; // Will be reused when saving updated txn
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
+ } else {
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
+ }
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
- TxnInfoPB txn_info;
- if (!txn_info.ParseFromString(info_val)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // TODO: do more check like txn state, 2PC etc.
- DCHECK(txn_info.txn_id() == txn_id);
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
- code = MetaServiceCode::TXN_ALREADY_ABORTED;
- ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ // TODO: do more check like txn state, 2PC etc.
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
- if (request->has_is_2pc() && request->is_2pc()) {
- code = MetaServiceCode::TXN_ALREADY_VISIBLE;
- ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(INFO) << msg;
response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- code = MetaServiceCode::OK;
- ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(INFO) << msg;
- response->mutable_txn_info()->CopyFrom(txn_info);
- return;
- }
- if (request->has_is_2pc() && request->is_2pc() &&
- txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
- code = MetaServiceCode::TXN_INVALID_STATUS;
- ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Prepare rowset meta and new_versions
+ // Prepare rowset meta and new_versions
+ // Read tablet indexes in batch.
+ std::vector<std::string> tablet_idx_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
+ }
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ size_t total_rowsets = tmp_rowsets_meta.size();
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ for (size_t i = 0; i < total_rowsets; i++) {
+ uint64_t tablet_id = tmp_rowsets_meta[i].second.tablet_id();
+ if (!tablet_idx_values[i].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " tablet_id=" << tablet_id << " key=" << hex(tablet_idx_keys[i]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "malformed tablet index value tablet_id=" << tablet_id
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ VLOG_DEBUG << "tablet_id:" << tablet_id
+ << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ }
+
+ tablet_idx_keys.clear();
+ tablet_idx_values.clear();
+
+ // {table/partition} -> version
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
+ }
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ size_t total_versions = version_keys.size();
+ for (size_t i = 0; i < total_versions; i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
Review Comment:
use single `last_pending_txn_id` is enough to describe the logic `need_advance_last_txn` and `last_pending_txn_id`.
because, last_pending_txn_id != 0 always means need_advance_last_txn == true? != 0 always means
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -862,94 +863,485 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
*/
void commit_txn_immediately(
const CommitTxnRequest* request, CommitTxnResponse* response,
- std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
- const std::string& instance_id, int64_t db_id,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
std::stringstream ss;
int64_t txn_id = request->txn_id();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // Get txn info with db_id and txn_id
- std::string info_val; // Will be reused when saving updated txn
- const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
- err = txn->get(info_key, &info_val);
- if (err != TxnErrorCode::TXN_OK) {
- code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
- : cast_as<ErrCategory::READ>(err);
- if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
- ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
- } else {
- ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
- << " err=" << err;
+ // Get txn info with db_id and txn_id
+ std::string info_val; // Will be reused when saving updated txn
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
+ } else {
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
+ }
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
- TxnInfoPB txn_info;
- if (!txn_info.ParseFromString(info_val)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // TODO: do more check like txn state, 2PC etc.
- DCHECK(txn_info.txn_id() == txn_id);
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
- code = MetaServiceCode::TXN_ALREADY_ABORTED;
- ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ // TODO: do more check like txn state, 2PC etc.
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
- if (request->has_is_2pc() && request->is_2pc()) {
- code = MetaServiceCode::TXN_ALREADY_VISIBLE;
- ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(INFO) << msg;
response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- code = MetaServiceCode::OK;
- ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(INFO) << msg;
- response->mutable_txn_info()->CopyFrom(txn_info);
- return;
- }
- if (request->has_is_2pc() && request->is_2pc() &&
- txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
- code = MetaServiceCode::TXN_INVALID_STATUS;
- ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Prepare rowset meta and new_versions
+ // Prepare rowset meta and new_versions
+ // Read tablet indexes in batch.
+ std::vector<std::string> tablet_idx_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
+ }
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ size_t total_rowsets = tmp_rowsets_meta.size();
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ for (size_t i = 0; i < total_rowsets; i++) {
+ uint64_t tablet_id = tmp_rowsets_meta[i].second.tablet_id();
+ if (!tablet_idx_values[i].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " tablet_id=" << tablet_id << " key=" << hex(tablet_idx_keys[i]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "malformed tablet index value tablet_id=" << tablet_id
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ VLOG_DEBUG << "tablet_id:" << tablet_id
+ << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ }
+
+ tablet_idx_keys.clear();
+ tablet_idx_values.clear();
+
+ // {table/partition} -> version
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
+ }
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ size_t total_versions = version_keys.size();
+ for (size_t i = 0; i < total_versions; i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+ version_keys.clear();
+ version_values.clear();
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
+ continue;
+ }
+
+ std::vector<std::pair<std::string, std::string>> rowsets;
+ std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
+ rowsets.reserve(tmp_rowsets_meta.size());
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
Review Comment:
do not change what you don't modify
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -862,94 +863,485 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
*/
void commit_txn_immediately(
const CommitTxnRequest* request, CommitTxnResponse* response,
- std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
- const std::string& instance_id, int64_t db_id,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
std::stringstream ss;
int64_t txn_id = request->txn_id();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // Get txn info with db_id and txn_id
- std::string info_val; // Will be reused when saving updated txn
- const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
- err = txn->get(info_key, &info_val);
- if (err != TxnErrorCode::TXN_OK) {
- code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
- : cast_as<ErrCategory::READ>(err);
- if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
- ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
- } else {
- ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
- << " err=" << err;
+ // Get txn info with db_id and txn_id
+ std::string info_val; // Will be reused when saving updated txn
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
+ } else {
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
+ }
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
- TxnInfoPB txn_info;
- if (!txn_info.ParseFromString(info_val)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // TODO: do more check like txn state, 2PC etc.
- DCHECK(txn_info.txn_id() == txn_id);
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
- code = MetaServiceCode::TXN_ALREADY_ABORTED;
- ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ // TODO: do more check like txn state, 2PC etc.
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
- if (request->has_is_2pc() && request->is_2pc()) {
- code = MetaServiceCode::TXN_ALREADY_VISIBLE;
- ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(INFO) << msg;
response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- code = MetaServiceCode::OK;
- ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(INFO) << msg;
- response->mutable_txn_info()->CopyFrom(txn_info);
- return;
- }
- if (request->has_is_2pc() && request->is_2pc() &&
- txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
- code = MetaServiceCode::TXN_INVALID_STATUS;
- ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Prepare rowset meta and new_versions
+ // Prepare rowset meta and new_versions
+ // Read tablet indexes in batch.
+ std::vector<std::string> tablet_idx_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
+ }
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ size_t total_rowsets = tmp_rowsets_meta.size();
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ for (size_t i = 0; i < total_rowsets; i++) {
+ uint64_t tablet_id = tmp_rowsets_meta[i].second.tablet_id();
+ if (!tablet_idx_values[i].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " tablet_id=" << tablet_id << " key=" << hex(tablet_idx_keys[i]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "malformed tablet index value tablet_id=" << tablet_id
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ VLOG_DEBUG << "tablet_id:" << tablet_id
+ << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ }
+
+ tablet_idx_keys.clear();
+ tablet_idx_values.clear();
+
+ // {table/partition} -> version
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
+ }
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ size_t total_versions = version_keys.size();
+ for (size_t i = 0; i < total_versions; i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+ version_keys.clear();
+ version_values.clear();
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
+ continue;
+ }
+
+ std::vector<std::pair<std::string, std::string>> rowsets;
+ std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
+ rowsets.reserve(tmp_rowsets_meta.size());
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions[ver_key] == 0) [[unlikely]] {
+ // it is impossible.
+ code = MetaServiceCode::UNDEFINED_ERR;
+ ss << "failed to get partition version key, the target version not exists in "
+ "new_versions."
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(ERROR) << msg;
+ return;
+ }
+
+ // Update rowset version
+ int64_t new_version = new_versions[ver_key];
+ i.set_start_version(new_version);
+ i.set_end_version(new_version);
+
+ std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
+ std::string val;
+ if (!i.SerializeToString(&val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ rowsets.emplace_back(std::move(key), std::move(val));
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tablet_id];
+ stats.data_size += i.data_disk_size();
+ stats.num_rows += i.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += i.num_segments();
+ } // for tmp_rowsets_meta
+
+ // process mow table, check lock and remove pending key
+ std::vector<std::string> lock_keys;
+ lock_keys.reserve(request->mow_table_ids().size());
+ for (auto table_id : request->mow_table_ids()) {
+ lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
+ }
+ std::vector<std::optional<std::string>> lock_values;
+ err = txn->batch_get(&lock_values, lock_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
+ << " err=" << err;
+ msg = ss.str();
+ code = cast_as<ErrCategory::READ>(err);
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ size_t total_locks = lock_keys.size();
+ for (size_t i = 0; i < total_locks; i++) {
+ int64_t table_id = request->mow_table_ids(i);
+ // When the key does not exist, it means the lock has been acquired
+ // by another transaction and successfully committed.
+ if (!lock_values[i].has_value()) {
+ ss << "get delete bitmap update lock info, lock is expired"
+ << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
+ code = MetaServiceCode::LOCK_EXPIRED;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ DeleteBitmapUpdateLockPB lock_info;
+ if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "failed to parse DeleteBitmapUpdateLockPB";
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ if (lock_info.lock_id() != request->txn_id()) {
+ msg = "lock is expired";
+ code = MetaServiceCode::LOCK_EXPIRED;
+ return;
+ }
+ txn->remove(lock_keys[i]);
+ LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
+ << " txn_id=" << txn_id;
+
+ for (auto tablet_id : table_id_tablet_ids[table_id]) {
+ std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
+ txn->remove(pending_key);
+ LOG(INFO) << "xxx remove delete bitmap pending key, pending_key="
+ << hex(pending_key) << " txn_id=" << txn_id;
+ }
+ }
+ lock_keys.clear();
+ lock_values.clear();
+
+ // Save rowset meta
+ for (auto& i : rowsets) {
+ size_t rowset_size = i.first.size() + i.second.size();
+ txn->put(i.first, i.second);
+ LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_size;
+ }
+
+ // Save versions
+ int64_t version_update_time_ms =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ response->set_version_update_time_ms(version_update_time_ms);
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_update_time_ms(version_update_time_ms);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(i.first, ver_val);
+ LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
+ << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+
+ std::string_view ver_key = i.first;
+ ver_key.remove_prefix(1); // Remove key space
+ // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
+ int ret = decode_key(&ver_key, &out);
+ if (ret != 0) [[unlikely]] {
+ // decode version key error means this is something wrong,
+ // we can not continue this txn
+ LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = "decode version key error";
+ return;
+ }
+
+ int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
+ int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
+ VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+
+ response->add_table_ids(table_id);
+ response->add_partition_ids(partition_id);
+ response->add_versions(i.second);
+ }
+
+ // Save table versions
+ for (auto& i : table_id_tablet_ids) {
+ std::string ver_key = table_version_key({instance_id, db_id, i.first});
+ txn->atomic_add(ver_key, 1);
+ LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key)
Review Comment:
do not change what you don't modify
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -862,94 +863,485 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
*/
void commit_txn_immediately(
const CommitTxnRequest* request, CommitTxnResponse* response,
- std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
- const std::string& instance_id, int64_t db_id,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
std::stringstream ss;
int64_t txn_id = request->txn_id();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // Get txn info with db_id and txn_id
- std::string info_val; // Will be reused when saving updated txn
- const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
- err = txn->get(info_key, &info_val);
- if (err != TxnErrorCode::TXN_OK) {
- code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
- : cast_as<ErrCategory::READ>(err);
- if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
- ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
- } else {
- ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
- << " err=" << err;
+ // Get txn info with db_id and txn_id
+ std::string info_val; // Will be reused when saving updated txn
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
+ } else {
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
+ }
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
- TxnInfoPB txn_info;
- if (!txn_info.ParseFromString(info_val)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // TODO: do more check like txn state, 2PC etc.
- DCHECK(txn_info.txn_id() == txn_id);
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
- code = MetaServiceCode::TXN_ALREADY_ABORTED;
- ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ // TODO: do more check like txn state, 2PC etc.
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
- if (request->has_is_2pc() && request->is_2pc()) {
- code = MetaServiceCode::TXN_ALREADY_VISIBLE;
- ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(INFO) << msg;
response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- code = MetaServiceCode::OK;
- ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(INFO) << msg;
- response->mutable_txn_info()->CopyFrom(txn_info);
- return;
- }
- if (request->has_is_2pc() && request->is_2pc() &&
- txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
- code = MetaServiceCode::TXN_INVALID_STATUS;
- ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Prepare rowset meta and new_versions
+ // Prepare rowset meta and new_versions
+ // Read tablet indexes in batch.
+ std::vector<std::string> tablet_idx_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
+ }
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ size_t total_rowsets = tmp_rowsets_meta.size();
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ for (size_t i = 0; i < total_rowsets; i++) {
+ uint64_t tablet_id = tmp_rowsets_meta[i].second.tablet_id();
+ if (!tablet_idx_values[i].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " tablet_id=" << tablet_id << " key=" << hex(tablet_idx_keys[i]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "malformed tablet index value tablet_id=" << tablet_id
Review Comment:
do not change what you don't modify
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -862,94 +863,485 @@ void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stat
*/
void commit_txn_immediately(
const CommitTxnRequest* request, CommitTxnResponse* response,
- std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
- const std::string& instance_id, int64_t db_id,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
std::stringstream ss;
int64_t txn_id = request->txn_id();
- std::unique_ptr<Transaction> txn;
- TxnErrorCode err = txn_kv->create_txn(&txn);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::CREATE>(err);
- ss << "filed to create txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+ do {
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // Get txn info with db_id and txn_id
- std::string info_val; // Will be reused when saving updated txn
- const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
- err = txn->get(info_key, &info_val);
- if (err != TxnErrorCode::TXN_OK) {
- code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
- : cast_as<ErrCategory::READ>(err);
- if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
- ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
- } else {
- ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
- << " err=" << err;
+ // Get txn info with db_id and txn_id
+ std::string info_val; // Will be reused when saving updated txn
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ if (err == TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ ss << "transaction [" << txn_id << "] not found, db_id=" << db_id;
+ } else {
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
+ }
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
- TxnInfoPB txn_info;
- if (!txn_info.ParseFromString(info_val)) {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- // TODO: do more check like txn state, 2PC etc.
- DCHECK(txn_info.txn_id() == txn_id);
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
- code = MetaServiceCode::TXN_ALREADY_ABORTED;
- ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ // TODO: do more check like txn state, 2PC etc.
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction [" << txn_id << "] is already aborted, db_id=" << db_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
- if (request->has_is_2pc() && request->is_2pc()) {
- code = MetaServiceCode::TXN_ALREADY_VISIBLE;
- ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(INFO) << msg;
response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- code = MetaServiceCode::OK;
- ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
- msg = ss.str();
- LOG(INFO) << msg;
- response->mutable_txn_info()->CopyFrom(txn_info);
- return;
- }
- if (request->has_is_2pc() && request->is_2pc() &&
- txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
- code = MetaServiceCode::TXN_INVALID_STATUS;
- ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id" << txn_id;
- msg = ss.str();
- LOG(WARNING) << msg;
- return;
- }
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
- LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Prepare rowset meta and new_versions
+ // Prepare rowset meta and new_versions
+ // Read tablet indexes in batch.
+ std::vector<std::string> tablet_idx_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
+ }
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ size_t total_rowsets = tmp_rowsets_meta.size();
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ for (size_t i = 0; i < total_rowsets; i++) {
+ uint64_t tablet_id = tmp_rowsets_meta[i].second.tablet_id();
+ if (!tablet_idx_values[i].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " tablet_id=" << tablet_id << " key=" << hex(tablet_idx_keys[i]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "malformed tablet index value tablet_id=" << tablet_id
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ VLOG_DEBUG << "tablet_id:" << tablet_id
+ << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ }
+
+ tablet_idx_keys.clear();
+ tablet_idx_values.clear();
+
+ // {table/partition} -> version
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
+ }
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ size_t total_versions = version_keys.size();
+ for (size_t i = 0; i < total_versions; i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+ version_keys.clear();
+ version_values.clear();
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
+ continue;
+ }
+
+ std::vector<std::pair<std::string, std::string>> rowsets;
+ std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
+ rowsets.reserve(tmp_rowsets_meta.size());
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions[ver_key] == 0) [[unlikely]] {
+ // it is impossible.
+ code = MetaServiceCode::UNDEFINED_ERR;
+ ss << "failed to get partition version key, the target version not exists in "
+ "new_versions."
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(ERROR) << msg;
+ return;
+ }
+
+ // Update rowset version
+ int64_t new_version = new_versions[ver_key];
+ i.set_start_version(new_version);
+ i.set_end_version(new_version);
+
+ std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
+ std::string val;
+ if (!i.SerializeToString(&val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ rowsets.emplace_back(std::move(key), std::move(val));
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tablet_id];
+ stats.data_size += i.data_disk_size();
+ stats.num_rows += i.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += i.num_segments();
+ } // for tmp_rowsets_meta
+
+ // process mow table, check lock and remove pending key
+ std::vector<std::string> lock_keys;
+ lock_keys.reserve(request->mow_table_ids().size());
+ for (auto table_id : request->mow_table_ids()) {
+ lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
+ }
+ std::vector<std::optional<std::string>> lock_values;
+ err = txn->batch_get(&lock_values, lock_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
+ << " err=" << err;
+ msg = ss.str();
+ code = cast_as<ErrCategory::READ>(err);
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ size_t total_locks = lock_keys.size();
+ for (size_t i = 0; i < total_locks; i++) {
+ int64_t table_id = request->mow_table_ids(i);
+ // When the key does not exist, it means the lock has been acquired
+ // by another transaction and successfully committed.
+ if (!lock_values[i].has_value()) {
+ ss << "get delete bitmap update lock info, lock is expired"
+ << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
+ code = MetaServiceCode::LOCK_EXPIRED;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ DeleteBitmapUpdateLockPB lock_info;
+ if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "failed to parse DeleteBitmapUpdateLockPB";
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ if (lock_info.lock_id() != request->txn_id()) {
+ msg = "lock is expired";
+ code = MetaServiceCode::LOCK_EXPIRED;
+ return;
+ }
+ txn->remove(lock_keys[i]);
+ LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
+ << " txn_id=" << txn_id;
+
+ for (auto tablet_id : table_id_tablet_ids[table_id]) {
+ std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
+ txn->remove(pending_key);
+ LOG(INFO) << "xxx remove delete bitmap pending key, pending_key="
+ << hex(pending_key) << " txn_id=" << txn_id;
+ }
+ }
+ lock_keys.clear();
+ lock_values.clear();
+
+ // Save rowset meta
+ for (auto& i : rowsets) {
+ size_t rowset_size = i.first.size() + i.second.size();
+ txn->put(i.first, i.second);
+ LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_size;
+ }
+
+ // Save versions
+ int64_t version_update_time_ms =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ response->set_version_update_time_ms(version_update_time_ms);
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_update_time_ms(version_update_time_ms);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(i.first, ver_val);
+ LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
+ << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+
+ std::string_view ver_key = i.first;
+ ver_key.remove_prefix(1); // Remove key space
+ // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
+ int ret = decode_key(&ver_key, &out);
+ if (ret != 0) [[unlikely]] {
+ // decode version key error means this is something wrong,
+ // we can not continue this txn
+ LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = "decode version key error";
+ return;
+ }
+
+ int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
+ int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
+ VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+
+ response->add_table_ids(table_id);
+ response->add_partition_ids(partition_id);
+ response->add_versions(i.second);
+ }
+
+ // Save table versions
+ for (auto& i : table_id_tablet_ids) {
+ std::string ver_key = table_version_key({instance_id, db_id, i.first});
+ txn->atomic_add(ver_key, 1);
+ LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key)
+ << " txn_id=" << txn_id;
+ }
+
+ LOG(INFO) << " before update txn_info=" << txn_info.ShortDebugString();
+
+ // Update txn_info
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ // Update stats of affected tablet
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+ // Remove tmp rowset meta
+ for (auto& [k, _] : tmp_rowsets_meta) {
+ txn->remove(k);
+ LOG(INFO) << "xxx remove tmp_rowset_key=" << hex(k) << " txn_id=" << txn_id;
+ }
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ recycle_pb.set_creation_time(commit_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(recycle_key, recycle_val);
+
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
+ }
+
+ LOG(INFO) << "xxx commit_txn put recycle_key key=" << hex(recycle_key)
+ << " txn_id=" << txn_id;
+ LOG(INFO) << "commit_txn put_size=" << txn->put_bytes()
Review Comment:
do not change what you don't modify
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
Review Comment:
we need to check `if (!tablet_idx_pb.has_db_id())` before copying so many keys.
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
Review Comment:
why not submit multiple pending txn_ids?
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
Review Comment:
`tablet_idx_keys` should be `sub_tablet_idx_keys`?
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
Review Comment:
LOG every key that is modified and its vaule too:
db_id tablet_id txn_id. it is affordabale because number of tablets finite andn this process is convergent.
and LOG some summary of these update: how many tablet_idx has been updated, txn_id.
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
Review Comment:
keep `last_pending_txn_id` is enough, need_advance_last_txn is redundant.
and it seems that there may be more than one `last_pending_txn_id`s, becase each partition may have a pending txn attached to it.
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
Review Comment:
add comment what the KV stands for
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
Review Comment:
add a summary here how long do we take before we reach here (there may be mutiple `task->wait()`s which may take a lot of time.)
LOG how may txn "advanced" and how long it takes + txn_id.
also make it a bvar to stats
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
Review Comment:
LOG txn id
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
msg = ss.str();
return;
}
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
- std::string_view ver_key = i.first;
- ver_key.remove_prefix(1); // Remove key space
- // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- int ret = decode_key(&ver_key, &out);
- if (ret != 0) [[unlikely]] {
- // decode version key error means this is something wrong,
- // we can not continue this txn
- LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = "decode version key error";
- return;
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
}
- int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
- int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
- VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+ // save versions for partition
+ int64_t version_update_time_ms =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ response->set_version_update_time_ms(version_update_time_ms);
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_txn_id(txn_id);
+ version_pb.set_update_time_ms(version_update_time_ms);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- response->add_table_ids(table_id);
- response->add_partition_ids(partition_id);
- response->add_versions(i.second);
- }
+ txn->put(i.first, ver_val);
+ LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
Review Comment:
ditto
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
msg = ss.str();
return;
}
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
Review Comment:
dont log "xxx" any more...
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
Review Comment:
LOG right after parsing it from string at line 1601
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
Review Comment:
don't log "xxx"
##########
cloud/src/meta-service/txn_lazy_committer.h:
##########
Review Comment:
add comment for all structures and public functions
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(recycle_key, recycle_val);
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+ }
+}
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
+ std::stringstream ss;
+ int retry_times = 0;
+ do {
+ LOG(INFO) << "lazy task commit txn_id=" << txn_id_ << " retry_times=" << retry_times;
+ do {
+ code_ = MetaServiceCode::OK;
+ msg_.clear();
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id_, txn_id_, txn_kv_, code_, msg_, &db_id, &tmp_rowset_metas);
+ if (code_ != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id_ << " code=" << code_;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id_
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id_;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
+ partition_to_tmp_rowset_metas;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].emplace_back();
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().first =
+ tmp_rowset_key;
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().second =
+ tmp_rowset_pb;
+ }
+
+ // tablet_id -> TabletIndexPB
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ for (auto& [partition_id, tmp_rowset_metas] : partition_to_tmp_rowset_metas) {
+ for (size_t i = 0; i < tmp_rowset_metas.size();
+ i += config::txn_lazy_max_rowsets_per_batch) {
+ size_t end =
+ (i + config::txn_lazy_max_rowsets_per_batch) > tmp_rowset_metas.size()
+ ? tmp_rowset_metas.size()
+ : i + config::txn_lazy_max_rowsets_per_batch;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>
+ sub_partition_tmp_rowset_metas(tmp_rowset_metas.begin() + i,
+ tmp_rowset_metas.begin() + end);
+ convert_tmp_rowsets(instance_id_, txn_id_, txn_kv_, code_, msg_, db_id,
+ sub_partition_tmp_rowset_metas, tablet_ids);
+ if (code_ != MetaServiceCode::OK) break;
+ }
+ if (code_ != MetaServiceCode::OK) break;
+
+ DCHECK(tmp_rowset_metas.size() > 0);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code_ = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id_ << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+
+ int64_t table_id = -1;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ if (table_id <= 0) {
+ table_id = tablet_ids[tmp_rowset_pb.tablet_id()].table_id();
+ }
+ txn->remove(tmp_rowset_key);
+ }
+
+ DCHECK(table_id > 0);
+ DCHECK(partition_id > 0);
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id_, db_id, table_id, partition_id});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code_ = err == TxnErrorCode::TXN_KEY_NOT_FOUND
+ ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id_
+ << " key=" << hex(ver_key) << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id_
+ << " key=" << hex(ver_key);
+ msg_ = ss.str();
+ break;
+ }
+
+ if (version_pb.has_txn_id() && version_pb.txn_id() == txn_id_) {
+ version_pb.clear_txn_id();
+ ver_val.clear();
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id_;
+ msg_ = ss.str();
+ return;
+ }
+ txn->put(ver_key, ver_val);
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code_ = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id_ << " err=" << err;
+ msg_ = ss.str();
+ break;
+ }
+ }
+ }
+ make_committed_txn_visible(instance_id_, db_id, txn_id_, txn_kv_, code_, msg_);
+ } while (false);
+ } while (code_ == MetaServiceCode::KV_TXN_CONFLICT &&
+ retry_times++ < config::txn_store_retry_times);
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ this->finished_ = true;
+ }
+ this->cond_.notify_all();
+}
+
+std::pair<MetaServiceCode, std::string> TxnLazyCommitTask::wait() {
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ cond_.wait(lock, [this]() { return this->finished_ == true; });
Review Comment:
wait with timeout with a loop, and LOG what is going on, how long does it take while waiting to be done.
and we may need to count how many `wait()` has been called for this pending txn.
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(recycle_key, recycle_val);
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+ }
+}
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
+ std::stringstream ss;
+ int retry_times = 0;
+ do {
+ LOG(INFO) << "lazy task commit txn_id=" << txn_id_ << " retry_times=" << retry_times;
+ do {
+ code_ = MetaServiceCode::OK;
+ msg_.clear();
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id_, txn_id_, txn_kv_, code_, msg_, &db_id, &tmp_rowset_metas);
+ if (code_ != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id_ << " code=" << code_;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id_
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id_;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
+ partition_to_tmp_rowset_metas;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].emplace_back();
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().first =
+ tmp_rowset_key;
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().second =
+ tmp_rowset_pb;
+ }
+
+ // tablet_id -> TabletIndexPB
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ for (auto& [partition_id, tmp_rowset_metas] : partition_to_tmp_rowset_metas) {
+ for (size_t i = 0; i < tmp_rowset_metas.size();
+ i += config::txn_lazy_max_rowsets_per_batch) {
+ size_t end =
+ (i + config::txn_lazy_max_rowsets_per_batch) > tmp_rowset_metas.size()
+ ? tmp_rowset_metas.size()
+ : i + config::txn_lazy_max_rowsets_per_batch;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>
+ sub_partition_tmp_rowset_metas(tmp_rowset_metas.begin() + i,
+ tmp_rowset_metas.begin() + end);
+ convert_tmp_rowsets(instance_id_, txn_id_, txn_kv_, code_, msg_, db_id,
+ sub_partition_tmp_rowset_metas, tablet_ids);
+ if (code_ != MetaServiceCode::OK) break;
+ }
+ if (code_ != MetaServiceCode::OK) break;
+
+ DCHECK(tmp_rowset_metas.size() > 0);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code_ = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id_ << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+
+ int64_t table_id = -1;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ if (table_id <= 0) {
+ table_id = tablet_ids[tmp_rowset_pb.tablet_id()].table_id();
+ }
+ txn->remove(tmp_rowset_key);
+ }
+
+ DCHECK(table_id > 0);
+ DCHECK(partition_id > 0);
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id_, db_id, table_id, partition_id});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code_ = err == TxnErrorCode::TXN_KEY_NOT_FOUND
+ ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id_
+ << " key=" << hex(ver_key) << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id_
+ << " key=" << hex(ver_key);
+ msg_ = ss.str();
+ break;
+ }
+
+ if (version_pb.has_txn_id() && version_pb.txn_id() == txn_id_) {
+ version_pb.clear_txn_id();
+ ver_val.clear();
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id_;
+ msg_ = ss.str();
+ return;
+ }
+ txn->put(ver_key, ver_val);
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code_ = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id_ << " err=" << err;
+ msg_ = ss.str();
+ break;
+ }
+ }
+ }
+ make_committed_txn_visible(instance_id_, db_id, txn_id_, txn_kv_, code_, msg_);
+ } while (false);
+ } while (code_ == MetaServiceCode::KV_TXN_CONFLICT &&
+ retry_times++ < config::txn_store_retry_times);
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ this->finished_ = true;
Review Comment:
do we count it as a finish even if `retry_times > config::txn_store_retry_times`? line 413 may be false and make it reach here.
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
Review Comment:
add UT for this function to do some boundary tests of the "for loop"
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
msg = ss.str();
return;
}
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
- std::string_view ver_key = i.first;
- ver_key.remove_prefix(1); // Remove key space
- // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- int ret = decode_key(&ver_key, &out);
- if (ret != 0) [[unlikely]] {
- // decode version key error means this is something wrong,
- // we can not continue this txn
- LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = "decode version key error";
- return;
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
}
- int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
- int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
- VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+ // save versions for partition
+ int64_t version_update_time_ms =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ response->set_version_update_time_ms(version_update_time_ms);
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_txn_id(txn_id);
+ version_pb.set_update_time_ms(version_update_time_ms);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- response->add_table_ids(table_id);
- response->add_partition_ids(partition_id);
- response->add_versions(i.second);
- }
+ txn->put(i.first, ver_val);
+ LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
+ << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+
+ std::string_view ver_key = i.first;
+ ver_key.remove_prefix(1); // Remove key space
+ // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
+ int ret = decode_key(&ver_key, &out);
+ if (ret != 0) [[unlikely]] {
+ // decode version key error means this is something wrong,
+ // we can not continue this txn
+ LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = "decode version key error";
+ return;
+ }
- // Save table versions
- for (auto& i : table_id_tablet_ids) {
- std::string ver_key = table_version_key({instance_id, db_id, i.first});
- txn->atomic_add(ver_key, 1);
- LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key) << " txn_id=" << txn_id;
- }
+ int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
+ int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
+ VLOG_DEBUG << "txn_id=" << txn_id << " table_id=" << table_id
+ << " partition_id=" << partition_id << " version=" << i.second;
- LOG(INFO) << " before update txn_info=" << txn_info.ShortDebugString();
+ response->add_table_ids(table_id);
+ response->add_partition_ids(partition_id);
+ response->add_versions(i.second);
+ }
- // Update txn_info
- txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+ // process mow table, check lock and remove pending key
+ std::vector<std::string> lock_keys;
+ lock_keys.reserve(request->mow_table_ids().size());
+ for (auto table_id : request->mow_table_ids()) {
+ lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
+ }
+ std::vector<std::optional<std::string>> lock_values;
+ err = txn->batch_get(&lock_values, lock_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
+ << " err=" << err;
+ msg = ss.str();
+ code = cast_as<ErrCategory::READ>(err);
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- auto now_time = system_clock::now();
- uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
- if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
- LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
- << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
- return;
- }
- txn_info.set_commit_time(commit_time);
- txn_info.set_finish_time(commit_time);
- if (request->has_commit_attachment()) {
- txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
- }
- LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
- info_val.clear();
- if (!txn_info.SerializeToString(&info_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(info_key, info_val);
- LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+ for (size_t i = 0; i < lock_keys.size(); i++) {
+ int64_t table_id = request->mow_table_ids(i);
+ // When the key does not exist, it means the lock has been acquired
+ // by another transaction and successfully committed.
+ if (!lock_values[i].has_value()) {
+ ss << "get delete bitmap update lock info, lock is expired"
+ << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
+ code = MetaServiceCode::LOCK_EXPIRED;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
- // Update stats of affected tablet
- for (auto& [tablet_id, stats] : tablet_stats) {
- DCHECK(tablet_ids.count(tablet_id));
- auto& tablet_idx = tablet_ids[tablet_id];
- StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
- tablet_idx.partition_id(), tablet_id};
- update_tablet_stats(info, stats, txn, code, msg);
- if (code != MetaServiceCode::OK) return;
- }
- // Remove tmp rowset meta
- for (auto& [k, _] : tmp_rowsets_meta) {
- txn->remove(k);
- LOG(INFO) << "xxx remove tmp_rowset_key=" << hex(k) << " txn_id=" << txn_id;
- }
+ DeleteBitmapUpdateLockPB lock_info;
+ if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ msg = "failed to parse DeleteBitmapUpdateLockPB";
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+ if (lock_info.lock_id() != request->txn_id()) {
+ msg = "lock is expired";
+ code = MetaServiceCode::LOCK_EXPIRED;
+ return;
+ }
+ txn->remove(lock_keys[i]);
+ LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
+ << " txn_id=" << txn_id;
- const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
- LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
- txn->remove(running_key);
+ for (auto tablet_id : table_id_tablet_ids[table_id]) {
+ std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
+ txn->remove(pending_key);
+ LOG(INFO) << "xxx remove delete bitmap pending key, pending_key="
+ << hex(pending_key) << " txn_id=" << txn_id;
+ }
+ }
+ lock_keys.clear();
+ lock_values.clear();
- std::string recycle_val;
- std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
- RecycleTxnPB recycle_pb;
- recycle_pb.set_creation_time(commit_time);
- recycle_pb.set_label(txn_info.label());
+ // Save table versions
+ for (auto& i : table_id_tablet_ids) {
+ std::string ver_key = table_version_key({instance_id, db_id, i.first});
+ txn->atomic_add(ver_key, 1);
+ LOG(INFO) << "xxx atomic add table_version_key=" << hex(ver_key)
+ << " txn_id=" << txn_id;
+ }
- if (!recycle_pb.SerializeToString(&recycle_val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
- msg = ss.str();
- return;
- }
- txn->put(recycle_key, recycle_val);
+ LOG(INFO) << "commit_txn_eventually put_size=" << txn->put_bytes()
+ << " del_size=" << txn->delete_bytes() << " num_put_keys=" << txn->num_put_keys()
+ << " num_del_keys=" << txn->num_del_keys()
+ << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
- if (txn_info.load_job_source_type() ==
- LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
- put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
- }
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
- LOG(INFO) << "xxx commit_txn put recycle_key key=" << hex(recycle_key) << " txn_id=" << txn_id;
- LOG(INFO) << "commit_txn put_size=" << txn->put_bytes() << " del_size=" << txn->delete_bytes()
- << " num_put_keys=" << txn->num_put_keys() << " num_del_keys=" << txn->num_del_keys()
- << " txn_size=" << txn->approximate_bytes() << " txn_id=" << txn_id;
+ std::shared_ptr<TxnLazyCommitTask> task = txn_lazy_committer->submit(instance_id, txn_id);
+ std::pair<MetaServiceCode, std::string> ret = task->wait();
+ if (ret.first != MetaServiceCode::OK) {
+ LOG(WARNING) << "lazy commit txn failed txn_id=" << txn_id << " code=" << ret.first
+ << "msg=" << ret.second;
+ }
- // Finally we are done...
- err = txn->commit();
- if (err != TxnErrorCode::TXN_OK) {
- if ((err == TxnErrorCode::TXN_VALUE_TOO_LARGE ||
- err == TxnErrorCode::TXN_BYTES_TOO_LARGE) &&
- !tmp_rowsets_meta.empty()) {
- size_t max_size = 0, max_idx = 0, max_num_segments = 0,
- min_num_segments = std::numeric_limits<size_t>::max(), avg_num_segments = 0;
- for (size_t i = 0; i < tmp_rowsets_meta.size(); i++) {
- auto& [k, v] = tmp_rowsets_meta[i];
- if (v.ByteSizeLong() > max_size) {
- max_size = v.ByteSizeLong();
- max_idx = i;
- }
- if (v.num_segments() > max_num_segments) {
- max_num_segments = v.num_segments();
- }
- if (v.num_segments() < min_num_segments) {
- min_num_segments = v.num_segments();
- }
- avg_num_segments += v.num_segments();
- }
- if (!tmp_rowsets_meta.empty()) {
- avg_num_segments /= tmp_rowsets_meta.size();
- }
- LOG(WARNING) << "failed to commit kv txn"
- << ", err=" << err << ", txn_id=" << txn_id
- << ", total_rowsets=" << tmp_rowsets_meta.size()
- << ", avg_num_segments=" << avg_num_segments
- << ", min_num_segments=" << min_num_segments
- << ", max_num_segments=" << max_num_segments
- << ", largest_rowset_size=" << max_size
- << ", largest_rowset_key=" << hex(tmp_rowsets_meta[max_idx].first)
- << ", largest_rowset_value="
- << tmp_rowsets_meta[max_idx].second.ShortDebugString();
+ std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ // Accumulate affected rows
+ auto& stats = tablet_stats[i.tablet_id()];
+ stats.data_size += i.data_disk_size();
+ stats.num_rows += i.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += i.num_segments();
}
- code = cast_as<ErrCategory::COMMIT>(err);
- ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
- msg = ss.str();
- return;
- }
- // calculate table stats from tablets stats
- std::map<int64_t /*table_id*/, TableStats> table_stats;
- std::vector<int64_t> base_tablet_ids(request->base_tablet_ids().begin(),
- request->base_tablet_ids().end());
- calc_table_stats(tablet_ids, tablet_stats, table_stats, base_tablet_ids);
- for (const auto& pair : table_stats) {
- TableStatsPB* stats_pb = response->add_table_stats();
- auto table_id = pair.first;
- auto stats = pair.second;
- get_pb_from_tablestats(stats, stats_pb);
- stats_pb->set_table_id(table_id);
- VLOG_DEBUG << "Add TableStats to CommitTxnResponse. txn_id=" << txn_id
- << " table_id=" << table_id
- << " updated_row_count=" << stats_pb->updated_row_count();
- }
+ // calculate table stats from tablets stats
+ std::map<int64_t /*table_id*/, TableStats> table_stats;
+ std::vector<int64_t> base_tablet_ids(request->base_tablet_ids().begin(),
+ request->base_tablet_ids().end());
+ calc_table_stats(tablet_ids, tablet_stats, table_stats, base_tablet_ids);
+ for (const auto& pair : table_stats) {
+ TableStatsPB* stats_pb = response->add_table_stats();
+ auto table_id = pair.first;
+ auto stats = pair.second;
+ get_pb_from_tablestats(stats, stats_pb);
+ stats_pb->set_table_id(table_id);
+ VLOG_DEBUG << "Add TableStats to CommitTxnResponse. txn_id=" << txn_id
+ << " table_id=" << table_id
+ << " updated_row_count=" << stats_pb->updated_row_count();
+ }
- response->mutable_txn_info()->CopyFrom(txn_info);
-} // end commit_txn
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
Review Comment:
is it VISIBLE even if `task->wait()` failed?
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
Review Comment:
is it a unrecoverable error?
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(recycle_key, recycle_val);
Review Comment:
log
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
msg = ss.str();
return;
}
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
- std::string_view ver_key = i.first;
- ver_key.remove_prefix(1); // Remove key space
- // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- int ret = decode_key(&ver_key, &out);
- if (ret != 0) [[unlikely]] {
- // decode version key error means this is something wrong,
- // we can not continue this txn
- LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = "decode version key error";
- return;
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
}
- int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
- int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
- VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+ // save versions for partition
+ int64_t version_update_time_ms =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ response->set_version_update_time_ms(version_update_time_ms);
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_txn_id(txn_id);
+ version_pb.set_update_time_ms(version_update_time_ms);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
Review Comment:
key or partition id should be printed.
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(recycle_key, recycle_val);
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+ }
+}
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
+ std::stringstream ss;
+ int retry_times = 0;
+ do {
+ LOG(INFO) << "lazy task commit txn_id=" << txn_id_ << " retry_times=" << retry_times;
+ do {
+ code_ = MetaServiceCode::OK;
+ msg_.clear();
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id_, txn_id_, txn_kv_, code_, msg_, &db_id, &tmp_rowset_metas);
+ if (code_ != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id_ << " code=" << code_;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id_
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id_;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
Review Comment:
add comment for the map, what is `std::pair<std::string, doris::RowsetMetaCloudPB>`
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
Review Comment:
and it should be a snapshot GET, concurrent updating does not matter, otherwise the update procedure may no succeed if there are other reads on tablet_idx.
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(recycle_key, recycle_val);
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+ }
+}
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
+ std::stringstream ss;
+ int retry_times = 0;
+ do {
+ LOG(INFO) << "lazy task commit txn_id=" << txn_id_ << " retry_times=" << retry_times;
+ do {
+ code_ = MetaServiceCode::OK;
+ msg_.clear();
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id_, txn_id_, txn_kv_, code_, msg_, &db_id, &tmp_rowset_metas);
+ if (code_ != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id_ << " code=" << code_;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id_
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id_;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
+ partition_to_tmp_rowset_metas;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].emplace_back();
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().first =
+ tmp_rowset_key;
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().second =
+ tmp_rowset_pb;
+ }
+
+ // tablet_id -> TabletIndexPB
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ for (auto& [partition_id, tmp_rowset_metas] : partition_to_tmp_rowset_metas) {
+ for (size_t i = 0; i < tmp_rowset_metas.size();
+ i += config::txn_lazy_max_rowsets_per_batch) {
+ size_t end =
+ (i + config::txn_lazy_max_rowsets_per_batch) > tmp_rowset_metas.size()
+ ? tmp_rowset_metas.size()
+ : i + config::txn_lazy_max_rowsets_per_batch;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>
+ sub_partition_tmp_rowset_metas(tmp_rowset_metas.begin() + i,
+ tmp_rowset_metas.begin() + end);
+ convert_tmp_rowsets(instance_id_, txn_id_, txn_kv_, code_, msg_, db_id,
+ sub_partition_tmp_rowset_metas, tablet_ids);
+ if (code_ != MetaServiceCode::OK) break;
+ }
+ if (code_ != MetaServiceCode::OK) break;
+
+ DCHECK(tmp_rowset_metas.size() > 0);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code_ = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id_ << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+
+ int64_t table_id = -1;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ if (table_id <= 0) {
+ table_id = tablet_ids[tmp_rowset_pb.tablet_id()].table_id();
+ }
+ txn->remove(tmp_rowset_key);
Review Comment:
LOG every key removed.
##########
cloud/src/meta-service/meta_service_txn.cpp:
##########
@@ -974,353 +1361,476 @@ void commit_txn_immediately(
LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
return;
}
- if (!tablet_ids[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
+ if (!(*tablet_ids)[tablet_id].ParseFromString(tablet_idx_values[i].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
ss << "malformed tablet index value tablet_id=" << tablet_id << " txn_id=" << txn_id;
msg = ss.str();
LOG(WARNING) << msg;
return;
}
- table_id_tablet_ids[tablet_ids[tablet_id].table_id()].push_back(tablet_id);
+ if (!(*tablet_ids)[tablet_id].has_db_id()) {
+ *need_repair_tablet_idx = true;
+ }
+ (*table_id_tablet_ids)[(*tablet_ids)[tablet_id].table_id()].push_back(tablet_id);
VLOG_DEBUG << "tablet_id:" << tablet_id
- << " value:" << tablet_ids[tablet_id].ShortDebugString();
+ << " value:" << (*tablet_ids)[tablet_id].ShortDebugString();
}
tablet_idx_keys.clear();
tablet_idx_values.clear();
+}
- // {table/partition} -> version
- std::unordered_map<std::string, uint64_t> new_versions;
- std::vector<std::string> version_keys;
+void repair_tablet_index(
+ std::shared_ptr<TxnKv>& txn_kv, MetaServiceCode& code, std::string& msg,
+ const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ std::vector<std::string> tablet_idx_keys;
for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions.count(ver_key) == 0) {
- new_versions.insert({ver_key, 0});
- version_keys.push_back(std::move(ver_key));
- }
- }
- std::vector<std::optional<std::string>> version_values;
- err = txn->batch_get(&version_values, version_keys);
- if (err != TxnErrorCode::TXN_OK) {
- code = cast_as<ErrCategory::READ>(err);
- ss << "failed to get partition versions, err=" << err;
- msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
+ tablet_idx_keys.push_back(meta_tablet_idx_key({instance_id, i.tablet_id()}));
}
- size_t total_versions = version_keys.size();
- for (size_t i = 0; i < total_versions; i++) {
- int64_t version;
- if (version_values[i].has_value()) {
- VersionPB version_pb;
- if (!version_pb.ParseFromString(version_values[i].value())) {
+
+#define MAX_TABLET_INDEX_NUM 2048
+ for (size_t i = 0; i < tablet_idx_keys.size(); i += MAX_TABLET_INDEX_NUM) {
+ size_t end = (i + MAX_TABLET_INDEX_NUM) > tablet_idx_keys.size() ? tablet_idx_keys.size()
+ : i + MAX_TABLET_INDEX_NUM;
+ const std::vector<std::string> sub_tablet_idx_keys(tablet_idx_keys.begin() + i,
+ tablet_idx_keys.begin() + end);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::vector<std::optional<std::string>> tablet_idx_values;
+ // batch get snapshot is false
+ err = txn->batch_get(&tablet_idx_values, tablet_idx_keys,
+ Transaction::BatchGetOptions(false));
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet table index ids, err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
+ return;
+ }
+
+ for (size_t j = 0; j < sub_tablet_idx_keys.size(); j++) {
+ if (!tablet_idx_values[j].has_value()) [[unlikely]] {
+ // The value must existed
+ code = MetaServiceCode::KV_TXN_GET_ERR;
+ ss << "failed to get tablet table index ids, err=not found"
+ << " key=" << hex(tablet_idx_keys[j]);
+ msg = ss.str();
+ LOG(WARNING) << msg << " err=" << err << " txn_id=" << txn_id;
+ return;
+ }
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_values[j].value())) [[unlikely]] {
code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- ss << "failed to parse version pb txn_id=" << txn_id
- << " key=" << hex(version_keys[i]);
+ ss << "malformed tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- version = version_pb.version();
- } else {
- version = 1;
+
+ if (!tablet_idx_pb.has_db_id()) {
+ tablet_idx_pb.set_db_id(db_id);
+ std::string idx_val;
+ if (!tablet_idx_pb.SerializeToString(&idx_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize tablet index value key=" << hex(tablet_idx_keys[j])
+ << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ txn->put(sub_tablet_idx_keys[j], idx_val);
+ }
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ }
+}
+
+void commit_txn_eventually(
+ const CommitTxnRequest* request, CommitTxnResponse* response,
+ std::shared_ptr<TxnKv>& txn_kv, std::shared_ptr<TxnLazyCommitter>& txn_lazy_committer,
+ MetaServiceCode& code, std::string& msg, const std::string& instance_id, int64_t db_id,
+ const std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta) {
+ std::stringstream ss;
+ TxnErrorCode err = TxnErrorCode::TXN_OK;
+ int64_t txn_id = request->txn_id();
+ bool need_advance_last_txn = false;
+ int64_t last_pending_txn_id = 0;
+
+ do {
+ std::unique_ptr<Transaction> txn;
+ err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // tablet_id -> {table/index/partition}_id
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ // table_id -> tablets_ids
+ std::unordered_map<int64_t, std::vector<int64_t>> table_id_tablet_ids;
+ bool need_repair_tablet_idx = false;
+ get_tablet_indexes(instance_id, txn_id, tmp_rowsets_meta, txn, code, msg, &tablet_ids,
+ &table_id_tablet_ids, &need_repair_tablet_idx);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "get_tablet_indexes failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+
+ if (need_repair_tablet_idx) {
+ txn.reset();
+ repair_tablet_index(txn_kv, code, msg, instance_id, db_id, txn_id, tmp_rowsets_meta);
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "repair_tablet_index failed, txn_id=" << txn_id << " code=" << code;
+ return;
+ }
+ continue;
+ }
+
+ std::unordered_map<std::string, uint64_t> new_versions;
+ std::vector<std::string> version_keys;
+ for (auto& [_, i] : tmp_rowsets_meta) {
+ int64_t tablet_id = i.tablet_id();
+ int64_t table_id = tablet_ids[tablet_id].table_id();
+ int64_t partition_id = i.partition_id();
+ std::string ver_key =
+ partition_version_key({instance_id, db_id, table_id, partition_id});
+ if (new_versions.count(ver_key) == 0) {
+ new_versions.insert({ver_key, 0});
+ version_keys.push_back(std::move(ver_key));
+ }
}
- new_versions[version_keys[i]] = version + 1;
- }
- version_keys.clear();
- version_values.clear();
- std::vector<std::pair<std::string, std::string>> rowsets;
- std::unordered_map<int64_t, TabletStats> tablet_stats; // tablet_id -> stats
- rowsets.reserve(tmp_rowsets_meta.size());
- for (auto& [_, i] : tmp_rowsets_meta) {
- int64_t tablet_id = i.tablet_id();
- int64_t table_id = tablet_ids[tablet_id].table_id();
- int64_t partition_id = i.partition_id();
- std::string ver_key = partition_version_key({instance_id, db_id, table_id, partition_id});
- if (new_versions[ver_key] == 0) [[unlikely]] {
- // it is impossible.
- code = MetaServiceCode::UNDEFINED_ERR;
- ss << "failed to get partition version key, the target version not exists in "
- "new_versions."
- << " txn_id=" << txn_id;
+ std::vector<std::optional<std::string>> version_values;
+ err = txn->batch_get(&version_values, version_keys);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partition versions, err=" << err;
msg = ss.str();
- LOG(ERROR) << msg;
+ LOG(WARNING) << msg << " txn_id=" << txn_id;
return;
}
- // Update rowset version
- int64_t new_version = new_versions[ver_key];
- i.set_start_version(new_version);
- i.set_end_version(new_version);
+ for (size_t i = 0; i < version_keys.size(); i++) {
+ int64_t version;
+ if (version_values[i].has_value()) {
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(version_values[i].value())) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id
+ << " key=" << hex(version_keys[i]);
+ msg = ss.str();
+ return;
+ }
+ if (version_pb.has_txn_id()) {
+ need_advance_last_txn = true;
+ last_pending_txn_id = version_pb.txn_id();
+ break;
+ }
+ version = version_pb.version();
+ } else {
+ version = 1;
+ }
+ new_versions[version_keys[i]] = version + 1;
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ }
+
+ if (need_advance_last_txn) {
+ txn.reset();
+ DCHECK(last_pending_txn_id > 0);
+ std::shared_ptr<TxnLazyCommitTask> task =
+ txn_lazy_committer->submit(instance_id, last_pending_txn_id);
+
+ std::tie(code, msg) = task->wait();
+ need_advance_last_txn = false;
+ last_pending_txn_id = 0;
+ if (code != MetaServiceCode::OK) {
+ LOG(WARNING) << "advance_last_txn failed last_txn=" << last_pending_txn_id
+ << " code=" << code << "msg=" << msg;
+ return;
+ }
- std::string key = meta_rowset_key({instance_id, tablet_id, i.end_version()});
- std::string val;
- if (!i.SerializeToString(&val)) {
- code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize rowset_meta, txn_id=" << txn_id;
+ // there maybe concurrent commit_txn_eventually, so we need continue to make sure
+ // partition versionPB has no txn_id
+ continue;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id
+ << " err=" << err;
msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- rowsets.emplace_back(std::move(key), std::move(val));
-
- // Accumulate affected rows
- auto& stats = tablet_stats[tablet_id];
- stats.data_size += i.data_disk_size();
- stats.num_rows += i.num_rows();
- ++stats.num_rowsets;
- stats.num_segs += i.num_segments();
- } // for tmp_rowsets_meta
- // process mow table, check lock and remove pending key
- std::vector<std::string> lock_keys;
- lock_keys.reserve(request->mow_table_ids().size());
- for (auto table_id : request->mow_table_ids()) {
- lock_keys.push_back(meta_delete_bitmap_update_lock_key({instance_id, table_id, -1}));
- }
- std::vector<std::optional<std::string>> lock_values;
- err = txn->batch_get(&lock_values, lock_keys);
- if (err != TxnErrorCode::TXN_OK) {
- ss << "failed to get delete bitmap update lock key info, instance_id=" << instance_id
- << " err=" << err;
- msg = ss.str();
- code = cast_as<ErrCategory::READ>(err);
- LOG(WARNING) << msg << " txn_id=" << txn_id;
- return;
- }
- size_t total_locks = lock_keys.size();
- for (size_t i = 0; i < total_locks; i++) {
- int64_t table_id = request->mow_table_ids(i);
- // When the key does not exist, it means the lock has been acquired
- // by another transaction and successfully committed.
- if (!lock_values[i].has_value()) {
- ss << "get delete bitmap update lock info, lock is expired"
- << " table_id=" << table_id << " key=" << hex(lock_keys[i]);
- code = MetaServiceCode::LOCK_EXPIRED;
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, db_id=" << db_id << " txn_id=" << txn_id;
msg = ss.str();
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ LOG(WARNING) << msg;
return;
}
- DeleteBitmapUpdateLockPB lock_info;
- if (!lock_info.ParseFromString(lock_values[i].value())) [[unlikely]] {
- code = MetaServiceCode::PROTOBUF_PARSE_ERR;
- msg = "failed to parse DeleteBitmapUpdateLockPB";
- LOG(WARNING) << msg << " txn_id=" << txn_id;
+ DCHECK(txn_info.txn_id() == txn_id);
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_ABORTED) {
+ code = MetaServiceCode::TXN_ALREADY_ABORTED;
+ ss << "transaction is already aborted: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
return;
}
- if (lock_info.lock_id() != request->txn_id()) {
- msg = "lock is expired";
- code = MetaServiceCode::LOCK_EXPIRED;
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE) {
+ if (request->has_is_2pc() && request->is_2pc()) {
+ code = MetaServiceCode::TXN_ALREADY_VISIBLE;
+ ss << "transaction [" << txn_id << "] is already visible, not pre-committed.";
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
+ return;
+ }
+ code = MetaServiceCode::OK;
+ ss << "transaction is already visible: db_id=" << db_id << " txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(INFO) << msg;
+ response->mutable_txn_info()->CopyFrom(txn_info);
return;
}
- txn->remove(lock_keys[i]);
- LOG(INFO) << "xxx remove delete bitmap lock, lock_key=" << hex(lock_keys[i])
- << " txn_id=" << txn_id;
- for (auto tablet_id : table_id_tablet_ids[table_id]) {
- std::string pending_key = meta_pending_delete_bitmap_key({instance_id, tablet_id});
- txn->remove(pending_key);
- LOG(INFO) << "xxx remove delete bitmap pending key, pending_key=" << hex(pending_key)
- << " txn_id=" << txn_id;
+ if (request->has_is_2pc() && request->is_2pc() &&
+ txn_info.status() == TxnStatusPB::TXN_STATUS_PREPARED) {
+ code = MetaServiceCode::TXN_INVALID_STATUS;
+ ss << "transaction is prepare, not pre-committed: db_id=" << db_id << " txn_id"
+ << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
}
- }
- lock_keys.clear();
- lock_values.clear();
+ LOG(INFO) << "txn_id=" << txn_id << " txn_info=" << txn_info.ShortDebugString();
- // Save rowset meta
- for (auto& i : rowsets) {
- size_t rowset_size = i.first.size() + i.second.size();
- txn->put(i.first, i.second);
- LOG(INFO) << "xxx put rowset_key=" << hex(i.first) << " txn_id=" << txn_id
- << " rowset_size=" << rowset_size;
- }
+ auto now_time = system_clock::now();
+ uint64_t commit_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ if ((txn_info.prepare_time() + txn_info.timeout_ms()) < commit_time) {
+ code = MetaServiceCode::UNDEFINED_ERR;
+ msg = fmt::format("txn is expired, not allow to commit txn_id={}", txn_id);
+ LOG(INFO) << msg << " prepare_time=" << txn_info.prepare_time()
+ << " timeout_ms=" << txn_info.timeout_ms() << " commit_time=" << commit_time;
+ return;
+ }
+ txn_info.set_commit_time(commit_time);
+ txn_info.set_finish_time(commit_time);
+ if (request->has_commit_attachment()) {
+ txn_info.mutable_commit_attachment()->CopyFrom(request->commit_attachment());
+ }
+ DCHECK(txn_info.status() != TxnStatusPB::TXN_STATUS_COMMITTED);
+ // lazy commit set status TXN_STATUS_COMMITTED not TXN_STATUS_VISIBLE !!!
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_COMMITTED);
- // Save versions
- int64_t version_update_time_ms =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
- response->set_version_update_time_ms(version_update_time_ms);
- for (auto& i : new_versions) {
- std::string ver_val;
- VersionPB version_pb;
- version_pb.set_version(i.second);
- version_pb.set_update_time_ms(version_update_time_ms);
- if (!version_pb.SerializeToString(&ver_val)) {
+ LOG(INFO) << "after update txn_info=" << txn_info.ShortDebugString();
+ info_val.clear();
+ if (!txn_info.SerializeToString(&info_val)) {
code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
- ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
msg = ss.str();
return;
}
- txn->put(i.first, ver_val);
- LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
- << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
- std::string_view ver_key = i.first;
- ver_key.remove_prefix(1); // Remove key space
- // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
- std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
- int ret = decode_key(&ver_key, &out);
- if (ret != 0) [[unlikely]] {
- // decode version key error means this is something wrong,
- // we can not continue this txn
- LOG(WARNING) << "failed to decode key, ret=" << ret << " key=" << hex(ver_key);
- code = MetaServiceCode::UNDEFINED_ERR;
- msg = "decode version key error";
- return;
+ if (txn_info.load_job_source_type() ==
+ LoadJobSourceTypePB::LOAD_JOB_SRC_TYPE_ROUTINE_LOAD_TASK) {
+ put_routine_load_progress(code, msg, instance_id, request, txn.get(), db_id);
}
- int64_t table_id = std::get<int64_t>(std::get<0>(out[4]));
- int64_t partition_id = std::get<int64_t>(std::get<0>(out[5]));
- VLOG_DEBUG << " table_id=" << table_id << " partition_id=" << partition_id;
+ // save versions for partition
+ int64_t version_update_time_ms =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+ response->set_version_update_time_ms(version_update_time_ms);
+ for (auto& i : new_versions) {
+ std::string ver_val;
+ VersionPB version_pb;
+ version_pb.set_version(i.second);
+ version_pb.set_txn_id(txn_id);
+ version_pb.set_update_time_ms(version_update_time_ms);
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
- response->add_table_ids(table_id);
- response->add_partition_ids(partition_id);
- response->add_versions(i.second);
- }
+ txn->put(i.first, ver_val);
+ LOG(INFO) << "xxx put partition_version_key=" << hex(i.first) << " version:" << i.second
+ << " txn_id=" << txn_id << " update_time=" << version_update_time_ms;
+
+ std::string_view ver_key = i.first;
+ ver_key.remove_prefix(1); // Remove key space
+ // PartitionVersionKeyInfo {instance_id, db_id, table_id, partition_id}
+ std::vector<std::tuple<std::variant<int64_t, std::string>, int, int>> out;
+ int ret = decode_key(&ver_key, &out);
Review Comment:
is this a redundant check?
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(recycle_key, recycle_val);
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+ }
+}
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
+ std::stringstream ss;
+ int retry_times = 0;
+ do {
+ LOG(INFO) << "lazy task commit txn_id=" << txn_id_ << " retry_times=" << retry_times;
+ do {
+ code_ = MetaServiceCode::OK;
+ msg_.clear();
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id_, txn_id_, txn_kv_, code_, msg_, &db_id, &tmp_rowset_metas);
+ if (code_ != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id_ << " code=" << code_;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id_
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
Review Comment:
how come `tmp_rowset_metas.size() == 0` may exist?
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ DCHECK(version_pb.has_txn_id());
+ DCHECK(version_pb.txn_id() == txn_id);
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+
+ std::string rowset_key =
+ meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version_pb.version()});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version_pb.version());
+ tmp_rowset_pb.set_end_version(version_pb.version());
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "xxx put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "xxx put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "xxx remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(recycle_key, recycle_val);
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+ }
+}
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
+ std::stringstream ss;
+ int retry_times = 0;
+ do {
+ LOG(INFO) << "lazy task commit txn_id=" << txn_id_ << " retry_times=" << retry_times;
+ do {
+ code_ = MetaServiceCode::OK;
+ msg_.clear();
+ int64_t db_id;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>> tmp_rowset_metas;
+ scan_tmp_rowset(instance_id_, txn_id_, txn_kv_, code_, msg_, &db_id, &tmp_rowset_metas);
+ if (code_ != MetaServiceCode::OK) {
+ LOG(WARNING) << "scan_tmp_rowset failed, txn_id=" << txn_id_ << " code=" << code_;
+ break;
+ }
+
+ VLOG_DEBUG << "txn_id=" << txn_id_
+ << " tmp_rowset_metas.size()=" << tmp_rowset_metas.size();
+ if (tmp_rowset_metas.size() == 0) {
+ LOG(INFO) << "empty tmp_rowset_metas, txn_id=" << txn_id_;
+ }
+
+ // <partition_id, tmp_rowsets>
+ std::unordered_map<int64_t,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>>
+ partition_to_tmp_rowset_metas;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].emplace_back();
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().first =
+ tmp_rowset_key;
+ partition_to_tmp_rowset_metas[tmp_rowset_pb.partition_id()].back().second =
+ tmp_rowset_pb;
+ }
+
+ // tablet_id -> TabletIndexPB
+ std::unordered_map<int64_t, TabletIndexPB> tablet_ids;
+ for (auto& [partition_id, tmp_rowset_metas] : partition_to_tmp_rowset_metas) {
+ for (size_t i = 0; i < tmp_rowset_metas.size();
+ i += config::txn_lazy_max_rowsets_per_batch) {
+ size_t end =
+ (i + config::txn_lazy_max_rowsets_per_batch) > tmp_rowset_metas.size()
+ ? tmp_rowset_metas.size()
+ : i + config::txn_lazy_max_rowsets_per_batch;
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>
+ sub_partition_tmp_rowset_metas(tmp_rowset_metas.begin() + i,
+ tmp_rowset_metas.begin() + end);
+ convert_tmp_rowsets(instance_id_, txn_id_, txn_kv_, code_, msg_, db_id,
+ sub_partition_tmp_rowset_metas, tablet_ids);
+ if (code_ != MetaServiceCode::OK) break;
+ }
+ if (code_ != MetaServiceCode::OK) break;
+
+ DCHECK(tmp_rowset_metas.size() > 0);
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv_->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code_ = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id_ << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+
+ int64_t table_id = -1;
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowset_metas) {
+ if (table_id <= 0) {
+ table_id = tablet_ids[tmp_rowset_pb.tablet_id()].table_id();
+ }
+ txn->remove(tmp_rowset_key);
+ }
+
+ DCHECK(table_id > 0);
+ DCHECK(partition_id > 0);
+
+ std::string ver_val;
+ std::string ver_key =
+ partition_version_key({instance_id_, db_id, table_id, partition_id});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code_ = err == TxnErrorCode::TXN_KEY_NOT_FOUND
+ ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id_
+ << " key=" << hex(ver_key) << " err=" << err;
+ msg_ = ss.str();
+ LOG(WARNING) << msg_;
+ break;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id_
+ << " key=" << hex(ver_key);
+ msg_ = ss.str();
+ break;
+ }
+
+ if (version_pb.has_txn_id() && version_pb.txn_id() == txn_id_) {
+ version_pb.clear_txn_id();
+ ver_val.clear();
+ if (!version_pb.SerializeToString(&ver_val)) {
+ code_ = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize version_pb when saving, txn_id=" << txn_id_;
+ msg_ = ss.str();
+ return;
+ }
+ txn->put(ver_key, ver_val);
Review Comment:
log every key put
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2312250476
<details>
<summary>TPC-DS: <b>Total hot run time: 192630 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit fb825b12499087f8dea29592d393d5582d3623c3, data reload: false
query1 1267 889 893 889
query2 6247 1929 1946 1929
query3 10625 3993 3895 3895
query4 60205 27074 23094 23094
query5 5296 508 507 507
query6 412 170 168 168
query7 5763 294 299 294
query8 296 222 227 222
query9 8845 2501 2478 2478
query10 500 280 273 273
query11 15821 15065 15283 15065
query12 168 105 108 105
query13 1572 425 395 395
query14 11222 7009 7292 7009
query15 244 174 186 174
query16 7576 462 451 451
query17 1113 589 558 558
query18 1933 299 296 296
query19 286 151 144 144
query20 122 117 114 114
query21 210 103 100 100
query22 4563 4365 4426 4365
query23 34185 33807 33264 33264
query24 5956 2909 2875 2875
query25 551 399 408 399
query26 692 163 165 163
query27 1782 290 295 290
query28 3815 2059 2050 2050
query29 707 429 434 429
query30 234 154 151 151
query31 945 752 761 752
query32 80 56 55 55
query33 426 296 291 291
query34 864 490 510 490
query35 826 728 704 704
query36 1079 918 938 918
query37 134 80 84 80
query38 4008 3948 3925 3925
query39 1450 1385 1382 1382
query40 203 121 121 121
query41 47 45 49 45
query42 118 98 96 96
query43 525 486 477 477
query44 1107 749 753 749
query45 198 167 177 167
query46 1085 753 775 753
query47 1907 1804 1823 1804
query48 381 293 299 293
query49 772 438 445 438
query50 829 436 418 418
query51 7265 7100 7038 7038
query52 103 94 88 88
query53 255 184 182 182
query54 579 464 465 464
query55 79 77 82 77
query56 287 269 269 269
query57 1207 1098 1069 1069
query58 238 252 233 233
query59 3167 2744 2774 2744
query60 306 293 316 293
query61 126 122 119 119
query62 751 646 646 646
query63 218 189 187 187
query64 2871 762 739 739
query65 3283 3149 3118 3118
query66 676 347 349 347
query67 15459 15115 15364 15115
query68 4459 574 548 548
query69 418 276 280 276
query70 1178 1067 1039 1039
query71 367 275 265 265
query72 6636 4016 4005 4005
query73 769 335 332 332
query74 9094 9154 8851 8851
query75 3411 2700 2697 2697
query76 1711 1062 1038 1038
query77 539 321 317 317
query78 9798 9320 9081 9081
query79 1541 534 534 534
query80 846 527 543 527
query81 570 230 222 222
query82 302 134 135 134
query83 186 145 155 145
query84 262 75 81 75
query85 885 290 291 290
query86 403 287 302 287
query87 4368 4263 4310 4263
query88 3894 2364 2353 2353
query89 390 294 292 292
query90 2000 202 194 194
query91 122 100 102 100
query92 61 53 54 53
query93 1686 538 538 538
query94 851 307 265 265
query95 356 259 275 259
query96 604 274 272 272
query97 3207 3091 3106 3091
query98 227 207 205 205
query99 1535 1250 1285 1250
Total cold run time: 308738 ms
Total hot run time: 192630 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2245562478
<details>
<summary>ClickBench: <b>Total hot run time: 30.15 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit a7e2b1bd85dd3827c86fb9ead1aa462b016a3aba, data reload: false
query1 0.04 0.03 0.04
query2 0.07 0.03 0.04
query3 0.22 0.05 0.05
query4 1.69 0.08 0.07
query5 0.49 0.49 0.48
query6 1.13 0.73 0.73
query7 0.02 0.02 0.01
query8 0.06 0.04 0.05
query9 0.56 0.50 0.47
query10 0.53 0.52 0.53
query11 0.16 0.12 0.12
query12 0.14 0.12 0.13
query13 0.59 0.58 0.58
query14 0.76 0.77 0.79
query15 0.86 0.82 0.81
query16 0.36 0.37 0.36
query17 0.96 1.04 1.00
query18 0.22 0.21 0.21
query19 1.75 1.65 1.81
query20 0.01 0.00 0.00
query21 15.40 0.72 0.65
query22 3.85 7.47 1.64
query23 18.32 1.43 1.29
query24 2.08 0.25 0.21
query25 0.16 0.08 0.08
query26 0.29 0.22 0.20
query27 0.45 0.23 0.23
query28 13.26 1.01 1.00
query29 12.59 3.30 3.29
query30 0.25 0.06 0.05
query31 2.86 0.39 0.40
query32 3.27 0.47 0.48
query33 2.88 2.87 2.89
query34 16.89 4.36 4.34
query35 4.42 4.35 4.38
query36 0.65 0.47 0.48
query37 0.19 0.15 0.16
query38 0.15 0.14 0.15
query39 0.04 0.03 0.04
query40 0.15 0.12 0.12
query41 0.10 0.04 0.05
query42 0.06 0.05 0.05
query43 0.05 0.04 0.04
Total cold run time: 108.98 s
Total hot run time: 30.15 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2244632951
<details>
<summary>TPC-H: <b>Total hot run time: 40396 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 0cac9c57dfbabd3aa3c3d90819462ad7e839f881, data reload: false
------ Round 1 ----------------------------------
q1 18633 4997 4405 4405
q2 2629 208 199 199
q3 10973 1205 1193 1193
q4 10788 775 851 775
q5 7688 2793 2838 2793
q6 234 141 140 140
q7 976 616 618 616
q8 9274 2109 2125 2109
q9 8620 6579 6551 6551
q10 8858 3801 3825 3801
q11 458 236 241 236
q12 399 234 235 234
q13 17763 2955 2971 2955
q14 289 233 233 233
q15 545 484 505 484
q16 474 399 377 377
q17 992 672 679 672
q18 8226 7563 7372 7372
q19 4583 1469 1438 1438
q20 683 320 342 320
q21 5056 3211 4018 3211
q22 361 296 282 282
Total cold run time: 118502 ms
Total hot run time: 40396 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4353 4246 4222 4222
q2 388 268 254 254
q3 2983 2766 2793 2766
q4 1932 1641 1607 1607
q5 5302 5353 5316 5316
q6 220 134 135 134
q7 2144 1702 1742 1702
q8 3198 3337 3321 3321
q9 8446 8429 8428 8428
q10 3908 3728 3753 3728
q11 576 522 494 494
q12 778 592 613 592
q13 16554 2967 2973 2967
q14 295 273 260 260
q15 518 485 485 485
q16 491 425 417 417
q17 1782 1469 1452 1452
q18 7708 7624 7355 7355
q19 2722 1662 1488 1488
q20 1994 1794 1801 1794
q21 4898 4744 4760 4744
q22 589 485 508 485
Total cold run time: 71779 ms
Total hot run time: 54011 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2249779271
<details>
<summary>ClickBench: <b>Total hot run time: 30.88 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit bf6aad6e7d1b3229f6fdc1b41de15dc9b7d01bfc, data reload: false
query1 0.04 0.04 0.03
query2 0.08 0.04 0.04
query3 0.22 0.06 0.05
query4 1.68 0.07 0.07
query5 0.48 0.49 0.49
query6 1.14 0.73 0.72
query7 0.02 0.01 0.02
query8 0.05 0.04 0.04
query9 0.55 0.49 0.50
query10 0.56 0.55 0.55
query11 0.15 0.12 0.11
query12 0.15 0.13 0.12
query13 0.60 0.60 0.58
query14 0.77 0.78 0.79
query15 0.86 0.83 0.82
query16 0.36 0.36 0.36
query17 0.96 0.94 0.97
query18 0.22 0.22 0.21
query19 1.80 1.69 1.70
query20 0.01 0.01 0.02
query21 15.39 0.72 0.66
query22 4.09 6.84 2.18
query23 18.32 1.46 1.28
query24 2.07 0.22 0.21
query25 0.15 0.09 0.09
query26 0.30 0.22 0.21
query27 0.46 0.24 0.23
query28 13.28 1.03 0.99
query29 12.60 3.31 3.31
query30 0.26 0.06 0.05
query31 2.89 0.39 0.39
query32 3.25 0.47 0.46
query33 2.92 2.89 2.94
query34 17.08 4.35 4.33
query35 4.43 4.42 4.40
query36 0.66 0.51 0.48
query37 0.20 0.16 0.16
query38 0.17 0.15 0.17
query39 0.05 0.04 0.04
query40 0.15 0.12 0.13
query41 0.10 0.05 0.05
query42 0.06 0.05 0.05
query43 0.06 0.04 0.04
Total cold run time: 109.64 s
Total hot run time: 30.88 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2249743123
<details>
<summary>TPC-H: <b>Total hot run time: 39710 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit bf6aad6e7d1b3229f6fdc1b41de15dc9b7d01bfc, data reload: false
------ Round 1 ----------------------------------
q1 18903 6335 4278 4278
q2 2011 188 197 188
q3 10567 1129 1077 1077
q4 10335 730 832 730
q5 7563 2711 2673 2673
q6 224 137 136 136
q7 950 597 584 584
q8 9216 2068 2049 2049
q9 8626 6526 6530 6526
q10 8716 3756 3758 3756
q11 483 238 245 238
q12 411 226 224 224
q13 17774 2982 2988 2982
q14 284 237 263 237
q15 522 486 493 486
q16 511 392 400 392
q17 986 696 695 695
q18 8084 7442 7301 7301
q19 4948 1442 1416 1416
q20 642 329 317 317
q21 4837 3154 3201 3154
q22 344 273 271 271
Total cold run time: 116937 ms
Total hot run time: 39710 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4377 4203 4201 4201
q2 360 268 262 262
q3 3047 2901 2956 2901
q4 1993 1654 1720 1654
q5 5585 5531 5489 5489
q6 220 145 129 129
q7 2223 1884 1828 1828
q8 3276 3399 3385 3385
q9 8726 8840 8816 8816
q10 4142 3798 3920 3798
q11 606 510 523 510
q12 811 659 657 657
q13 15727 3230 3188 3188
q14 322 291 295 291
q15 556 484 503 484
q16 500 440 422 422
q17 1845 1550 1520 1520
q18 8033 7955 7709 7709
q19 1778 1544 1534 1534
q20 2240 1880 1879 1879
q21 8261 4891 4857 4857
q22 609 541 519 519
Total cold run time: 75237 ms
Total hot run time: 56033 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2314365746
<details>
<summary>TPC-H: <b>Total hot run time: 38261 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit cbbeda91329c7f9ecaf9f55ca0b98af79b86d7ee, data reload: false
------ Round 1 ----------------------------------
q1 18891 5287 4355 4355
q2 2054 189 189 189
q3 11442 964 1144 964
q4 10333 693 732 693
q5 7762 2882 2904 2882
q6 228 140 137 137
q7 974 617 601 601
q8 9327 2133 2112 2112
q9 7352 6556 6576 6556
q10 7006 2323 2297 2297
q11 441 246 245 245
q12 393 224 230 224
q13 17765 3030 3037 3030
q14 274 240 242 240
q15 528 469 488 469
q16 586 527 503 503
q17 993 694 670 670
q18 7533 6842 6862 6842
q19 1386 1016 1088 1016
q20 696 341 326 326
q21 4552 2969 2888 2888
q22 1152 1032 1022 1022
Total cold run time: 111668 ms
Total hot run time: 38261 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4435 4335 4320 4320
q2 383 271 267 267
q3 2892 2634 2744 2634
q4 1934 1718 1734 1718
q5 5725 5694 5837 5694
q6 225 133 133 133
q7 2202 1793 1847 1793
q8 3329 3488 3533 3488
q9 8904 8917 8871 8871
q10 3577 3438 3414 3414
q11 588 516 501 501
q12 865 677 678 677
q13 13058 3068 3223 3068
q14 320 278 291 278
q15 531 508 488 488
q16 648 576 602 576
q17 1851 1567 1557 1557
q18 8236 7798 7811 7798
q19 1745 1630 1537 1537
q20 2196 1923 1906 1906
q21 5786 5462 5503 5462
q22 1149 1037 1035 1035
Total cold run time: 70579 ms
Total hot run time: 57215 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1733771142
##########
cloud/src/recycler/recycler.cpp:
##########
@@ -1222,6 +1309,10 @@ int InstanceRecycler::recycle_tablets(int64_t table_id, int64_t index_id, int64_
int ret = scan_and_recycle(tablet_key_begin, tablet_key_end, std::move(recycle_func),
std::move(loop_done));
+ if (ret != 0) {
+ LOG(WARNING) << "failed to scan_and_recycle, instance_id=" << instance_id_;
Review Comment:
in the internal call `func`, it has printed more detail log when `ret != 0`
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1733937630
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,476 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include <chrono>
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+#include "meta-service/meta_service_tablet_stats.h"
+
+using namespace std::chrono;
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void update_tablet_stats(const StatsTabletKeyInfo& info, const TabletStats& stats,
+ std::unique_ptr<Transaction>& txn, MetaServiceCode& code,
+ std::string& msg);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids) {
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ // partition_id -> VersionPB
+ std::unordered_map<int64_t, VersionPB> partition_versions;
+ // tablet_id -> stats
+ std::unordered_map<int64_t, TabletStats> tablet_stats;
+
+ for (auto& [tmp_rowset_key, tmp_rowset_pb] : tmp_rowsets_meta) {
+ std::string tmp_rowst_data;
+ err = txn->get(tmp_rowset_key, &tmp_rowst_data);
+ if (TxnErrorCode::TXN_KEY_NOT_FOUND == err) {
+ // the tmp rowset has been converted
+ VLOG_DEBUG << "tmp rowset has been converted, key=" << hex(tmp_rowset_key);
+ continue;
+ }
+
+ if (TxnErrorCode::TXN_OK != err) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tmp_rowset_key, txn_id=" << txn_id
+ << " key=" << hex(tmp_rowset_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ if (!tablet_ids.contains(tmp_rowset_pb.tablet_id())) {
+ std::string tablet_idx_key =
+ meta_tablet_idx_key({instance_id, tmp_rowset_pb.tablet_id()});
+ std::string tablet_idx_val;
+ err = txn->get(tablet_idx_key, &tablet_idx_val, true);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get tablet idx, txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key) << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TabletIndexPB tablet_idx_pb;
+ if (!tablet_idx_pb.ParseFromString(tablet_idx_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse tablet idx pb txn_id=" << txn_id
+ << " key=" << hex(tablet_idx_key);
+ msg = ss.str();
+ return;
+ }
+ tablet_ids.emplace(tmp_rowset_pb.tablet_id(), tablet_idx_pb);
+ }
+ const TabletIndexPB& tablet_idx_pb = tablet_ids[tmp_rowset_pb.tablet_id()];
+
+ if (!partition_versions.contains(tmp_rowset_pb.partition_id())) {
+ std::string ver_val;
+ std::string ver_key = partition_version_key(
+ {instance_id, db_id, tablet_idx_pb.table_id(), tmp_rowset_pb.partition_id()});
+ err = txn->get(ver_key, &ver_val);
+ if (TxnErrorCode::TXN_OK != err) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get partiton version, txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ VersionPB version_pb;
+ if (!version_pb.ParseFromString(ver_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse version pb txn_id=" << txn_id << " key=" << hex(ver_key);
+ msg = ss.str();
+ return;
+ }
+ LOG(INFO) << "txn_id=" << txn_id << " key=" << hex(ver_key)
+ << " version_pb:" << version_pb.ShortDebugString();
+ partition_versions.emplace(tmp_rowset_pb.partition_id(), version_pb);
+ }
+
+ const VersionPB& version_pb = partition_versions[tmp_rowset_pb.partition_id()];
+ DCHECK(version_pb.pending_txn_ids_size() > 0);
+ DCHECK_EQ(version_pb.pending_txn_ids(0), txn_id);
+
+ int64_t version = version_pb.has_version() ? (version_pb.version() + 1) : 2;
+
+ std::string rowset_key = meta_rowset_key({instance_id, tmp_rowset_pb.tablet_id(), version});
+ std::string rowset_val;
+ err = txn->get(rowset_key, &rowset_val);
+ if (TxnErrorCode::TXN_OK == err) {
+ // tmp rowset key has been converted
+ continue;
+ }
+
+ if (err != TxnErrorCode::TXN_KEY_NOT_FOUND) {
+ code = cast_as<ErrCategory::READ>(err);
+ ss << "failed to get rowset_key, txn_id=" << txn_id << " key=" << hex(rowset_key)
+ << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+ DCHECK(err == TxnErrorCode::TXN_KEY_NOT_FOUND);
+
+ tmp_rowset_pb.set_start_version(version);
+ tmp_rowset_pb.set_end_version(version);
+
+ rowset_val.clear();
+ if (!tmp_rowset_pb.SerializeToString(&rowset_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize rowset_meta, txn_id=" << txn_id
+ << " key=" << hex(rowset_key);
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(rowset_key, rowset_val);
+ LOG(INFO) << "put rowset_key=" << hex(rowset_key) << " txn_id=" << txn_id
+ << " rowset_size=" << rowset_key.size() + rowset_val.size();
+
+ // Accumulate affected rows
+ auto& stats = tablet_stats[tmp_rowset_pb.tablet_id()];
+ stats.data_size += tmp_rowset_pb.data_disk_size();
+ stats.num_rows += tmp_rowset_pb.num_rows();
+ ++stats.num_rowsets;
+ stats.num_segs += tmp_rowset_pb.num_segments();
+ }
+
+ DCHECK(partition_versions.size() == 1);
+
+ for (auto& [tablet_id, stats] : tablet_stats) {
+ DCHECK(tablet_ids.count(tablet_id));
+ auto& tablet_idx = tablet_ids[tablet_id];
+ StatsTabletKeyInfo info {instance_id, tablet_idx.table_id(), tablet_idx.index_id(),
+ tablet_idx.partition_id(), tablet_id};
+ update_tablet_stats(info, stats, txn, code, msg);
+ if (code != MetaServiceCode::OK) return;
+ }
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+}
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg) {
+ // 1. visible txn info
+ // 2. remove running key and put recycle txn key
+
+ std::stringstream ss;
+ std::unique_ptr<Transaction> txn;
+ TxnErrorCode err = txn_kv->create_txn(&txn);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::CREATE>(err);
+ ss << "failed to create txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ std::string info_val;
+ const std::string info_key = txn_info_key({instance_id, db_id, txn_id});
+ err = txn->get(info_key, &info_val);
+ if (err != TxnErrorCode::TXN_OK) {
+ code = err == TxnErrorCode::TXN_KEY_NOT_FOUND ? MetaServiceCode::TXN_ID_NOT_FOUND
+ : cast_as<ErrCategory::READ>(err);
+ ss << "failed to get txn_info, db_id=" << db_id << " txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ TxnInfoPB txn_info;
+ if (!txn_info.ParseFromString(info_val)) {
+ code = MetaServiceCode::PROTOBUF_PARSE_ERR;
+ ss << "failed to parse txn_info, txn_id=" << txn_id;
+ msg = ss.str();
+ LOG(WARNING) << msg;
+ return;
+ }
+
+ VLOG_DEBUG << "txn_info:" << txn_info.ShortDebugString();
+ DCHECK((txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) ||
+ (txn_info.status() == TxnStatusPB::TXN_STATUS_VISIBLE));
+
+ if (txn_info.status() == TxnStatusPB::TXN_STATUS_COMMITTED) {
+ txn_info.set_status(TxnStatusPB::TXN_STATUS_VISIBLE);
+
+ if (!txn_info.SerializeToString(&info_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize txn_info when saving, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+ txn->put(info_key, info_val);
+ LOG(INFO) << "put info_key=" << hex(info_key) << " txn_id=" << txn_id;
+
+ const std::string running_key = txn_running_key({instance_id, db_id, txn_id});
+ LOG(INFO) << "remove running_key=" << hex(running_key) << " txn_id=" << txn_id;
+ txn->remove(running_key);
+
+ std::string recycle_val;
+ std::string recycle_key = recycle_txn_key({instance_id, db_id, txn_id});
+ RecycleTxnPB recycle_pb;
+ auto now_time = system_clock::now();
+ uint64_t visible_time = duration_cast<milliseconds>(now_time.time_since_epoch()).count();
+ recycle_pb.set_creation_time(visible_time);
+ recycle_pb.set_label(txn_info.label());
+
+ if (!recycle_pb.SerializeToString(&recycle_val)) {
+ code = MetaServiceCode::PROTOBUF_SERIALIZE_ERR;
+ ss << "failed to serialize recycle_pb, txn_id=" << txn_id;
+ msg = ss.str();
+ return;
+ }
+
+ txn->put(recycle_key, recycle_val);
+ LOG(INFO) << "put recycle_key=" << hex(recycle_key) << " txn_id=" << txn_id;
+
+ err = txn->commit();
+ if (err != TxnErrorCode::TXN_OK) {
+ code = cast_as<ErrCategory::COMMIT>(err);
+ ss << "failed to commit kv txn, txn_id=" << txn_id << " err=" << err;
+ msg = ss.str();
+ return;
+ }
+ }
+}
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
Review Comment:
warning: function 'commit' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void TxnLazyCommitTask::commit() {
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:296:** 139 lines including whitespace and comments (threshold 80)
```cpp
void TxnLazyCommitTask::commit() {
^
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2312363624
run cloud_p0
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2260209528
<details>
<summary>TPC-H: <b>Total hot run time: 41823 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit ae48134efcfe7887d2b0b6f2d645e9c4fac57e59, data reload: false
------ Round 1 ----------------------------------
q1 17635 4159 4115 4115
q2 2025 206 201 201
q3 10550 1295 1294 1294
q4 10213 849 987 849
q5 7625 2981 2997 2981
q6 222 138 142 138
q7 1038 620 605 605
q8 9494 1935 1960 1935
q9 8486 6631 6617 6617
q10 8716 3862 3849 3849
q11 434 256 249 249
q12 419 228 230 228
q13 17757 2924 2915 2915
q14 270 246 246 246
q15 522 484 487 484
q16 531 387 384 384
q17 999 962 908 908
q18 8113 7322 7209 7209
q19 1477 1229 1228 1228
q20 566 338 355 338
q21 5345 4764 4769 4764
q22 358 295 286 286
Total cold run time: 112795 ms
Total hot run time: 41823 ms
----- Round 2, with runtime_filter_mode=off -----
q1 4052 4051 4081 4051
q2 324 231 220 220
q3 3010 2993 3147 2993
q4 2003 2049 1962 1962
q5 5622 5545 5444 5444
q6 217 132 134 132
q7 2150 1797 1878 1797
q8 3356 3388 3384 3384
q9 8717 8714 8799 8714
q10 3946 4057 3967 3967
q11 553 441 454 441
q12 714 591 582 582
q13 15293 3119 3124 3119
q14 301 277 284 277
q15 528 485 503 485
q16 456 412 414 412
q17 1800 1713 1700 1700
q18 8320 7788 7838 7788
q19 1735 1722 1714 1714
q20 2056 1857 1882 1857
q21 5775 5434 5437 5434
q22 526 457 488 457
Total cold run time: 71454 ms
Total hot run time: 56930 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1698539283
##########
cloud/src/meta-service/txn_lazy_committer.cpp:
##########
@@ -0,0 +1,208 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "txn_lazy_committer.h"
+
+#include "common/logging.h"
+#include "common/util.h"
+#include "meta-service/keys.h"
+#include "meta-service/meta_service_helper.h"
+
+namespace doris::cloud {
+
+void scan_tmp_rowset(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t* db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>* tmp_rowsets_meta);
+
+void convert_tmp_rowsets(
+ const std::string& instance_id, int64_t txn_id, std::shared_ptr<TxnKv> txn_kv,
+ MetaServiceCode& code, std::string& msg, int64_t db_id,
+ std::vector<std::pair<std::string, doris::RowsetMetaCloudPB>>& tmp_rowsets_meta,
+ std::unordered_map<int64_t, TabletIndexPB>& tablet_ids);
+
+void make_committed_txn_visible(const std::string& instance_id, int64_t db_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv, MetaServiceCode& code,
+ std::string& msg);
+
+TxnLazyCommitTask::TxnLazyCommitTask(const std::string& instance_id, int64_t txn_id,
+ std::shared_ptr<TxnKv> txn_kv,
+ TxnLazyCommitter* txn_lazy_committer)
+ : instance_id_(instance_id),
+ txn_id_(txn_id),
+ txn_kv_(txn_kv),
+ txn_lazy_committer_(txn_lazy_committer) {
+ DCHECK(txn_id > 0);
+}
+
+void TxnLazyCommitTask::commit() {
Review Comment:
warning: function 'commit' exceeds recommended size/complexity thresholds [readability-function-size]
```cpp
void TxnLazyCommitTask::commit() {
^
```
<details>
<summary>Additional context</summary>
**cloud/src/meta-service/txn_lazy_committer.cpp:51:** 118 lines including whitespace and comments (threshold 80)
```cpp
void TxnLazyCommitTask::commit() {
^
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2304691488
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2304947046
<details>
<summary>TPC-DS: <b>Total hot run time: 192723 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 0b1e4a8f000eb4cf1faa30535e050f844fb38a05, data reload: false
query1 1237 881 870 870
query2 6360 1961 1848 1848
query3 10663 3958 3973 3958
query4 59331 26821 23055 23055
query5 5246 492 493 492
query6 411 168 166 166
query7 5739 295 289 289
query8 281 212 213 212
query9 8729 2515 2499 2499
query10 459 280 255 255
query11 17413 15203 15220 15203
query12 164 107 104 104
query13 1555 379 383 379
query14 10928 7385 7359 7359
query15 225 180 177 177
query16 7212 475 435 435
query17 1120 554 565 554
query18 1998 298 315 298
query19 278 150 148 148
query20 120 110 109 109
query21 205 108 105 105
query22 4636 4390 4516 4390
query23 34188 33484 33255 33255
query24 5909 2866 2846 2846
query25 521 398 401 398
query26 633 158 158 158
query27 1681 276 276 276
query28 3571 2063 2041 2041
query29 669 429 419 419
query30 237 165 159 159
query31 937 771 729 729
query32 72 60 58 58
query33 418 286 292 286
query34 867 466 471 466
query35 868 735 747 735
query36 1086 942 931 931
query37 140 85 81 81
query38 3970 3913 3947 3913
query39 1479 1369 1398 1369
query40 205 119 120 119
query41 48 45 47 45
query42 122 99 99 99
query43 521 477 467 467
query44 1104 742 739 739
query45 202 170 168 168
query46 1087 769 734 734
query47 1876 1848 1845 1845
query48 374 294 301 294
query49 781 447 441 441
query50 802 420 410 410
query51 7147 6968 7019 6968
query52 105 89 88 88
query53 250 181 181 181
query54 570 455 467 455
query55 79 79 81 79
query56 311 272 282 272
query57 1199 1076 1061 1061
query58 222 233 238 233
query59 3026 2927 2883 2883
query60 297 270 286 270
query61 128 122 122 122
query62 738 648 668 648
query63 214 185 179 179
query64 2708 2832 2387 2387
query65 3231 3173 3148 3148
query66 677 323 346 323
query67 15581 15336 15198 15198
query68 4526 551 535 535
query69 573 367 287 287
query70 1166 1114 1062 1062
query71 433 261 271 261
query72 7242 2345 2128 2128
query73 762 316 320 316
query74 9544 8863 8808 8808
query75 3508 2671 2669 2669
query76 2062 1043 968 968
query77 712 321 308 308
query78 10939 9324 9485 9324
query79 3131 546 543 543
query80 897 492 493 492
query81 580 230 228 228
query82 768 139 137 137
query83 317 152 146 146
query84 273 75 73 73
query85 695 303 328 303
query86 435 294 293 293
query87 4336 4261 4253 4253
query88 3991 2280 2284 2280
query89 400 281 276 276
query90 1888 191 188 188
query91 119 98 99 98
query92 60 49 51 49
query93 2246 529 534 529
query94 750 282 287 282
query95 353 262 261 261
query96 586 262 268 262
query97 3185 3085 3036 3036
query98 232 203 201 201
query99 1751 1293 1246 1246
Total cold run time: 313621 ms
Total hot run time: 192723 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2304974454
<details>
<summary>ClickBench: <b>Total hot run time: 30.55 s</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 0b1e4a8f000eb4cf1faa30535e050f844fb38a05, data reload: false
query1 0.04 0.04 0.04
query2 0.09 0.04 0.04
query3 0.23 0.06 0.04
query4 1.68 0.11 0.09
query5 0.52 0.49 0.49
query6 1.13 0.75 0.73
query7 0.02 0.02 0.01
query8 0.06 0.05 0.05
query9 0.55 0.50 0.49
query10 0.54 0.55 0.54
query11 0.16 0.12 0.11
query12 0.16 0.12 0.12
query13 0.63 0.58 0.58
query14 0.78 0.79 0.77
query15 0.86 0.83 0.82
query16 0.38 0.38 0.38
query17 1.04 1.00 0.98
query18 0.22 0.21 0.20
query19 1.84 1.69 1.75
query20 0.02 0.01 0.01
query21 15.41 0.66 0.66
query22 4.05 7.73 1.78
query23 18.21 1.43 1.29
query24 2.05 0.25 0.22
query25 0.16 0.08 0.08
query26 0.28 0.18 0.18
query27 0.07 0.08 0.08
query28 13.26 1.02 1.00
query29 12.66 3.35 3.33
query30 0.24 0.06 0.05
query31 2.86 0.40 0.39
query32 3.26 0.47 0.48
query33 2.95 2.97 2.96
query34 16.91 4.40 4.43
query35 4.40 4.42 4.40
query36 0.66 0.48 0.49
query37 0.19 0.16 0.16
query38 0.17 0.15 0.15
query39 0.04 0.03 0.04
query40 0.15 0.12 0.13
query41 0.10 0.05 0.05
query42 0.06 0.05 0.05
query43 0.05 0.04 0.04
Total cold run time: 109.14 s
Total hot run time: 30.55 s
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "doris-robot (via GitHub)" <gi...@apache.org>.
doris-robot commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2303676968
<details>
<summary>TPC-DS: <b>Total hot run time: 198312 ms</b></summary>
```
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 740144c09664bd5fcc4a77551e5f4fdf659aa12d, data reload: false
query1 1312 916 889 889
query2 6570 1974 1945 1945
query3 10663 4138 3925 3925
query4 59449 25018 23244 23244
query5 5641 726 744 726
query6 474 210 212 210
query7 5812 337 330 330
query8 516 436 429 429
query9 8674 2574 2533 2533
query10 541 353 343 343
query11 17797 15211 15342 15211
query12 186 132 131 131
query13 1552 444 441 441
query14 11354 7380 7617 7380
query15 252 198 197 197
query16 7440 535 525 525
query17 1192 622 618 618
query18 2060 357 352 352
query19 321 172 178 172
query20 146 140 142 140
query21 251 149 143 143
query22 4599 4423 4599 4423
query23 34739 34092 34046 34046
query24 6176 3018 2978 2978
query25 582 442 427 427
query26 705 189 186 186
query27 1726 334 321 321
query28 3745 2181 2154 2154
query29 733 458 452 452
query30 238 193 190 190
query31 1074 938 871 871
query32 98 81 84 81
query33 539 361 348 348
query34 908 527 518 518
query35 864 799 759 759
query36 1076 998 972 972
query37 163 107 119 107
query38 4050 3917 3968 3917
query39 1547 1473 1453 1453
query40 241 159 160 159
query41 138 137 139 137
query42 133 114 116 114
query43 549 507 522 507
query44 1167 804 811 804
query45 221 194 197 194
query46 1122 792 792 792
query47 1937 1847 1902 1847
query48 428 349 355 349
query49 942 614 594 594
query50 884 474 471 471
query51 7205 7128 7037 7037
query52 120 107 109 107
query53 297 222 226 222
query54 631 542 513 513
query55 96 92 87 87
query56 345 314 324 314
query57 1229 1129 1108 1108
query58 295 309 308 308
query59 3038 2857 2876 2857
query60 383 333 336 333
query61 153 144 152 144
query62 811 703 695 695
query63 264 227 230 227
query64 3375 1882 1893 1882
query65 3257 3241 3241 3241
query66 963 671 670 670
query67 15563 15111 15407 15111
query68 4239 617 587 587
query69 474 325 332 325
query70 1247 1170 1172 1170
query71 408 326 331 326
query72 6427 2415 2112 2112
query73 803 360 362 360
query74 9271 8924 8851 8851
query75 3484 2748 2777 2748
query76 1535 1060 1019 1019
query77 664 443 438 438
query78 10730 9334 9173 9173
query79 1601 581 558 558
query80 1045 635 626 626
query81 601 262 262 262
query82 421 164 162 162
query83 240 208 212 208
query84 285 101 102 101
query85 906 415 358 358
query86 441 322 306 306
query87 4399 4377 4263 4263
query88 3270 2563 2554 2554
query89 441 326 328 326
query90 1869 234 233 233
query91 153 126 124 124
query92 89 82 77 77
query93 1639 555 562 555
query94 808 333 338 333
query95 390 309 296 296
query96 610 290 291 290
query97 3283 3160 3098 3098
query98 253 225 227 225
query99 1859 1350 1337 1337
Total cold run time: 315437 ms
Total hot run time: 198312 ms
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2304158770
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "w41ter (via GitHub)" <gi...@apache.org>.
w41ter commented on code in PR #38243:
URL: https://github.com/apache/doris/pull/38243#discussion_r1722598237
##########
be/src/cloud/config.h:
##########
@@ -94,4 +94,6 @@ DECLARE_mBool(save_load_error_log_to_s3);
// the theads which sync the datas which loaded in other clusters
DECLARE_mInt32(sync_load_for_tablets_thread);
+DECLARE_mBool(txn_lazy_commit);
Review Comment:
Add `cloud_` prefix, and add a description too.
##########
cloud/src/meta-service/meta_service.cpp:
##########
@@ -618,11 +649,13 @@ void MetaServiceImpl::create_tablets(::google::protobuf::RpcController* controll
msg = fmt::format("failed to get vault id, vault name={}", name);
return;
}
+ DCHECK(request->has_db_id());
Review Comment:
What happens if the doris FE is the old version?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "SWJTU-ZhangLei (via GitHub)" <gi...@apache.org>.
SWJTU-ZhangLei commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2300026963
run buildall
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org
Re: [PR] [feature](cloud) Add lazy commit mechanism for `commit_txn` [doris]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #38243:
URL: https://github.com/apache/doris/pull/38243#issuecomment-2298075618
PR approved by anyone and no changes requested.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org