You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Vitess supports routing rules for tables, allowing queries targeting one table in a keyspace to be transparently routed to another table in another (or the same) keyspace. This is used during MoveTables workflows for example, to shift traffic between keyspaces as tables are moved.
In order to support moving views in MoveTables, Vitess needs support for routing rules for views.
Views
Views in Vitess are not explicitly defined in the VSchema. VTGates discover views dynamically through schema tracking, and are stored in the VTGate's local VSchema. When a view changes, VTTablets notify VTGates through healthchecks, which VTGate then fetches the views' definitions with the GetSchema RPC.
When VTGates are building the routing rules, they'll first look up the target to see if it's a view. If the view does not exist, it'll treat it as a table as normal. If the view does exist, it'll store the routing rule as a new ViewRoutingRule:
The reason we check if it's a view before we check if it's a table is because tables that do not exist in the VSchema of an unsharded keyspace are assumed to be a table regardless. If we check for the reference as a table first, we would always treat it as a table even if there might exist a view with the same name.
Since views are discovered dynamically, the view might not yet exist in the target keyspace's (VTGate-local) VSchema. For example, in the case of a theoretical MoveTables with views:
MoveTables create initiated with view customer_view
customer_view is created in the target keyspace
Before VTGate is aware this view now exists in the target keyspace, MoveTables creates the routing rules
The VTGate receives notice of the new routing rules, but can't find a view (or table) with the same name in the target keyspace. It stores an error in its local routing rules.
{
"routing_rules": {
"customer_view": "table customer_view not found"
}
}
Soon after, the schema tracker is now aware of the new view, but the routing rules are not updated.
At query time, views are currently replaced with their definition as a derived table. We can update this logic to first look up the view routing rules. If a matching routing rule is found, replace the view with the target view's definition instead. For example, in keyspace source_ks and target_ks, the same view is created:
select*from (select col1, col2 fromtarget_ks.user_view) as user_view
...rather than ...from source_ks.user_view.
Alternatives
Since queries containing a view are rewritten with their definition, we could choose to rely on the underlying tables' routing rules instead of creating explicit routing rules for the views themselves. However, in the case of a MoveTables, this would cause an ambiguous table reference when using global routing, as the view would exist in both keyspaces. Therefore, we require explicit routing rules to disambiguate.
In VTGate, we choose to store only the target keyspace and target view name, rather than the target view's definition. The view's definition is then resolved at query time. Alternatively, we can store the target view's definition directly, which would require updating the routing rule when the view's definition changes.
We can create an entirely new field in VSchema for view routing rules. This means also creating the equivalent ApplyRoutingRules, etc. commands. This approach would allow us to be more explicit instead of trying to treat views and tables similarly, but requires more effort up front.
Implications
The underlying tables that views reference likely have their own routing rules as well. When views are replaced with the target view's definition, the tables will still have their own routing applied as well. In the case of MoveTables, the routing rules will be configured in the same direction, but in the case of manual routing rules, there might be some conflicting routing if users are not careful.
Background
Routing rules
Vitess supports routing rules for tables, allowing queries targeting one table in a keyspace to be transparently routed to another table in another (or the same) keyspace. This is used during
MoveTablesworkflows for example, to shift traffic between keyspaces as tables are moved.In order to support moving views in
MoveTables, Vitess needs support for routing rules for views.Views
Views in Vitess are not explicitly defined in the VSchema. VTGates discover views dynamically through schema tracking, and are stored in the VTGate's local VSchema. When a view changes, VTTablets notify VTGates through healthchecks, which VTGate then fetches the views' definitions with the
GetSchemaRPC.At query time, when a VTGate encounters a view, the view is replaced with its definition as a derived table. For example, for this view:
A query like:
Would be rewritten to:
See the Views RFC for more information.
Proposal
View routing rules can be added in the same way as table routing rules:
{ "rules": [ { "from_table": "my_view", "to_tables": ["target_ks.my_view"] } ] }When VTGates are building the routing rules, they'll first look up the target to see if it's a view. If the view does not exist, it'll treat it as a table as normal. If the view does exist, it'll store the routing rule as a new
ViewRoutingRule:For example, the rule shown above would be stored as:
The view routing rules would then be stored in a new map within the VTGate's
VSchema:Note
The reason we check if it's a view before we check if it's a table is because tables that do not exist in the VSchema of an unsharded keyspace are assumed to be a table regardless. If we check for the reference as a table first, we would always treat it as a table even if there might exist a view with the same name.
Since views are discovered dynamically, the view might not yet exist in the target keyspace's (VTGate-local) VSchema. For example, in the case of a theoretical
MoveTableswith views:MoveTables createinitiated with viewcustomer_viewcustomer_viewis created in the target keyspaceBefore VTGate is aware this view now exists in the target keyspace,
MoveTablescreates the routing rulesThe VTGate receives notice of the new routing rules, but can't find a view (or table) with the same name in the target keyspace. It stores an error in its local routing rules.
{ "routing_rules": { "customer_view": "table customer_view not found" } }Soon after, the schema tracker is now aware of the new view, but the routing rules are not updated.
To work around this, whenever new or updated views are added to the VSchema by the schema tracker, VTGate will rebuild the routing rules so that they can consider the new views.
Query routing
At query time, views are currently replaced with their definition as a derived table. We can update this logic to first look up the view routing rules. If a matching routing rule is found, replace the view with the target view's definition instead. For example, in keyspace
source_ksandtarget_ks, the same view is created:This routing rule:
{ "rules": [ { "from_table": "user_view", "to_tables": ["target_ks.user_view"] } ] }Would cause this query:
To be rewritten to:
...rather than
...from source_ks.user_view.Alternatives
MoveTables, this would cause an ambiguous table reference when using global routing, as the view would exist in both keyspaces. Therefore, we require explicit routing rules to disambiguate.ApplyRoutingRules, etc. commands. This approach would allow us to be more explicit instead of trying to treat views and tables similarly, but requires more effort up front.Implications
MoveTables, the routing rules will be configured in the same direction, but in the case of manual routing rules, there might be some conflicting routing if users are not careful.