# OceanBase 的 MySQL 兼容性简介

MySQL 兼容性主要看表的数据类型、业务 SQL 的兼容性。
MySQL 的函数、触发器、存储过程 在 OceanBase MySQL 里支持的并不好，也不推荐用。所以本章数据迁移就只包含数据库表对象及其数据的迁移。

## 支持的数据类型

OceanBase 数据库支持的数据类型有：

+ 数值类型
    - 整数类型：BOOL/BOOLEAN、TINYINT、SMALLINT、MEDIUMINT、INT/INTEGER、BIGINT
    - 定点类型：DECIMAL/NUMERIC
    - 浮点类型：FLOAT、DOUBLE
    - Bit-Value 类型：BIT
+ 日期时间类型
    - DATETIME、TIMESTAMP、DATE、TIME、YEAR
+ 字符类型
    - VARCHAR、VARBINARY、CHAR、BINARY、enum、set
+ 大对象类型
    - TINYTEXT、TINYBLOB、TEXT、BLOB、MEDIUMTEXT、MEDIUMBLOB、LONGTEXT、LONGBLOB
    - OceanBase 的大对象目前大小不能超过 48MB 。

与 MySQL 数据库对比，OceanBase 数据库暂不支持空间数据类型和  JSON  数据类型，其他类别的数据类型除了大对象外，支持情况是等于或大于 MySQL 数据库的。


## 支持的SQL 语法

常用的 SQL 这里主要列举 查询和修改 SQL 。

+ `SELECT`
    - 支持大部分查询功能，包括支持单、多表查询；支持子查询；支持内连接、半连接以及外连接；支持分组、聚合；常见的概率、线性回归等数据挖掘函数等
    - 支持如下集合操作：
    `union`、`union all`、`intersect` 、`minus` 
    - 不支持 `SELECT … FOR SHARE …` 语法


支持通过如下方式查看执行计划：

```sql
EXPLAIN <SQL Statement> \G

EXPLAIN extended_noaddr <SQL Statement> \G

EXPLAIN extended <SQL Statement> \G
```


+ `INSERT`
    - 支持单行和多行插入，同时还支持指定分区插入
    - 支持 `INSERT INTO … SELECT …` 语句

+ `UPDATE`
    - 支持单列和多列更新
    - 支持使用子查询
    - 支持集合更新

+ `DELETE`
    - 支持单表和多表删除

+ `TRUNCATE` 
    - 支持完全清空指定表

## 支持的变量

MySQL 实例里的参数叫 `variable` 。可以在启动时命令行下设置，也可以在启动的配置文件中设置，或者在 SQL 命令行下设置。SQL 里设置又分为全局级别设置和会话级别设置。

MySQL 有些变量在 OceanBase MySQL 租户里同样适用，但是要留心源端 MySQL 和目标端 OceanBase 这些变量值的差异。

| 变量名                       | 变量默认值(OB）          | 变量含义                                                                             |
|---------------------------|--------------------|----------------------------------------------------------------------------------|
| autocommit                | ON                 | 是否自动提交。ON 表示每个DML后会自动添加 commit 语句；OFF 表示不会自动 commit，需要用户主动 commit 或 rollback 事务。 |
| auto_increment_cache_size | 1000000            | 自增列的缓存值。自增列在节点重启发生切换后可能会跳号，这个值越大，跳号间隔越大。                                         |
| auto_increment_increment  | 1                  | 自增列类型值的增长步长                                                                      |
| auto_increment_offset     | 1                  | 自增列类型值的起始值                                                                       |
| character_set_client      | utf8mb4            | 连接的客户端环境的字符集。保持默认。                                                               |
| character_set_connection  | utf8mb4            | 连接自身的字符集。保持默认。                                                                   |
| character_set_database    | utf8mb4            | 连接的数据库的字符集。保持默认。                                                                 |
| collation_connection      | utf8mb4_general_ci |                                                                                  |
| collation_database        | utf8mb4_general_ci |                                                                                  |
| collation_server          | utf8mb4_general_ci |                                                                                  |
| max_allowed_packet        | 4194304            | 需要调大，否则 SQL文本或数据量很大的时候可能报错。                                                      |
| sql_mode                  | STRICT_ALL_TABLES  |                                                                                  |
| transaction_isolation     | READ-COMMITTED     |                                                                                  |
| tx_isolation              | READ-COMMITTED     |                                                                                  |
| lower_case_table_names    | 1                  | 1 表示自动将表名转小写，则大小写不敏感。0 表示不对表名大小写转换，则是大小写敏感。                                                               |
| foreign_key_checks | ON | ON：检查外键约束；OFF：不检查外键约束。 |

这些变量中要留意字符集相关设置、`sql_mode` 设置以及 `lower_case_table_names` 设置。这些设置最好是在数据迁移之前就正确设置。后期修改会带来风险。

## 支持的字符集

OceanBase MySQL 租户支持字符集 `gbk` 和 `utf8mb4` 。 默认是后者。租户的字符集在租户创建的时候指定，设置的是租户全局级别的字符集。
字符集 `utf8mb4` 是 `utf8` 的超集，多一些表情字符的编码。建议迁移到 OceanBase 都使用这个字符集。
在 `utf8mb4` 字符集下，每个英文字符长度 1 字节，每个汉字 长度 3 字节，每个表情字符长度 4 字节。如果迁移数据换了字符集，字符串列的长度需要适当放长。

```sql
MySQL [test]> create table t1(c1 varchar(50));
Query OK, 0 rows affected (0.04 sec)

MySQL [test]> insert into t1 values('a'),('中');
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

MySQL [test]> select length(c1) from t1;
+------------+
| length(c1) |
+------------+
|          1 |
|          3 |
+------------+
2 rows in set (0.01 sec)
```

当从 MySQL 中导出数据时，要确保数据库里的字符都能正确输出到文件中。通过 `vim` 命令下的 `:set fileencoding` 命令可以查看文件的编码。一般建议都是 `utf-8`。这样通过文件迁移 MySQL 数据时就不会出现乱码现象。
