@@ -134,6 +134,7 @@ METRIC_DECLARE_entity(tablet);
134
134
METRIC_DECLARE_gauge_uint64 (aborted_transactions_pending_cleanup);
135
135
METRIC_DECLARE_histogram (handler_latency_outbound_transfer);
136
136
METRIC_DECLARE_gauge_int64 (rpc_busy_reactors);
137
+ METRIC_DECLARE_gauge_uint64 (wal_replayable_applied_transactions);
137
138
138
139
namespace yb ::pgwrapper {
139
140
namespace {
@@ -2552,6 +2553,151 @@ TEST_F(PgMiniTestSingleNode, TestBootstrapOnAppliedTransactionWithIntents) {
2552
2553
ASSERT_EQ (res, 1 );
2553
2554
}
2554
2555
2556
+ TEST_F (PgMiniTestSingleNode, TestAppliedTransactionsStateReadOnly) {
2557
+ constexpr size_t kIters = 100 ;
2558
+
2559
+ ANNOTATE_UNPROTECTED_WRITE (FLAGS_delete_intents_sst_files) = false ;
2560
+ ANNOTATE_UNPROTECTED_WRITE (FLAGS_use_bootstrap_intent_ht_filter) = true ;
2561
+ ANNOTATE_UNPROTECTED_WRITE (FLAGS_TEST_no_schedule_remove_intents) = true ;
2562
+ ANNOTATE_UNPROTECTED_WRITE (FLAGS_TEST_disable_flush_on_shutdown) = true ;
2563
+
2564
+ auto conn = ASSERT_RESULT (Connect ());
2565
+
2566
+ LOG (INFO) << " Creating tables" ;
2567
+ ASSERT_OK (conn.Execute (" CREATE TABLE test1(a int primary key) SPLIT INTO 1 TABLETS" ));
2568
+
2569
+ tablet::TabletPeerPtr test1_peer = nullptr ;
2570
+ {
2571
+ const auto & peers = ListTabletPeers (cluster_.get (), ListPeersFilter::kLeaders );
2572
+ for (auto peer : peers) {
2573
+ if (peer->shared_tablet ()->regular_db ()) {
2574
+ test1_peer = peer;
2575
+ break ;
2576
+ }
2577
+ }
2578
+ ASSERT_NE (test1_peer, nullptr );
2579
+ }
2580
+ std::string test1_tablet_id = test1_peer->shared_tablet ()->tablet_id ();
2581
+
2582
+ ASSERT_OK (conn.StartTransaction (IsolationLevel::SNAPSHOT_ISOLATION));
2583
+ ASSERT_OK (conn.Execute (" INSERT INTO test1(a) VALUES (0)" ));
2584
+ ASSERT_OK (conn.CommitTransaction ());
2585
+
2586
+ ASSERT_OK (test1_peer->shared_tablet ()->Flush (tablet::FlushMode::kSync ));
2587
+ ASSERT_OK (test1_peer->FlushBootstrapState ());
2588
+
2589
+ ASSERT_OK (conn.Execute (" CREATE TABLE test2(a int references test1(a)) SPLIT INTO 1 TABLETS" ));
2590
+ for (size_t i = 0 ; i < kIters ; ++i) {
2591
+ ASSERT_OK (conn.StartTransaction (IsolationLevel::SNAPSHOT_ISOLATION));
2592
+ ASSERT_OK (conn.Execute (" INSERT INTO test2(a) VALUES (0)" ));
2593
+ ASSERT_OK (conn.CommitTransaction ());
2594
+ }
2595
+
2596
+ ASSERT_EQ (
2597
+ GetMetricOpt<AtomicGauge<uint64_t >>(
2598
+ *test1_peer->shared_tablet (), METRIC_wal_replayable_applied_transactions)->value (),
2599
+ 1 );
2600
+
2601
+ LOG (INFO) << " Restarting cluster" ;
2602
+ ASSERT_OK (RestartCluster ());
2603
+
2604
+ for (auto peer : ListTabletPeers (cluster_.get (), ListPeersFilter::kAll )) {
2605
+ if (!peer->shared_tablet ()->regular_db ()) {
2606
+ continue ;
2607
+ }
2608
+ auto metric_value = GetMetricOpt<AtomicGauge<uint64_t >>(
2609
+ *peer->shared_tablet (), METRIC_wal_replayable_applied_transactions)->value ();
2610
+ if (peer->shared_tablet ()->tablet_id () == test1_tablet_id) {
2611
+ ASSERT_EQ (metric_value, 1 );
2612
+ } else {
2613
+ ASSERT_EQ (metric_value, kIters );
2614
+ }
2615
+ }
2616
+
2617
+ conn = ASSERT_RESULT (Connect ());
2618
+ auto res = ASSERT_RESULT (conn.FetchRow <PGUint64>(" SELECT COUNT(*) FROM test1" ));
2619
+ ASSERT_EQ (res, 1 );
2620
+ res = ASSERT_RESULT (conn.FetchRow <PGUint64>(" SELECT COUNT(*) FROM test2" ));
2621
+ ASSERT_EQ (res, kIters );
2622
+ }
2623
+
2624
+ TEST_F (PgMiniTest, TestAppliedTransactionsStateInFlight) {
2625
+ const auto kApplyWait = 5s * kTimeMultiplier ;
2626
+
2627
+ ANNOTATE_UNPROTECTED_WRITE (FLAGS_delete_intents_sst_files) = false ;
2628
+ ANNOTATE_UNPROTECTED_WRITE (FLAGS_use_bootstrap_intent_ht_filter) = true ;
2629
+ ANNOTATE_UNPROTECTED_WRITE (FLAGS_TEST_no_schedule_remove_intents) = true ;
2630
+ ANNOTATE_UNPROTECTED_WRITE (FLAGS_TEST_disable_flush_on_shutdown) = true ;
2631
+
2632
+ auto conn1 = ASSERT_RESULT (Connect ());
2633
+ auto conn2 = ASSERT_RESULT (Connect ());
2634
+ auto conn3 = ASSERT_RESULT (Connect ());
2635
+
2636
+ LOG (INFO) << " Creating table" ;
2637
+ ASSERT_OK (conn1.Execute (" CREATE TABLE test(a int) SPLIT INTO 1 TABLETS" ));
2638
+
2639
+ const auto & pg_ts_uuid = cluster_->mini_tablet_server (kPgTsIndex )->server ()->permanent_uuid ();
2640
+ tablet::TabletPeerPtr tablet_peer = nullptr ;
2641
+ for (auto peer : ListTabletPeers (cluster_.get (), ListPeersFilter::kNonLeaders )) {
2642
+ if (peer->shared_tablet ()->regular_db () && peer->permanent_uuid () != pg_ts_uuid) {
2643
+ tablet_peer = peer;
2644
+ break ;
2645
+ }
2646
+ }
2647
+ ASSERT_NE (tablet_peer, nullptr );
2648
+
2649
+ tserver::MiniTabletServer* tablet_server = nullptr ;
2650
+ for (size_t i = 0 ; i < NumTabletServers (); ++i) {
2651
+ auto * ts = cluster_->mini_tablet_server (i);
2652
+ if (ts->server ()->permanent_uuid () == tablet_peer->permanent_uuid ()) {
2653
+ tablet_server = ts;
2654
+ break ;
2655
+ }
2656
+ }
2657
+ ASSERT_NE (tablet_server, nullptr );
2658
+
2659
+ ASSERT_OK (conn1.StartTransaction (IsolationLevel::SNAPSHOT_ISOLATION));
2660
+ ASSERT_OK (conn1.Execute (" INSERT INTO test(a) VALUES (0)" ));
2661
+ ASSERT_OK (conn1.CommitTransaction ());
2662
+
2663
+ ASSERT_OK (conn1.StartTransaction (IsolationLevel::SNAPSHOT_ISOLATION));
2664
+ ASSERT_OK (conn1.Execute (" INSERT INTO test(a) VALUES (1)" ));
2665
+
2666
+ ASSERT_OK (conn2.StartTransaction (IsolationLevel::SNAPSHOT_ISOLATION));
2667
+ ASSERT_OK (conn2.Execute (" INSERT INTO test(a) VALUES (2)" ));
2668
+ ASSERT_OK (conn2.FetchRow <PGUint32>(" SELECT a FROM test WHERE a = 0 FOR KEY SHARE" ));
2669
+
2670
+ ASSERT_OK (conn3.StartTransaction (IsolationLevel::SNAPSHOT_ISOLATION));
2671
+ ASSERT_OK (conn3.FetchRow <PGUint32>(" SELECT a FROM test WHERE a = 0 FOR KEY SHARE" ));
2672
+
2673
+ ASSERT_OK (tablet_peer->shared_tablet ()->Flush (tablet::FlushMode::kSync ));
2674
+
2675
+ ASSERT_OK (tablet_server->Restart ());
2676
+ ASSERT_OK (tablet_server->WaitStarted ());
2677
+
2678
+ ASSERT_OK (conn1.CommitTransaction ());
2679
+ ASSERT_OK (conn2.CommitTransaction ());
2680
+ ASSERT_OK (conn3.CommitTransaction ());
2681
+
2682
+ // Wait for apply.
2683
+ SleepFor (kApplyWait );
2684
+
2685
+ std::unordered_map<std::string, uint64_t > metric_values;
2686
+ for (auto peer : ListTabletPeers (cluster_.get (), ListPeersFilter::kAll )) {
2687
+ if (peer->shared_tablet ()->regular_db ()) {
2688
+ metric_values[peer->permanent_uuid ()] = GetMetricOpt<AtomicGauge<uint64_t >>(
2689
+ *peer->shared_tablet (), METRIC_wal_replayable_applied_transactions)->value ();
2690
+ }
2691
+ }
2692
+
2693
+ // Expecting metric value to be 3 on all peers: the intial insert + conn1/conn2 transactions.
2694
+ // conn3 transaction is readonly and not added to map.
2695
+ LOG (INFO) << " Metric values: " << CollectionToString (metric_values);
2696
+ for (const auto & [_, value] : metric_values) {
2697
+ ASSERT_EQ (value, 3 );
2698
+ }
2699
+ }
2700
+
2555
2701
Status MockAbortFailure (
2556
2702
const yb::tserver::PgFinishTransactionRequestPB* req,
2557
2703
yb::tserver::PgFinishTransactionResponsePB* resp, yb::rpc::RpcContext* context) {
0 commit comments