diff --git a/pydantic/config.py b/pydantic/config.py
--- a/pydantic/config.py
+++ b/pydantic/config.py
@@ -2,20 +2,20 @@
 from enum import Enum
 from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Tuple, Type, Union
 
+from typing_extensions import Literal, Protocol
+
 from .typing import AnyCallable
 from .utils import GetterDict
 
 if TYPE_CHECKING:
     from typing import overload
 
-    import typing_extensions
-
     from .fields import ModelField
     from .main import BaseModel
 
     ConfigType = Type['BaseConfig']
 
-    class SchemaExtraCallable(typing_extensions.Protocol):
+    class SchemaExtraCallable(Protocol):
         @overload
         def __call__(self, schema: Dict[str, Any]) -> None:
             pass
@@ -63,8 +63,10 @@ class BaseConfig:
     json_encoders: Dict[Union[Type[Any], str], AnyCallable] = {}
     underscore_attrs_are_private: bool = False
 
-    # whether inherited models as fields should be reconstructed as base model
-    copy_on_model_validation: bool = True
+    # whether inherited models as fields should be reconstructed as base model,
+    # and whether such a copy should be shallow or deep
+    copy_on_model_validation: Literal['none', 'deep', 'shallow'] = 'shallow'
+
     # whether `Union` should check all allowed types before even trying to coerce
     smart_union: bool = False
 
diff --git a/pydantic/main.py b/pydantic/main.py
--- a/pydantic/main.py
+++ b/pydantic/main.py
@@ -675,10 +675,28 @@ def __get_validators__(cls) -> 'CallableGenerator':
     @classmethod
     def validate(cls: Type['Model'], value: Any) -> 'Model':
         if isinstance(value, cls):
-            if cls.__config__.copy_on_model_validation:
-                return value._copy_and_set_values(value.__dict__, value.__fields_set__, deep=True)
-            else:
+            copy_on_model_validation = cls.__config__.copy_on_model_validation
+            # whether to deep or shallow copy the model on validation, None means do not copy
+            deep_copy: Optional[bool] = None
+            if copy_on_model_validation not in {'deep', 'shallow', 'none'}:
+                # Warn about deprecated behavior
+                warnings.warn(
+                    "`copy_on_model_validation` should be a string: 'deep', 'shallow' or 'none'", DeprecationWarning
+                )
+                if copy_on_model_validation:
+                    deep_copy = False
+
+            if copy_on_model_validation == 'shallow':
+                # shallow copy
+                deep_copy = False
+            elif copy_on_model_validation == 'deep':
+                # deep copy
+                deep_copy = True
+
+            if deep_copy is None:
                 return value
+            else:
+                return value._copy_and_set_values(value.__dict__, value.__fields_set__, deep=deep_copy)
 
         value = cls._enforce_dict_if_root(value)
 

Thanks for reporting, please can you provide a self contained example that shows the error.
I am experiencing the same, references that would've previously been carried through a hierarchy of types now get broken during validation. I will try to put together a repro and suggest changes to maintain the prior functionality 
https://github.com/samuelcolvin/pydantic/pull/3642/commits/ae408326e70d84510a8e25e8f6a6ae8871df2fd0
here is a fine repro:
https://github.com/PrettyWood/pydantic/blob/ae408326e70d84510a8e25e8f6a6ae8871df2fd0/tests/test_main.py#L1564

That line was changed from `is` to `is not`. This is a breaking change in functionality
Well that's not the same as the error shown above, that's just a change in behaviour.
sure, but its a breaking change in behavior. 
diff --git a/tests/test_main.py b/tests/test_main.py
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -1561,18 +1561,66 @@ class Config:
 
     assert t.user is not my_user
     assert t.user.hobbies == ['scuba diving']
-    assert t.user.hobbies is not my_user.hobbies  # `Config.copy_on_model_validation` does a deep copy
+    assert t.user.hobbies is my_user.hobbies  # `Config.copy_on_model_validation` does a shallow copy
     assert t.user._priv == 13
     assert t.user.password.get_secret_value() == 'hashedpassword'
     assert t.dict() == {'id': '1234567890', 'user': {'id': 42, 'hobbies': ['scuba diving']}}
 
 
+def test_model_exclude_copy_on_model_validation_shallow():
+    """When `Config.copy_on_model_validation` is set and `Config.copy_on_model_validation_shallow` is set,
+    do the same as the previous test but perform a shallow copy"""
+
+    class User(BaseModel):
+        class Config:
+            copy_on_model_validation = 'shallow'
+
+        hobbies: List[str]
+
+    my_user = User(hobbies=['scuba diving'])
+
+    class Transaction(BaseModel):
+        user: User = Field(...)
+
+    t = Transaction(user=my_user)
+
+    assert t.user is not my_user
+    assert t.user.hobbies is my_user.hobbies  # unlike above, this should be a shallow copy
+
+
+@pytest.mark.parametrize('comv_value', [True, False])
+def test_copy_on_model_validation_warning(comv_value):
+    class User(BaseModel):
+        class Config:
+            # True interpreted as 'shallow', False interpreted as 'none'
+            copy_on_model_validation = comv_value
+
+        hobbies: List[str]
+
+    my_user = User(hobbies=['scuba diving'])
+
+    class Transaction(BaseModel):
+        user: User
+
+    with pytest.warns(DeprecationWarning, match="`copy_on_model_validation` should be a string: 'deep', 'shallow' or"):
+        t = Transaction(user=my_user)
+
+    if comv_value:
+        assert t.user is not my_user
+    else:
+        assert t.user is my_user
+    assert t.user.hobbies is my_user.hobbies
+
+
 def test_validation_deep_copy():
     """By default, Config.copy_on_model_validation should do a deep copy"""
 
     class A(BaseModel):
         name: str
 
+        class Config:
+            copy_on_model_validation = 'deep'
+
     class B(BaseModel):
         list_a: List[A]
 
@@ -1987,7 +2035,7 @@ def __hash__(self):
             return id(self)
 
         class Config:
-            copy_on_model_validation = False
+            copy_on_model_validation = 'none'
 
     class Item(BaseModel):
         images: List[Image]

1.9.1 Breaking change with model deep copying
### Checks

* [X] I added a descriptive title to this issue
* [X] I have searched (google, github) for similar issues and couldn't find anything
* [X] I have read and followed [the docs](https://pydantic-docs.helpmanual.io/) and still think this is a bug

<!-- Sorry to sound so draconian, but every second saved replying to issues is time spend improving pydantic :-) -->

# Bug
https://github.com/samuelcolvin/pydantic/pull/3642/files
The above PR changes the way models are copied and has created a breaking change in our code base. When running our test suite we now get the following error:

```log
INTERNALERROR>   File "/Users/worx/ape/src/ape_test/providers.py", line 19, in __init__
INTERNALERROR>     super().__init__(**data)
INTERNALERROR>   File "pydantic/main.py", line 339, in pydantic.main.BaseModel.__init__
INTERNALERROR>   File "pydantic/main.py", line 1038, in pydantic.main.validate_model
INTERNALERROR>   File "pydantic/fields.py", line 857, in pydantic.fields.ModelField.validate
INTERNALERROR>   File "pydantic/fields.py", line 1074, in pydantic.fields.ModelField._validate_singleton
INTERNALERROR>   File "pydantic/fields.py", line 1121, in pydantic.fields.ModelField._apply_validators
INTERNALERROR>   File "pydantic/class_validators.py", line 313, in pydantic.class_validators._generic_validator_basic.lambda12
INTERNALERROR>   File "pydantic/main.py", line 679, in pydantic.main.BaseModel.validate
INTERNALERROR>   File "pydantic/main.py", line 605, in pydantic.main.BaseModel._copy_and_set_values
INTERNALERROR>   File "/Users/worx/.pyenv/versions/3.9.2/lib/python3.9/copy.py", line 146, in deepcopy
INTERNALERROR>     y = copier(x, memo)
INTERNALERROR>   File "/Users/worx/.pyenv/versions/3.9.2/lib/python3.9/copy.py", line 230, in _deepcopy_dict
INTERNALERROR>     y[deepcopy(key, memo)] = deepcopy(value, memo)
INTERNALERROR>   File "/Users/worx/.pyenv/versions/3.9.2/lib/python3.9/copy.py", line 151, in deepcopy
INTERNALERROR>     copier = getattr(x, "__deepcopy__", None)
INTERNALERROR>   File "/Users/worx/ape/src/ape/api/networks.py", line 183, in __getattr__
INTERNALERROR>     return self.get_network(network_name)
INTERNALERROR>   File "/Users/worx/ape/src/ape/api/networks.py", line 320, in get_network
INTERNALERROR>     raise NetworkNotFoundError(network_name)
INTERNALERROR> ape.exceptions.NetworkNotFoundError: No network named '--deepcopy--'.
```
Pinning to 1.9.0 as current fix.

Output of `python -c "import pydantic.utils; print(pydantic.utils.version_info())"`:
```
pydantic version: 1.9.1
            pydantic compiled: True
                 install path: /Users/worx/.pyenv/versions/3.9.2/envs/ape/lib/python3.9/site-packages/pydantic
               python version: 3.9.2 (default, Dec  2 2021, 09:57:33)  [Clang 13.0.0 (clang-1300.0.29.3)]
                     platform: macOS-12.3.1-arm64-arm-64bit
     optional deps. installed: ['typing-extensions']
```
<!-- or if you're using pydantic prior to v1.3, manually include: OS, python version and pydantic version -->

<!-- Please read the [docs](https://pydantic-docs.helpmanual.io/) and search through issues to
confirm your bug hasn't already been reported. -->

<!-- Where possible please include a self-contained code snippet describing your bug: -->

```py
import pydantic

...
```


tests/test_main.py::test_model_exclude_copy_on_model_validation tests/test_main.py::test_model_exclude_copy_on_model_validation_shallow tests/test_main.py::test_copy_on_model_validation_warning[True] tests/test_main.py::test_copy_on_model_validation_warning[False] tests/test_main.py::test_inherited_model_field_untouched
tests/test_main.py::test_success tests/test_main.py::test_ultra_simple_missing tests/test_main.py::test_ultra_simple_failed tests/test_main.py::test_ultra_simple_repr tests/test_main.py::test_default_factory_field tests/test_main.py::test_default_factory_no_type_field tests/test_main.py::test_comparing tests/test_main.py::test_nullable_strings_success tests/test_main.py::test_nullable_strings_fails tests/test_main.py::test_recursion tests/test_main.py::test_recursion_fails tests/test_main.py::test_not_required tests/test_main.py::test_infer_type tests/test_main.py::test_allow_extra tests/test_main.py::test_allow_extra_repr tests/test_main.py::test_forbidden_extra_success tests/test_main.py::test_forbidden_extra_fails tests/test_main.py::test_disallow_mutation tests/test_main.py::test_extra_allowed tests/test_main.py::test_extra_ignored tests/test_main.py::test_set_attr tests/test_main.py::test_set_attr_invalid tests/test_main.py::test_any tests/test_main.py::test_alias tests/test_main.py::test_population_by_field_name tests/test_main.py::test_field_order tests/test_main.py::test_required tests/test_main.py::test_mutability tests/test_main.py::test_immutability[False-False] tests/test_main.py::test_immutability[False-True] tests/test_main.py::test_immutability[True-True] tests/test_main.py::test_not_frozen_are_not_hashable tests/test_main.py::test_with_declared_hash tests/test_main.py::test_frozen_with_hashable_fields_are_hashable tests/test_main.py::test_frozen_with_unhashable_fields_are_not_hashable tests/test_main.py::test_hash_function_give_different_result_for_different_object tests/test_main.py::test_const_validates tests/test_main.py::test_const_uses_default tests/test_main.py::test_const_validates_after_type_validators tests/test_main.py::test_const_with_wrong_value tests/test_main.py::test_const_with_validator tests/test_main.py::test_const_list tests/test_main.py::test_const_list_with_wrong_value tests/test_main.py::test_const_validation_json_serializable tests/test_main.py::test_validating_assignment_pass tests/test_main.py::test_validating_assignment_fail tests/test_main.py::test_validating_assignment_pre_root_validator_fail tests/test_main.py::test_validating_assignment_post_root_validator_fail tests/test_main.py::test_root_validator_many_values_change tests/test_main.py::test_enum_values tests/test_main.py::test_literal_enum_values tests/test_main.py::test_enum_raw tests/test_main.py::test_set_tuple_values tests/test_main.py::test_default_copy tests/test_main.py::test_arbitrary_type_allowed_validation_success tests/test_main.py::test_arbitrary_type_allowed_validation_fails tests/test_main.py::test_arbitrary_types_not_allowed tests/test_main.py::test_type_type_validation_success tests/test_main.py::test_type_type_subclass_validation_success tests/test_main.py::test_type_type_validation_fails_for_instance tests/test_main.py::test_type_type_validation_fails_for_basic_type tests/test_main.py::test_bare_type_type_validation_success tests/test_main.py::test_bare_type_type_validation_fails tests/test_main.py::test_annotation_field_name_shadows_attribute tests/test_main.py::test_value_field_name_shadows_attribute tests/test_main.py::test_class_var tests/test_main.py::test_fields_set tests/test_main.py::test_exclude_unset_dict tests/test_main.py::test_exclude_unset_recursive tests/test_main.py::test_dict_exclude_unset_populated_by_alias tests/test_main.py::test_dict_exclude_unset_populated_by_alias_with_extra tests/test_main.py::test_exclude_defaults tests/test_main.py::test_dir_fields tests/test_main.py::test_dict_with_extra_keys tests/test_main.py::test_root tests/test_main.py::test_root_list tests/test_main.py::test_root_nested tests/test_main.py::test_encode_nested_root tests/test_main.py::test_root_failed tests/test_main.py::test_root_undefined_failed tests/test_main.py::test_parse_root_as_mapping tests/test_main.py::test_parse_obj_non_mapping_root tests/test_main.py::test_parse_obj_nested_root tests/test_main.py::test_untouched_types tests/test_main.py::test_custom_types_fail_without_keep_untouched tests/test_main.py::test_model_iteration tests/test_main.py::test_model_export_nested_list[excluding tests/test_main.py::test_model_export_nested_list[should tests/test_main.py::test_model_export_nested_list[using tests/test_main.py::test_model_export_dict_exclusion[excluding tests/test_main.py::test_model_export_dict_exclusion[using tests/test_main.py::test_model_export_dict_exclusion[exclude tests/test_main.py::test_model_exclude_config_field_merging tests/test_main.py::test_validation_deep_copy tests/test_main.py::test_model_export_exclusion_with_fields_and_config[None-expected0-kinds0] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[None-expected0-kinds1] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[None-expected0-kinds2] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[None-expected0-kinds3] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[None-expected0-kinds4] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[None-expected0-kinds5] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[None-expected0-kinds6] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[exclude1-expected1-kinds0] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[exclude1-expected1-kinds1] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[exclude1-expected1-kinds2] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[exclude1-expected1-kinds3] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[exclude1-expected1-kinds4] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[exclude1-expected1-kinds5] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[exclude1-expected1-kinds6] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[exclude2-expected2-kinds0] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[exclude2-expected2-kinds1] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[exclude2-expected2-kinds2] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[exclude2-expected2-kinds3] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[exclude2-expected2-kinds4] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[exclude2-expected2-kinds5] tests/test_main.py::test_model_export_exclusion_with_fields_and_config[exclude2-expected2-kinds6] tests/test_main.py::test_model_export_exclusion_inheritance tests/test_main.py::test_model_export_with_true_instead_of_ellipsis tests/test_main.py::test_model_export_inclusion tests/test_main.py::test_model_export_inclusion_inheritance tests/test_main.py::test_custom_init_subclass_params tests/test_main.py::test_update_forward_refs_does_not_modify_module_dict tests/test_main.py::test_two_defaults tests/test_main.py::test_default_factory tests/test_main.py::test_default_factory_called_once tests/test_main.py::test_default_factory_called_once_2 tests/test_main.py::test_default_factory_validate_children tests/test_main.py::test_default_factory_parse tests/test_main.py::test_none_min_max_items tests/test_main.py::test_reuse_same_field tests/test_main.py::test_base_config_type_hinting tests/test_main.py::test_allow_mutation_field tests/test_main.py::test_repr_field tests/test_main.py::test_inherited_model_field_copy tests/test_main.py::test_mapping_retains_type_subclass tests/test_main.py::test_mapping_retains_type_defaultdict tests/test_main.py::test_mapping_retains_type_fallback_error tests/test_main.py::test_typing_coercion_dict tests/test_main.py::test_typing_non_coercion_of_dict_subclasses tests/test_main.py::test_typing_coercion_defaultdict tests/test_main.py::test_typing_coercion_counter tests/test_main.py::test_typing_counter_value_validation tests/test_main.py::test_class_kwargs_config tests/test_main.py::test_class_kwargs_config_json_encoders tests/test_main.py::test_class_kwargs_config_and_attr_conflict tests/test_main.py::test_class_kwargs_custom_config