> ## Documentation Index
> Fetch the complete documentation index at: https://villagesql.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 管理扩展

> 监控、排查并管理 VillageSQL 扩展

## 查看已安装的扩展

使用 INFORMATION\_SCHEMA 视图查询已安装的扩展：

```sql theme={null}
SELECT * FROM INFORMATION_SCHEMA.EXTENSIONS;
```

**输出：**

```
+------------------+-------------------+
| EXTENSION_NAME   | EXTENSION_VERSION |
+------------------+-------------------+
| vsql_complex     | 0.0.1             |
| vsql_uuid        | 0.0.3             |
+------------------+-------------------+
```

**用法：**

* 可以在交互式会话和脚本中使用
* 标准 SQL 接口，与 MySQL 工具兼容

***

## 检查扩展函数

验证扩展函数在安装后是否正常工作：

```sql theme={null}
-- Test a function directly
SELECT complex_abs('(1.0,2.0)');
```

***

## 扩展目录

检查 VillageSQL 查找 `.veb` 文件的位置：

```sql theme={null}
SHOW VARIABLES LIKE 'veb_dir';
```

**列出可用的扩展：**

```bash theme={null}
ls -la /path/to/veb_dir/*.veb
```

<h3 id="configuring-veb_dir">
  配置 veb\_dir
</h3>

要更改扩展目录的位置，请在 MySQL 配置文件中设置 `veb_dir`：

**my.cnf / my.ini：**

```ini theme={null}
[mysqld]
veb_dir=/custom/path/to/extensions/
```

**要求：**

* 路径必须是绝对路径（而不是相对路径）
* 目录必须在服务器启动之前存在
* MySQL 用户必须对该目录具有读取权限
* 仅支持一个 `veb_dir`（不能有多个路径）
* 更改后需要重新启动服务器才能生效

**重启后验证：**

```sql theme={null}
SHOW VARIABLES LIKE 'veb_dir';
```

***

## 故障排除

### 快速参考

| 问题            | 快速解决方法                                                   |
| ------------- | -------------------------------------------------------- |
| 找不到扩展         | 验证 `.veb` 文件是否存在于 `veb_dir` 中，并且名称正确                     |
| 权限被拒绝         | 检查权限：`chmod 644 extension.veb`                           |
| 无法卸载：类型正在使用   | 尝试 `UNINSTALL EXTENSION`；错误会通过名称标识阻止的列                   |
| 版本不匹配         | 重新启动服务器以清除缓存                                             |
| 更新后扩展显示旧行为    | `UNINSTALL` 然后 `INSTALL`；如果需要，清除 `.veb_expansion_cache/` |
| 无法比较类型 X 和 Y  | 两侧都必须使用相同的自定义类型                                          |
| 无法隐式转换为非自定义类型 | 要比较的字面量或列与自定义类型不兼容                                       |

### 找不到扩展

**错误：** `Extension 'my_extension' not found`

**调试步骤：**

```bash theme={null}
# 1. Check veb_dir location
mysql -u root -p -e "SHOW VARIABLES LIKE 'veb_dir';"

# 2. List .veb files
ls -la /path/to/veb_dir/

# 3. Verify filename matches extension name
# File: my_extension.veb
# Install: INSTALL EXTENSION my_extension;

# 4. Check permissions
ls -l /path/to/veb_dir/my_extension.veb
sudo chmod 644 /path/to/veb_dir/my_extension.veb
```

### 安装后函数不可用

**错误：** `FUNCTION my_func does not exist`

**调试步骤：**

```sql theme={null}
-- 1. Verify extension installed
SELECT * FROM INFORMATION_SCHEMA.EXTENSIONS WHERE EXTENSION_NAME = 'my_extension';
```

### 更新后扩展显示旧行为

**症状：** 在替换 `.veb` 文件并重新安装后，扩展仍然
运行旧代码。

**原因：** VillageSQL 会在第一次加载时将 `.veb` 文件扩展到 `{datadir}/.veb_expansion_cache/`。如果您
在不先运行 `UNINSTALL EXTENSION` 的情况下复制新的 `.veb`，服务器将继续
使用先前扩展的 `.so`，该 `.so` 已经加载到内存中。

**解决方案：** 始终遵循完整的 UNINSTALL → 替换 → INSTALL 流程：

```sql theme={null}
UNINSTALL EXTENSION my_extension;
```

然后，替换 `veb_dir` 中的 `.veb` 文件并重新安装：

```sql theme={null}
INSTALL EXTENSION my_extension;
```

如果扩展仍然显示旧行为，请在重新安装之前清除扩展缓存：

```bash theme={null}
rm -rf {datadir}/.veb_expansion_cache/my_extension/
```

```sql theme={null}
INSTALL EXTENSION my_extension;
```

***

### 无法卸载扩展

**错误：** `Cannot uninstall extension: types in use`

**解决方案：**

```sql theme={null}
-- Attempt uninstall; the error identifies blocking columns by name
UNINSTALL EXTENSION my_extension;
-- If blocked: ERROR HY000: Cannot drop extension `my_extension` as 1 column(s) depend on it,
--             e.g. mydb.mytable.my_column has type MYTYPE

-- Drop or alter the identified column(s), then retry
DROP TABLE mydb.mytable;
-- OR
ALTER TABLE mydb.mytable DROP COLUMN my_column;

UNINSTALL EXTENSION my_extension;
```

### 库加载错误

**错误：** `Cannot load library: undefined symbol`

**原因：**

* 缺少库依赖项
* ABI 兼容性不匹配
* MySQL 版本不正确

**调试：**

```bash theme={null}
# Check library dependencies (Linux)
ldd {datadir}/.veb_expansion_cache/my_extension/<sha256>/lib/my_extension.so

# Check library dependencies (macOS)
otool -L {datadir}/.veb_expansion_cache/my_extension/<sha256>/lib/my_extension.so
```

### 扩展名称验证错误

**错误：** `Failed to load VEF extension 'extension_name'` with log message `Extension name mismatch`

**原因：** `manifest.json` 中的扩展名称与 VEB 文件名不匹配。

**调试步骤：**

1. **检查 VEB 文件名是否与清单文件匹配：**
   ```bash theme={null}
   # VEB filename: my_extension.veb
   # manifest.json should have:
   {
     "name": "my_extension",  # Must match VEB filename (without .veb)
     ...
   }
   ```

2. **验证 manifest.json 中的 name 字段：**
   ```bash theme={null}
   # Extract and check manifest from VEB
   tar -xOf /path/to/veb_dir/my_extension.veb manifest.json | grep name
   ```

**解决方案：**

两个名称必须完全相同，使用下划线（请参阅[扩展命名约定](/docs/zh/mysql-8.4/0.0.4/install#extension-naming-conventions)）：

* VEB 文件名：`my_extension.veb`
* manifest.json：`"name": "my_extension"`

**常见错误：**

* 在清单文件中使用连字符：`"name": "my-extension"` ❌
* VEB 文件名不匹配：`my-extension.veb` 与 `"name": "my_extension"` ❌

**正确示例：**

```json theme={null}
// manifest.json
{
  "name": "my_extension",
  "version": "1.0.0"
}
```

```cpp theme={null}
// extension.cc
VEF_GENERATE_ENTRY_POINTS(
  make_extension()
    .func(...)
)
```

```bash theme={null}
# VEB filename
my_extension.veb
```

### 自定义类型比较错误

**错误：** `Cannot compare types X and Y in =`

**原因：** 比较的两侧都是自定义类型，但来自不同的类型或扩展。

```sql theme={null}
-- Example: comparing COMPLEX with UUID in a WHERE clause
SELECT * FROM t WHERE complex_col = uuid_col;
-- ERROR: Cannot compare types vsql_complex.COMPLEX and vsql_uuid.UUID in =
```

**解决方案：** 确保比较的两侧使用相同的自定义类型。如果需要跨类型进行比较，请使用适当的类型转换函数显式转换一侧。

***

**错误：** `Unable to implicitly cast a non-custom type during compare with a custom type in =`

**原因：** 比较的一侧是自定义类型列，另一侧是无法自动转换为该类型的字面量或列。

```sql theme={null}
-- Example: comparing a custom type with an integer literal
SELECT * FROM t WHERE complex_col = 42;
-- ERROR: Unable to implicitly cast a non-custom type during compare...
```

**解决方案：** 使用类型的编码函数，字面字符串会自动转换为自定义类型。对于其他类型（整数、浮点数），请使用显式转换函数：

```sql theme={null}
-- Use a string literal instead (auto-cast works)
SELECT * FROM t WHERE complex_col = '(1.0,2.0)';

-- Or use the type's from_string method explicitly
SELECT * FROM t WHERE complex_col = COMPLEX::from_string('(1.0,2.0)');
```

***

## 监控扩展使用情况

### 查询性能

使用 performance\_schema 跟踪 VDF 执行时间：

```sql theme={null}
-- Enable statement instrumentation
UPDATE performance_schema.setup_instruments
SET ENABLED = 'YES', TIMED = 'YES'
WHERE NAME LIKE '%statement%';

-- Query VDF execution times
SELECT
    DIGEST_TEXT,
    COUNT_STAR as executions,
    ROUND(SUM_TIMER_WAIT/1000000000, 2) as total_ms,
    ROUND(AVG_TIMER_WAIT/1000000000, 2) as avg_ms
FROM performance_schema.events_statements_summary_by_digest
WHERE DIGEST_TEXT LIKE '%complex_%'
ORDER BY total_ms DESC
LIMIT 10;
```

### 自定义类型使用情况

跟踪哪些表使用自定义类型：

```sql theme={null}
-- Find all columns using custom extension types
SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE LIKE '%.%'
ORDER BY DATA_TYPE, TABLE_SCHEMA, TABLE_NAME;
```

## 更新扩展

要将扩展更新到较新版本，请使用手动更新过程：

<Note>
  `ALTER EXTENSION UPDATE` 尚未支持，计划在未来的版本中提供。
</Note>

### 手动更新过程

1. **卸载当前版本：**
   ```sql theme={null}
   UNINSTALL EXTENSION extension_name;
   ```

2. **替换 `.veb` 文件：**
   ```bash theme={null}
   # Remove old .veb file
   sudo rm /path/to/veb_dir/extension_name.veb

   # Copy new .veb file
   sudo cp new_extension_name.veb /path/to/veb_dir/
   ```

3. **安装新版本：**
   ```sql theme={null}
   INSTALL EXTENSION extension_name;
   ```

4. **验证更新：**
   ```sql theme={null}
   SELECT EXTENSION_VERSION
   FROM INFORMATION_SCHEMA.EXTENSIONS
   WHERE EXTENSION_NAME = 'extension_name';
   ```

<Warning>
  **数据安全：** 如果表使用来自扩展的自定义类型，则必须在卸载之前删除或修改这些表。首先备份数据。
</Warning>

**示例：**

```sql theme={null}
-- Find columns using vsql_complex types before updating
SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE LIKE 'vsql_complex.%';

-- If columns exist, back up data and drop/alter them first
-- Then proceed with update
UNINSTALL EXTENSION vsql_complex;
-- (replace .veb file)
INSTALL EXTENSION vsql_complex;
```

***

## 清理

### 移除孤立的扩展目录

VillageSQL 将 `.veb` 文件扩展到 `{datadir}/.veb_expansion_cache/{name}/{sha256}/`。旧版本会随着时间的推移而累积。

```bash theme={null}
# List expansion directories (replace {datadir} with your actual datadir path)
ls -la {datadir}/.veb_expansion_cache/

# Compare with installed extensions
mysql -u root -p -e "SELECT EXTENSION_NAME FROM INFORMATION_SCHEMA.EXTENSIONS;"

# Find the actual SHA256 directory name for a specific extension
ls {datadir}/.veb_expansion_cache/my_extension/

# Remove the unused SHA256 directory using the name shown above
rm -rf {datadir}/.veb_expansion_cache/my_extension/<sha256-from-ls>/
```

<Note>
  服务器重启会自动清理孤立的扩展目录。
</Note>

***

<h2 id="replication">
  复制
</h2>

自定义类型需要 ROW 格式的 binlog。对于具有自定义类型列的表，不支持 STATEMENT 和 MIXED 模式。对自定义类型列执行的 INSERT、UPDATE、DELETE 和 ALTER TABLE 操作在 ROW 格式中都能正确复制。

`INSTALL EXTENSION` 不会复制——每个服务器管理自己的扩展。在复制开始之前，在每个副本上安装扩展，并使用与源相同的版本。服务器强制执行精确的版本匹配；版本不匹配会停止复制。

如果副本遇到它不识别的自定义类型，则复制将在 DDL 语句处停止——在 `CREATE TABLE` 或 `ALTER TABLE` 处，在任何依赖的 DML 应用之前。安装正确的扩展版本，然后恢复：

```sql theme={null}
INSTALL EXTENSION my_extension;
START REPLICA SQL_THREAD;
```

`mysqldump` 在输出中保留完全限定的自定义类型名称。只要在导入转储之前在目标服务器上安装了扩展，逻辑恢复就可以工作。

<Warning>
  尚未测试与 Clone 插件、XtraBackup 和 InnoDB Cluster / Group Replication 的行为。在生产环境中依赖它之前，请测试您的恢复路径。
</Warning>

***

## 在 Docker 中使用扩展

在 Docker 中运行 VillageSQL 时，将本地目录挂载为 `veb_dir`，以便您可以从主机添加 `.veb` 文件，而无需重新构建容器。

**Docker Compose 示例：**

```yaml theme={null}
services:
  villagesql:
    image: villagesql/server:stable
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
    ports:
      - "3306:3306"
    volumes:
      - ./extensions:/usr/lib/veb
    command: --veb_dir=/usr/lib/veb
```

将 `.veb` 文件复制到主机上的 `./extensions/` 中，然后从 SQL 安装：

```sql theme={null}
INSTALL EXTENSION my_extension;
```

要验证正在运行的服务器正在使用的目录：

```sql theme={null}
SHOW VARIABLES LIKE 'veb_dir';
```

***

## 获取帮助

如果您遇到此处未涵盖的问题：

1. **检查错误日志：** 大多数扩展错误都带有详细信息记录在日志中。
2. **查看扩展文档：** 扩展特定的故障排除方法可能存在。
3. **在 Discord 上提问：** 加入 [VillageSQL Discord](https://discord.gg/KSr6whd3Fr)。
4. **提交问题：** 在 [GitHub Issues](https://github.com/villagesql/villagesql-server/issues) 上报告错误。

***

## 后续步骤

<CardGroup cols={2}>
  <Card title="系统参考" icon="book" href="/docs/zh/mysql-8.4/0.0.4/reference">
    查询系统表和视图
  </Card>

  <Card title="卸载扩展" icon="trash" href="/docs/zh/mysql-8.4/0.0.4/uninstall">
    安全地删除扩展
  </Card>

  <Card title="扩展架构" icon="sitemap" href="/docs/zh/mysql-8.4/0.0.4/architecture">
    了解内部结构
  </Card>
</CardGroup>
