|
38 | 38 | #include "yb/client/table.h" |
39 | 39 | #include "yb/client/table_alterer.h" |
40 | 40 | #include "yb/client/transaction.h" |
| 41 | +#include "yb/client/transaction_manager.h" |
41 | 42 | #include "yb/client/yb_op.h" |
42 | 43 |
|
43 | 44 | #include "yb/common/common.pb.h" |
@@ -117,6 +118,11 @@ DEFINE_test_flag( |
117 | 118 | "Add several unknown tables while processing perfrom request. " |
118 | 119 | "It is expected that opening of such tables will fail"); |
119 | 120 |
|
| 121 | +DEFINE_test_flag(bool, perform_ignore_pg_is_region_local, false, |
| 122 | + "Ignore the is_all_region_local field of PgPerformOptionsPB. The intended state is for " |
| 123 | + "everything to work when this field is not set, as the field is only left in for upgrade from " |
| 124 | + "older versions and to be removed in the future."); |
| 125 | + |
120 | 126 | DECLARE_bool(vector_index_dump_stats); |
121 | 127 | DECLARE_bool(yb_enable_cdc_consistent_snapshot_streams); |
122 | 128 | DECLARE_bool(ysql_enable_db_catalog_version_mode); |
@@ -1518,6 +1524,10 @@ template <> |
1518 | 1524 | return DoTrackSharedMemoryPgMethodExecution(wait_state, metadata, "AcquireObjectLock"); |
1519 | 1525 | } |
1520 | 1526 |
|
| 1527 | +PgTablespaceOid GetOpTablespaceOid(const PgPerformOpPB& op) { |
| 1528 | + return op.has_write() ? op.write().tablespace_oid() : op.read().tablespace_oid(); |
| 1529 | +} |
| 1530 | + |
1521 | 1531 | } // namespace |
1522 | 1532 |
|
1523 | 1533 | class PgClientSession::Impl { |
@@ -3681,23 +3691,52 @@ class PgClientSession::Impl { |
3681 | 3691 | } |
3682 | 3692 |
|
3683 | 3693 | TransactionFullLocality GetTargetTransactionLocality(const PgPerformRequestPB& request) const { |
3684 | | - if (!FLAGS_use_tablespace_based_transaction_placement && |
3685 | | - !request.options().force_tablespace_locality()) { |
3686 | | - return request.options().is_all_region_local() |
3687 | | - ? TransactionFullLocality::RegionLocal() : TransactionFullLocality::Global(); |
| 3694 | + auto tablespace_oids = request.ops() | std::views::transform(GetOpTablespaceOid); |
| 3695 | + |
| 3696 | + if (FLAGS_use_tablespace_based_transaction_placement || |
| 3697 | + request.options().force_tablespace_locality()) { |
| 3698 | + if (auto oid = request.options().force_tablespace_locality_oid()) { |
| 3699 | + return TransactionFullLocality::TablespaceLocal(oid); |
| 3700 | + } |
| 3701 | + return CalculateTablespaceBasedLocality(tablespace_oids); |
3688 | 3702 | } |
3689 | 3703 |
|
3690 | | - if (auto oid = request.options().force_tablespace_locality_oid()) { |
3691 | | - return TransactionFullLocality::TablespaceLocal(oid); |
| 3704 | + // TODO: is_all_region_local() handles exactly two cases that tablespace oid check does not: |
| 3705 | + // 1. until upgrade is finalized (enable_tablespace_based_transaction_placement autoflag on |
| 3706 | + // master), tablespace oid check does not work, so it is needed to avoid global latencies |
| 3707 | + // during the upgrade. This is only for upgrades from before 2025.1.2/2025.2.0. |
| 3708 | + // 2. if auto_create_local_transaction_tables is OFF (not default), and transaction tables |
| 3709 | + // are manually created, tablespace oid will not be mapped to a transaction table, and |
| 3710 | + // TablespaceIsRegionLocal() returns false. But this case is not really supported, aside |
| 3711 | + // from use setting up some unit tests. |
| 3712 | + // Once these are no longer of concern, is_all_region_local and corresponding code in |
| 3713 | + // pggate/pg can be removed. |
| 3714 | + if (!FLAGS_TEST_perform_ignore_pg_is_region_local && request.options().is_all_region_local()) { |
| 3715 | + return TransactionFullLocality::RegionLocal(); |
3692 | 3716 | } |
| 3717 | + return CalculateRegionBasedLocality(tablespace_oids); |
| 3718 | + } |
| 3719 | + |
| 3720 | + TransactionFullLocality CalculateRegionBasedLocality( |
| 3721 | + std::ranges::range auto&& tablespace_oids) const { |
| 3722 | + auto& transaction_manager = context_.transaction_manager_provider(); |
| 3723 | + bool all_region_local = transaction_manager.RegionLocalTransactionsPossible(); |
| 3724 | + for (PgTablespaceOid oid : tablespace_oids) { |
| 3725 | + all_region_local = all_region_local && transaction_manager.TablespaceIsRegionLocal(oid); |
| 3726 | + } |
| 3727 | + return all_region_local |
| 3728 | + ? TransactionFullLocality::RegionLocal() : TransactionFullLocality::Global(); |
| 3729 | + } |
3693 | 3730 |
|
| 3731 | + TransactionFullLocality CalculateTablespaceBasedLocality( |
| 3732 | + std::ranges::range auto&& tablespace_oids) const { |
| 3733 | + auto& transaction_manager = context_.transaction_manager_provider(); |
3694 | 3734 | PgTablespaceOid tablespace_oid = kInvalidOid; |
3695 | | - for (const auto& op : request.ops()) { |
3696 | | - PgTablespaceOid oid = |
3697 | | - op.has_write() ? op.write().tablespace_oid() : op.read().tablespace_oid(); |
3698 | | - if (tablespace_oid == kInvalidOid) { |
| 3735 | + for (PgTablespaceOid oid : tablespace_oids) { |
| 3736 | + if (tablespace_oid == kInvalidOid || |
| 3737 | + transaction_manager.TablespaceContainsTablespace(oid, tablespace_oid)) { |
3699 | 3738 | tablespace_oid = oid; |
3700 | | - } else if (tablespace_oid != oid) { |
| 3739 | + } else if (!transaction_manager.TablespaceContainsTablespace(tablespace_oid, oid)) { |
3701 | 3740 | return TransactionFullLocality::Global(); |
3702 | 3741 | } |
3703 | 3742 | } |
|
0 commit comments