### 13.1.2 ALTER DATABASE 语句

[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)

```
ALTER {DATABASE | SCHEMA} [db_name]
    alter_option ...

alter_option: {
    [DEFAULT] CHARACTER SET [=] charset_name
  | [DEFAULT] COLLATE [=] collation_name
  | [DEFAULT] ENCRYPTION [=] {'Y' | 'N'}
  | READ ONLY [=] {DEFAULT | 0 | 1}
}
```

[`更改数据库`](alter-database.html)使您能够更改数据库的整体特征。这些特征存储在数据字典中。该声明要求[`改变`](privileges-provided.html#priv_alter)数据库的权限。[`改变模式`](alter-database.html)是同义词[`更改数据库`](alter-database.html).

如果省略数据库名称，则该语句适用于默认数据库。在这种情况下，如果没有默认数据库，则会发生错误。

对于任何*`改变选项`*从语句中省略，数据库将保留其当前选项值，但更改字符集可能会更改排序规则，反之亦然。

-   [字符集和排序规则选项](alter-database.html#alter-database-charset)

-   [加密选项](alter-database.html#alter-database-encryption)

-   [只读选项](alter-database.html#alter-database-read-only)

#### 字符集和排序规则选项

这`字符集`选项更改默认数据库字符集。这`整理`选项更改默认数据库排序规则。有关字符集和排序规则名称的信息，请参阅[第 10 章，*字符集、排序规则、Unicode*](charset.html).

要查看可用的字符集和排序规则，请使用[`显示字符集`](show-character-set.html)和[`显示整理`](show-collation.html)分别发表声明。看见[第13.7.7.3节，“显示字符集语句”](show-character-set.html)和[第13.7.7.4节，“显示排序语句”](show-collation.html).

创建例程时使用数据库默认值的存储例程将这些默认值作为其定义的一部分。（在存储例程中，如果未明确指定字符集或排序规则，则具有字符数据类型的变量将使用数据库默认值。请参阅。）[第13.1.17节，“创建程序和创建函数语句”](create-procedure.html)。如果更改数据库的默认字符集或排序规则，则必须删除并重新创建任何使用新默认值的存储例程。

#### 加密选项

这个`加密`选项在MySQL 8.0.16中引入，它定义了默认的数据库加密，由数据库中创建的表继承。允许值为`“是的”`（启用加密）和`“不”`（加密已禁用）。只有新创建的表才会继承默认的数据库加密。对于与数据库关联的现有表，它们的加密保持不变。如果[`表_加密_权限_检查`](server-system-variables.html#sysvar_table_encryption_privilege_check)系统变量启用时[`表_加密_管理`](privileges-provided.html#priv_table-encryption-admin)需要特权才能指定不同于[`默认\u表\u加密`](server-system-variables.html#sysvar_default_table_encryption)系统变量。有关更多信息，请参阅[为模式和常规表空间定义加密默认值](innodb-data-encryption.html#innodb-schema-tablespace-encryption-default).

#### 只读选项

[](<>)

这个`只读`选项，在MySQL 8.0.22中引入，控制是否允许修改数据库和其中的对象。允许值为`违约`要么`0`（非只读）和`1`（只读）。此选项对于数据库迁移很有用，因为一个数据库为其`只读`启用后可以迁移到另一个 MySQL 实例，而不用担心在操作过程中可能会更改数据库。

使用 NDB Cluster，使数据库只读一个[**mysqld**](mysqld.html)服务器与其他服务器同步[**mysqld**](mysqld.html)同一集群中的服务器，以便数据库在所有服务器上变为只读[**mysqld**](mysqld.html)服务器。

这`只读`选项，如果启用，将显示在`INFORMATION_SCHEMA` [`SCHEMATA_EXTENSIONS`](information-schema-schemata-extensions-table.html)桌子。看[第 26.3.32 节，“信息\_架构 架构\_扩展表”](information-schema-schemata-extensions-table.html).

[](<>)

这`只读`无法为这些系统架构启用选项：`mysql`,`信息模式`,`性能模式`.

在[`更改数据库`](alter-database.html)声明，`只读`option 与自身的其他实例以及其他选项交互，如下所示：

-   如果多个实例发生错误`只读`冲突（例如，`只读 = 1 只读 = 0`）。

-   一个[`更改数据库`](alter-database.html)仅包含（非冲突）的语句`只读`即使对于只读数据库，也允许使用选项。

-   混合（非冲突）`只读`如果语句之前或之后的数据库的只读状态允许修改，则允许带有其他选项的选项。如果之前和之后的只读状态都禁止更改，则会发生错误。

    无论数据库是否为只读，此语句都会成功：

    ```
    ALTER DATABASE mydb READ ONLY = 0 DEFAULT COLLATE utf8mb4_bin;
    ```

    如果数据库不是只读的，则该语句成功，但如果它已经是只读的，则该语句失败：

    ```
    ALTER DATABASE mydb READ ONLY = 1 DEFAULT COLLATE utf8mb4_bin;
    ```

    启用`只读`影响数据库的所有用户，这些例外不受只读检查的影响：

-   作为服务器初始化、重新启动、升级或复制的一部分，由服务器执行的语句。

-   服务器启动时命名的文件中的语句[`初始化文件`](server-system-variables.html#sysvar_init_file)系统变量。

-   `暂时的`表格；可以创建、更改、删​​除和写入`暂时的`只读数据库中的表。

-   NDB Cluster 非 SQL 插入和更新。

    除了刚刚列出的例外操作，启用`只读`禁止对数据库及其对象的写操作，包括它们的定义、数据和元数据。以下列表详细说明了受影响的 SQL 语句和操作：

-   数据库本身：

    -   [`创建数据库`](create-database.html)

    -   [`更改数据库`](alter-database.html)（除了改变`只读`选项）

    -   [`删除数据库`](drop-database.html)

-   意见：

    -   [`创建视图`](create-view.html)

    -   [`改变视图`](alter-view.html)

    -   [`下拉视图`](drop-view.html)

    -   从调用具有副作用的函数的视图中进行选择。

    -   更新可更新视图。

    -   在可写数据库中创建或删除对象的语句如果影响只读数据库中视图的元数据（例如，使视图有效或无效），则会被拒绝。

-   存储的例程：

    -   [`创建过程`](create-procedure.html)

    -   [`丢弃程序`](drop-procedure.html)

    -   [`称呼`](call.html)（有副作用的程序）

    -   [`创建函数`](create-function.html)

    -   [`拖放功能`](drop-function.html)

    -   [`选择`](select.html)（具有副作用的功能）

    -   对于过程和函数，只读检查遵循预锁定行为。为了[`称呼`](call.html)语句，只读检查是在每个语句的基础上完成的，所以如果一些条件执行的语句写入只读数据库并没有实际执行，调用仍然成功。另一方面，对于在一个内部调用的函数[`选择`](select.html)，函数体的执行发生在预锁定模式下。只要函数中的某个语句写入只读数据库，无论该语句是否实际执行，函数的执行都会失败并出现错误。

-   触发器：

    -   [`创建触发器`](create-trigger.html)

    -   [`下降触发器`](drop-trigger.html)

    -   触发调用。

-   事件：

    -   [`创建事件`](create-event.html)

    -   [`改变事件`](alter-event.html)

    -   [`掉落事件`](drop-event.html)

    -   事件执行：

        -   在数据库中执行事件失败，因为这会更改最后执行时间戳，这是存储在数据字典中的事件元数据。事件执行失败也会导致事件调度程序停止。

        -   如果事件写入只读数据库中的对象，则事件执行失败并出现错误，但事件调度程序不会停止。

-   表：

    -   [`创建表`](create-table.html)

    -   [`更改表`](alter-table.html)

    -   [`创建索引`](create-index.html)

    -   [`删除索引`](drop-index.html)

    -   [`重命名表`](rename-table.html)

    -   [`截断表`](truncate-table.html)

    -   [`删除表`](drop-table.html)

    -   [`删除`](delete.html)

    -   [`插入`](insert.html)

    -   [`导入表`](import-table.html)

    -   [`加载数据`](load-data.html)

    -   [`加载 XML`](load-xml.html)

    -   [`代替`](replace.html)

    -   [`更新`](update.html)

    -   对于子表位于只读数据库中的级联外键，即使子表没有直接受到影响，父表上的更新和删除也会被拒绝。

    -   为一个`合并`表如`创建表 s1.t(i int) 引擎合并联合 (s2.t, s3.t), INSERT_METHOD=...`，以下行为适用：

        -   插入到`合并`桌子 （`插入到 s1.t`) 失败，如果至少其中之一`s1`,`s2`,`s3`是只读的，与插入方法无关。即使插入实际上最终会出现在可写表中，它也会被拒绝。

        -   删除`合并`桌子 （`删除表 s1.t`) 只要成功`s1`不是只读的。允许丢弃一个`合并`引用只读数据库的表。

    一个[`更改数据库`](alter-database.html)语句阻塞，直到所有已访问正在更改的数据库中的对象的并发事务都已提交。相反，访问数据库中对象的写入事务在并发中被更改[`更改数据库`](alter-database.html)块直到[`更改数据库`](alter-database.html)已承诺。

    如果克隆插件用于克隆本地或远程数据目录，则克隆中的数据库将保留它们在源数据目录中的只读状态。只读状态不会影响克隆过程本身。如果不希望在克隆中具有相同的数据库只读状态，则必须在克隆过程完成后显式更改克隆的选项，使用[`更改数据库`](alter-database.html)克隆上的操作。

    当从捐赠者克隆到接受者时，如果接受者有一个只读的用户数据库，克隆将失败并显示错误消息。使数据库可写后，可以重试克隆。

`只读`被允许[`更改数据库`](alter-database.html), 但不是为了[`创建数据库`](create-database.html).但是，对于只读数据库，由[`显示创建数据库`](show-create-database.html)确实包括`只读=1`在注释中指示其只读状态：

```
mysql> ALTER DATABASE mydb READ ONLY = 1;
mysql> SHOW CREATE DATABASE mydb\G
*************************** 1. row ***************************
       Database: mydb
Create Database: CREATE DATABASE `mydb`
                 /*!40100 DEFAULT CHARACTER SET utf8mb4
                          COLLATE utf8mb4_0900_ai_ci */
                 /*!80016 DEFAULT ENCRYPTION='N' */
                 /* READ ONLY = 1 */
```

如果服务器执行一个[`创建数据库`](create-database.html)包含此类注释的语句，服务器将忽略该注释和`只读`选项未处理。这对[**mysql转储**](mysqldump.html)和[**mysql泵**](mysqlpump.html), 使用[`显示创建数据库`](show-create-database.html)生产[`创建数据库`](create-database.html)转储输出中的语句：

-   在转储文件中，[`创建数据库`](create-database.html)只读数据库的语句包含注释`只读`选项。

-   转储文件可以像往常一样恢复，但是因为服务器忽略了注释`只读`选项，恢复的数据库是*不是*只读。如果数据库在恢复后是只读的，则必须执行[`更改数据库`](alter-database.html)手动使其如此。

    假设`数据库`是只读的，您将其转储如下：


```
$> mysqldump --databases mydb > mydb.sql
```

稍后必须执行还原操作[`更改数据库`](alter-database.html)如果`数据库`仍应为只读：

```
$> mysql
mysql> SOURCE mydb.sql;
mysql> ALTER DATABASE mydb READ ONLY = 1;
```

MySQL Enterprise Backup 不受此问题的影响。它像其他任何数据库一样备份和恢复只读数据库，但启用`只读`如果在备份时启用，则在还原时选择该选项。

[`更改数据库`](alter-database.html)被写入二进制日志，所以改变`只读`复制源服务器上的选项也会影响副本。为了防止这种情况发生，必须在执行之前禁用二进制日志记录[`更改数据库`](alter-database.html)陈述。例如，要准备迁移数据库而不影响副本，请执行以下操作：

1.  在单个会话中，禁用二进制日志记录并启用`只读`对于数据库：

    ```
    mysql> SET sql_log_bin = OFF;
    mysql> ALTER DATABASE mydb READ ONLY = 1;
    ```

2.  转储数据库，例如，使用[**mysql转储**](mysqldump.html)要么[**mysql泵**](mysqlpump.html)：

    ```
    $> mysqldump --databases mydb > mydb.sql
    ```

3.  在单个会话中，禁用二进制日志记录并禁用`只读`对于数据库：

    ```
    mysql> SET sql_log_bin = OFF;
    mysql> ALTER DATABASE mydb READ ONLY = 0;
    ```
