> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-parallel-read-in-order-multi-part.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> `settings` 的约束可在 `user.xml` 配置文件的 `profiles` 部分中定义，并禁止用户通过 `SET` 查询更改其中的某些设置。

# 设置约束

<h2 id="overview">
  概述
</h2>

在 ClickHouse 中，设置上的“约束”指的是可应用于设置的限制和规则。这些约束有助于维持数据库的稳定性、安全性以及行为的可预测性。

<h2 id="defining-constraints">
  定义约束
</h2>

可以在 `user.xml`
配置文件的 `profiles` 部分中定义设置约束。这样可以禁止用户使用
[`SET`](/zh/reference/statements/set) 语句更改某些设置。

约束的定义如下：

```xml theme={null}
<profiles>
  <user_name>
    <constraints>
      <setting_name_1>
        <min>lower_boundary</min>
      </setting_name_1>
      <setting_name_2>
        <max>upper_boundary</max>
      </setting_name_2>
      <setting_name_3>
        <min>lower_boundary</min>
        <max>upper_boundary</max>
      </setting_name_3>
      <setting_name_4>
        <readonly/>
      </setting_name_4>
      <setting_name_5>
        <min>lower_boundary</min>
        <max>upper_boundary</max>
        <changeable_in_readonly/>
      </setting_name_5>
      <setting_name_6>
        <min>lower_boundary</min>
        <max>upper_boundary</max>
        <disallowed>value1</disallowed>
        <disallowed>value2</disallowed>
        <disallowed>value3</disallowed>
        <changeable_in_readonly/>
      </setting_name_6>
    </constraints>
  </user_name>
</profiles>
```

如果用户试图违反这些约束，则会抛出异常，并且
该设置保持不变。

<h2 id="types-of-constraints">
  约束的类型
</h2>

ClickHouse 支持以下几种约束：

* `min`
* `max`
* `disallowed`
* `readonly` (别名为 `const`)
* `changeable_in_readonly`

`min` 和 `max` 约束用于为数值型设置指定上下界，
并且可以结合使用。

`disallowed` 约束可用于指定某个设置不允许使用的特定值。

`readonly` 或 `const` 约束表示用户完全无法更改相应设置。

`changeable_in_readonly` 这种约束类型允许用户在 `min`/`max` 范围内更改该设置，
即使 `readonly` 设置为 `1` 也是如此；
否则，在 `readonly=1` 模式下将不允许更改设置。

<Note>
  仅当启用 `settings_constraints_replace_previous` 时，才支持 `changeable_in_readonly`：

  ```xml theme={null}
  <access_control_improvements>
    <settings_constraints_replace_previous>true</settings_constraints_replace_previous>
  </access_control_improvements>
  ```
</Note>

<h3 id="readonly-changeable-in-readonly">
  不要让 `readonly` 在只读模式下可更改
</h3>

<Warning>
  在每个 profile 中都不要把 `readonly` 加入 `changeable_in_readonly` 列表，包括未分配给任何人的 profile：任何 session 都可以按名称选择 profile。
</Warning>

不要把 `readonly` 本身标记为 `changeable_in_readonly`。否则，以 `readonly = 1` 启动的 session 就可以执行 `SET readonly = 0`，从而重新获得执行写入查询的能力 (只要其现有特权本就允许) ，除非同一约束也禁止了 `0`。

这一点适用于你定义的每个 profile，而不仅限于已分配的 profile：

* `SET profile` 不做访问检查，因此任何 session 都可以按名称选择任意 profile。即使某个 profile 未分配给任何人，它依然可以被选用，不过它随后更改的设置仍需通过该 session 中当前已生效约束的检查。
* 通过 HTTP 访问时，只有在实际生效值本来为 `0` 的情况下，`GET` 请求才会被强制设为 `readonly = 2`。因此，如果某个 profile 设置了 `readonly = 1`，却又允许在只读模式下更改 `readonly`，这项保护便会形同虚设，因为一个 `GET` 请求即可将其改回 `0` 并执行写入。

<h2 id="multiple-constraint-profiles">
  多个约束 profile
</h2>

如果某个用户同时启用了多个 profile，则约束会合并。
合并过程取决于 `settings_constraints_replace_previous`：

* **true** (推荐) ：相同设置的约束会在
  合并过程中被替换，因此会使用最后一个约束，之前的所有约束都会被忽略。
  这也包括新约束中未设置的字段。
* **false** (默认) ：相同设置的约束会按如下方式合并：
  每种未设置的约束类型都会沿用前一个 profile 中的值，而每种
  已设置的约束类型都会替换为新 profile 中的值。

<h2 id="read-only">
  只读模式
</h2>

只读模式由 `readonly` setting 启用，注意不要将其与 `readonly` CONSTRAINT 类型混淆。当 `readonly = 1` 时，原本会被拒绝修改的 setting，若有 `changeable_in_readonly` CONSTRAINT 允许，仍可被更改。该 setting 各取值的含义，请参阅
[settings 参考](/zh/reference/settings/session-settings/other#readonly)；各取值分别允许哪些类别的查询，以及 HTTP interface 如何设置它，请参阅
[查询权限](/zh/concepts/features/configuration/settings/permissions-for-queries#readonly)。

<h3 id="example-read-only">
  示例
</h3>

让 `users.xml` 包含以下内容：

```xml theme={null}
<profiles>
  <default>
    <max_memory_usage>10000000000</max_memory_usage>
    <force_index_by_date>0</force_index_by_date>
    ...
    <constraints>
      <max_memory_usage>
        <min>5000000000</min>
        <max>20000000000</max>
      </max_memory_usage>
      <force_index_by_date>
        <readonly/>
      </force_index_by_date>
    </constraints>
  </default>
</profiles>
```

以下查询都会引发异常：

```sql theme={null}
SET max_memory_usage=20000000001;
SET max_memory_usage=4999999999;
SET force_index_by_date=1;
```

```text theme={null}
Code: 452, e.displayText() = DB::Exception: Setting max_memory_usage should not be greater than 20000000000.
Code: 452, e.displayText() = DB::Exception: Setting max_memory_usage should not be less than 5000000000.
Code: 452, e.displayText() = DB::Exception: Setting force_index_by_date should not be changed.
```

<Note>
  `default` profile 的处理方式较为特殊：为 `default` profile 定义的所有
  约束都会成为默认约束，因此会对所有用户生效，
  直到针对这些用户显式覆盖这些约束为止。
</Note>

<h2 id="constraints-on-merge-tree-settings">
  MergeTree 设置的约束
</h2>

可以为 [MergeTree 设置](/zh/reference/settings/merge-tree-settings)定义约束。
这些约束会在创建使用 MergeTree 引擎的表时
或更改其存储设置时生效。

在 `<constraints>` 部分中引用时，
MergeTree 设置名称必须添加 `merge_tree_` 前缀。

<h3 id="example-mergetree">
  示例
</h3>

您可以禁止创建明确指定了 `storage_policy` 的新表

```xml theme={null}
<profiles>
  <default>
    <constraints>
      <merge_tree_storage_policy>
        <const/>
      </merge_tree_storage_policy>
    </constraints>
  </default>
</profiles>
```
