From 99ffb31b4c3dfc49e75a2d6d83f54039726f7758 Mon Sep 17 00:00:00 2001 From: Linh Nguyen Date: Mon, 6 Jun 2022 18:19:16 +0000 Subject: [PATCH] [BACKPORT 2.12][#12775] YSQL: Show transaction priority of the active transaction in current session Summary: Original commit: 0a12cb7ff08cd0afbc29986c62c5481385510097 / D17477 We show the transaction priority of the active transaction in the current session. There are two items to be shown: * The priority being picked * The priority type (normal, high or highest) See the unit test for the formatting of transaction priority to show to users. Test Plan: `ybd --java-test org.yb.pgsql.TestPgRegressMisc` Reviewers: ymahajan, pjain, smishra Reviewed By: smishra Subscribers: yql Differential Revision: https://phabricator.dev.yugabyte.com/D17648 --- src/postgres/src/backend/utils/misc/guc.c | 36 ++++++++++ .../src/test/regress/expected/yb_guc.out | 65 ++++++++++++++++++- src/postgres/src/test/regress/sql/yb_guc.sql | 33 ++++++++++ src/yb/client/transaction.h | 6 -- src/yb/yql/pggate/pg_txn_manager.cc | 37 +++++++++++ src/yb/yql/pggate/pg_txn_manager.h | 3 + src/yb/yql/pggate/pggate.cc | 8 +++ src/yb/yql/pggate/pggate.h | 2 + src/yb/yql/pggate/ybc_pg_typedefs.h | 6 ++ src/yb/yql/pggate/ybc_pggate.cc | 8 +++ src/yb/yql/pggate/ybc_pggate.h | 2 + 11 files changed, 197 insertions(+), 9 deletions(-) diff --git a/src/postgres/src/backend/utils/misc/guc.c b/src/postgres/src/backend/utils/misc/guc.c index b5a16db67b9..8574eb23e2a 100644 --- a/src/postgres/src/backend/utils/misc/guc.c +++ b/src/postgres/src/backend/utils/misc/guc.c @@ -133,6 +133,7 @@ extern bool optimize_bounded_sort; static double yb_transaction_priority_lower_bound = 0.0; static double yb_transaction_priority_upper_bound = 1.0; +static double yb_transaction_priority = 0.0; static int GUC_check_errcode_value; @@ -209,6 +210,9 @@ static bool check_transaction_priority_lower_bound(double *newval, void **extra, extern void YBCAssignTransactionPriorityLowerBound(double newval, void* extra); static bool check_transaction_priority_upper_bound(double *newval, void **extra, GucSource source); extern void YBCAssignTransactionPriorityUpperBound(double newval, void* extra); +extern double YBCGetTransactionPriority(); +extern TxnPriorityRequirement YBCGetTransactionPriorityType(); +static const char *show_transaction_priority(void); static void assign_ysql_upgrade_mode(bool newval, void *extra); @@ -3607,6 +3611,16 @@ static struct config_real ConfigureNamesReal[] = 1.0, 0.0, 1.0, check_transaction_priority_upper_bound, YBCAssignTransactionPriorityUpperBound, NULL }, + { + {"yb_transaction_priority", PGC_INTERNAL, CLIENT_CONN_STATEMENT, + gettext_noop("Gets the transaction priority used by the current active " + "transaction in the session. If no transaction is active, return 0"), + NULL + }, + &yb_transaction_priority, + 0.0, 0.0, 1.0, + NULL, NULL, show_transaction_priority + }, { {"retry_backoff_multiplier", PGC_USERSET, CLIENT_CONN_STATEMENT, @@ -11713,6 +11727,28 @@ check_transaction_priority_upper_bound(double *newval, void **extra, GucSource s return true; } +static const char * +show_transaction_priority(void) +{ + TxnPriorityRequirement txn_priority_type; + double txn_priority; + static char buf[50]; + + txn_priority_type = YBCGetTransactionPriorityType(); + txn_priority = YBCGetTransactionPriority(); + + if (txn_priority_type == kHighestPriority) + snprintf(buf, sizeof(buf), "Highest priority transaction"); + else if (txn_priority_type == kHigherPriorityRange) + snprintf(buf, sizeof(buf), + "%.9lf (High priority transaction)", txn_priority); + else + snprintf(buf, sizeof(buf), + "%.9lf (Normal priority transaction)", txn_priority); + + return buf; +} + static void assign_ysql_upgrade_mode(bool newval, void *extra) { diff --git a/src/postgres/src/test/regress/expected/yb_guc.out b/src/postgres/src/test/regress/expected/yb_guc.out index 8cf0a5c2185..d8bacbfd2e5 100644 --- a/src/postgres/src/test/regress/expected/yb_guc.out +++ b/src/postgres/src/test/regress/expected/yb_guc.out @@ -121,6 +121,65 @@ EXPLAIN SELECT j FROM test_scan; Seq Scan on test_scan (cost=10000000000.00..10000000100.00 rows=1000 width=4) (1 row) +-- Show transaction priority. As it is not possible to have a deterministic +-- yb_transaction_priority, we set yb_transaction_priority_lower_bound and +-- yb_transaction_priority_upper_bound to be the same, which forces +-- yb_transaction_priority to be equal to those two. +set yb_transaction_priority_lower_bound = 0.4; +set yb_transaction_priority_upper_bound = 0.4; +BEGIN TRANSACTION; +INSERT INTO test_scan (i, j) values (1, 1), (2, 2), (3, 3); +show yb_transaction_priority; + yb_transaction_priority +------------------------------------------- + 0.400000000 (Normal priority transaction) +(1 row) + +COMMIT; +-- Trying to set yb_transaction_priority will be an error +set yb_transaction_priority = 0.3; -- ERROR +ERROR: parameter "yb_transaction_priority" cannot be changed +-- High priority transaction +set yb_transaction_priority_lower_bound = 0.4; +set yb_transaction_priority_upper_bound = 0.4; +BEGIN TRANSACTION; +SELECT i, j FROM test_scan WHERE i = 1 FOR UPDATE; + i | j +---+--- + 1 | 1 +(1 row) + +show yb_transaction_priority; + yb_transaction_priority +----------------------------------------- + 0.400000000 (High priority transaction) +(1 row) + +COMMIT; +-- Highest priority transaction +set yb_transaction_priority_upper_bound = 1; +set yb_transaction_priority_lower_bound = 1; +BEGIN TRANSACTION; +SELECT i, j FROM test_scan WHERE i = 1 FOR UPDATE; + i | j +---+--- + 1 | 1 +(1 row) + +show yb_transaction_priority; + yb_transaction_priority +------------------------------ + Highest priority transaction +(1 row) + +COMMIT; +-- Showing yb_transaction_priority outside a transaction block +show yb_transaction_priority; + yb_transaction_priority +------------------------------------------- + 0.000000000 (Normal priority transaction) +(1 row) + -- SET LOCAL is restricted by a function SET option create or replace function myfunc(int) returns text as $$ begin @@ -151,21 +210,21 @@ SHOW plpgsql.extra_foo_warnings; -- but the parameter is set -- test `yb_db_admin` role can set and reset yb_db_admin-allowed PGC_SUSET variables SET SESSION AUTHORIZATION yb_db_admin; SHOW session_replication_role; - session_replication_role + session_replication_role -------------------------- origin (1 row) SET session_replication_role TO replica; SHOW session_replication_role; - session_replication_role + session_replication_role -------------------------- replica (1 row) RESET session_replication_role; SHOW session_replication_role; - session_replication_role + session_replication_role -------------------------- origin (1 row) diff --git a/src/postgres/src/test/regress/sql/yb_guc.sql b/src/postgres/src/test/regress/sql/yb_guc.sql index cd1dcefd017..64a53384aa7 100644 --- a/src/postgres/src/test/regress/sql/yb_guc.sql +++ b/src/postgres/src/test/regress/sql/yb_guc.sql @@ -53,6 +53,39 @@ EXPLAIN SELECT j FROM test_scan; set enable_indexonlyscan = off; EXPLAIN SELECT j FROM test_scan; +-- Show transaction priority. As it is not possible to have a deterministic +-- yb_transaction_priority, we set yb_transaction_priority_lower_bound and +-- yb_transaction_priority_upper_bound to be the same, which forces +-- yb_transaction_priority to be equal to those two. +set yb_transaction_priority_lower_bound = 0.4; +set yb_transaction_priority_upper_bound = 0.4; +BEGIN TRANSACTION; +INSERT INTO test_scan (i, j) values (1, 1), (2, 2), (3, 3); +show yb_transaction_priority; +COMMIT; + +-- Trying to set yb_transaction_priority will be an error +set yb_transaction_priority = 0.3; -- ERROR + +-- High priority transaction +set yb_transaction_priority_lower_bound = 0.4; +set yb_transaction_priority_upper_bound = 0.4; +BEGIN TRANSACTION; +SELECT i, j FROM test_scan WHERE i = 1 FOR UPDATE; +show yb_transaction_priority; +COMMIT; + +-- Highest priority transaction +set yb_transaction_priority_upper_bound = 1; +set yb_transaction_priority_lower_bound = 1; +BEGIN TRANSACTION; +SELECT i, j FROM test_scan WHERE i = 1 FOR UPDATE; +show yb_transaction_priority; +COMMIT; + +-- Showing yb_transaction_priority outside a transaction block +show yb_transaction_priority; + -- SET LOCAL is restricted by a function SET option create or replace function myfunc(int) returns text as $$ begin diff --git a/src/yb/client/transaction.h b/src/yb/client/transaction.h index 7d6fd09548a..fad26102740 100644 --- a/src/yb/client/transaction.h +++ b/src/yb/client/transaction.h @@ -36,12 +36,6 @@ class HybridTime; class Trace; -enum TxnPriorityRequirement { - kLowerPriorityRange, - kHigherPriorityRange, - kHighestPriority -}; - namespace client { using Waiter = boost::function; diff --git a/src/yb/yql/pggate/pg_txn_manager.cc b/src/yb/yql/pggate/pg_txn_manager.cc index a42dbe84f3b..ccd35afb57f 100644 --- a/src/yb/yql/pggate/pg_txn_manager.cc +++ b/src/yb/yql/pggate/pg_txn_manager.cc @@ -87,6 +87,19 @@ uint64_t ConvertHighPriorityTxnBound(double value) { return ConvertBound(value, yb::kHighPriTxnLowerBound, yb::kHighPriTxnUpperBound); } +// Convert uint64_t value in range [minValue, maxValue] to double value in range 0..1 +double ToTxnPriority(uint64_t value, uint64_t minValue, uint64_t maxValue) { + if (value <= minValue) { + return 0.0; + } + + if (value >= maxValue) { + return 1.0; + } + + return static_cast(value - minValue) / (maxValue - minValue); +} + } // namespace extern "C" { @@ -574,5 +587,29 @@ std::string PgTxnManager::TxnStateDebugStr() const { pg_isolation_level); } +double PgTxnManager::GetTransactionPriority() const { + auto priority = txn_->GetPriority(); + if (priority <= yb::kRegularTxnUpperBound) { + return ToTxnPriority(priority, + yb::kRegularTxnLowerBound, + yb::kRegularTxnUpperBound); + } + + return ToTxnPriority(priority, + yb::kHighPriTxnLowerBound, + yb::kHighPriTxnUpperBound); +} + +TxnPriorityRequirement PgTxnManager::GetTransactionPriorityType() const { + auto priority = txn_->GetPriority(); + if (priority <= yb::kRegularTxnUpperBound) { + return kLowerPriorityRange; + } + if (priority < yb::kHighPriTxnUpperBound) { + return kHigherPriorityRange; + } + return kHighestPriority; +} + } // namespace pggate } // namespace yb diff --git a/src/yb/yql/pggate/pg_txn_manager.h b/src/yb/yql/pggate/pg_txn_manager.h index f2b56f4f2ef..9436331422d 100644 --- a/src/yb/yql/pggate/pg_txn_manager.h +++ b/src/yb/yql/pggate/pg_txn_manager.h @@ -95,6 +95,9 @@ class PgTxnManager : public RefCountedThreadSafe { bool IsTxnInProgress() const { return txn_in_progress_; } bool ShouldUseFollowerReads() const { return updated_read_time_for_follower_reads_; } + double GetTransactionPriority() const; + TxnPriorityRequirement GetTransactionPriorityType() const; + private: YB_STRONGLY_TYPED_BOOL(NeedsHigherPriorityTxn); YB_STRONGLY_TYPED_BOOL(SavePriority); diff --git a/src/yb/yql/pggate/pggate.cc b/src/yb/yql/pggate/pggate.cc index fd16509cfc5..66f7ce44166 100644 --- a/src/yb/yql/pggate/pggate.cc +++ b/src/yb/yql/pggate/pggate.cc @@ -1532,6 +1532,14 @@ Status PgApiImpl::RollbackSubTransaction(SubTransactionId id) { return pg_txn_manager_->RollbackSubTransaction(id); } +double PgApiImpl::GetTransactionPriority() const { + return pg_txn_manager_->GetTransactionPriority(); +} + +TxnPriorityRequirement PgApiImpl::GetTransactionPriorityType() const { + return pg_txn_manager_->GetTransactionPriorityType(); +} + void PgApiImpl::ResetCatalogReadTime() { pg_session_->ResetCatalogReadPoint(); } diff --git a/src/yb/yql/pggate/pggate.h b/src/yb/yql/pggate/pggate.h index 7044ea35973..b775a00b49e 100644 --- a/src/yb/yql/pggate/pggate.h +++ b/src/yb/yql/pggate/pggate.h @@ -501,6 +501,8 @@ class PgApiImpl { void ClearSeparateDdlTxnMode(); CHECKED_STATUS SetActiveSubTransaction(SubTransactionId id); CHECKED_STATUS RollbackSubTransaction(SubTransactionId id); + double GetTransactionPriority() const; + TxnPriorityRequirement GetTransactionPriorityType() const; //------------------------------------------------------------------------------------------------ // Expressions. diff --git a/src/yb/yql/pggate/ybc_pg_typedefs.h b/src/yb/yql/pggate/ybc_pg_typedefs.h index da301c0d098..c227f04a369 100644 --- a/src/yb/yql/pggate/ybc_pg_typedefs.h +++ b/src/yb/yql/pggate/ybc_pg_typedefs.h @@ -179,6 +179,12 @@ typedef enum PgDatumKind { YB_YQL_DATUM_LIMIT_MIN, } YBCPgDatumKind; +typedef enum TxnPriorityRequirement { + kLowerPriorityRange, + kHigherPriorityRange, + kHighestPriority +} TxnPriorityRequirement; + // API to read type information. const YBCPgTypeEntity *YBCPgFindTypeEntity(int type_oid); YBCPgDataType YBCPgGetType(const YBCPgTypeEntity *type_entity); diff --git a/src/yb/yql/pggate/ybc_pggate.cc b/src/yb/yql/pggate/ybc_pggate.cc index 3d1d2ef7134..481b5beed3b 100644 --- a/src/yb/yql/pggate/ybc_pggate.cc +++ b/src/yb/yql/pggate/ybc_pggate.cc @@ -934,6 +934,14 @@ YBCStatus YBCPgResetTransactionReadPoint() { return ToYBCStatus(pgapi->ResetTransactionReadPoint()); } +double YBCGetTransactionPriority() { + return pgapi->GetTransactionPriority(); +} + +TxnPriorityRequirement YBCGetTransactionPriorityType() { + return pgapi->GetTransactionPriorityType(); +} + YBCStatus YBCPgRestartReadPoint() { return ToYBCStatus(pgapi->RestartReadPoint()); } diff --git a/src/yb/yql/pggate/ybc_pggate.h b/src/yb/yql/pggate/ybc_pggate.h index 09e4768dcec..11fb0d1b712 100644 --- a/src/yb/yql/pggate/ybc_pggate.h +++ b/src/yb/yql/pggate/ybc_pggate.h @@ -458,6 +458,8 @@ YBCStatus YBCPgExitSeparateDdlTxnMode(); void YBCPgClearSeparateDdlTxnMode(); YBCStatus YBCPgSetActiveSubTransaction(uint32_t id); YBCStatus YBCPgRollbackSubTransaction(uint32_t id); +double YBCGetTransactionPriority(); +TxnPriorityRequirement YBCGetTransactionPriorityType(); // System validation ------------------------------------------------------------------------------- // Validate placement information