干净实用的同义词

ywz888
发布于 2022-10-10 16:12
浏览
0收藏

同义词(Synonym)是数据库内对象的别名。数据库中的大部分数据库对象,如表、视图、物化视图、序列、函数、存储过程、包、dblink、同义词等等,均可以根据实际情况为他们定义同义词。

使用同义词可以在一定层度上降低应用开发者编写SQL的复杂度,用户可以不用关心一个Object的所属关系(例如table在哪个database下、是dblink其他数据库的对象还是本地对象),直接使用同义词即可。同义词带来的好处并不仅仅是别名这么简单,例如研发同学写了一条SQL,其中涉及到生产系统中的table,如果使用同义词,在测试初期可以先将该同义词指向一个mock table,测试通过后再重新将该同义词指向生产系统中的表。这样既避免了对代码的更改,又较少了生产系统的影响。

使用

同义词的语法与其他DDL操作类似,通过Create 来创建同义词,通过 Drop来删除同义词。

创建同义词

CREATE [OR REPLACE] [PUBLIC] SYNONYM

[DATABASE.]synonym_name

FOR [DATABASE.]object_name

当用户创建同义词时无需对同义词指向的对象具有权限,而是需要具有在指定Database下创建同义词的权限。如果指定PUBLIC关键词,该同义词不属于任何一个Database,因此该同义词不与其他Database共享Namespace,其属于PUBLIC的Namespace。

在SQL引擎处理Query时,如果没有指定同义词的DataBase,则首先尝试在当前Session的DataBase中查找是否有同名的Object(例如table/view/synonym),如果查找不到则会到PUBLIC中去查找同名的同义词。后续会举例说明。

删除同义词

DROP [PUBLIC] SYNONYM

[DATABASE.]synonym_name

[FORCE]


如果希望删除一个PUBLIC的同义词,则需要指定PUBLIC关键字,此时不能指定synonym_name的Database。

举例

当前有两个Database,其中db1中含有两张表t1和t2, db2为空:

OceanBase (root@db1)> use db1;
Database changed 
OceanBase (root@db1)> select * from t1;
+------+
| c1   |
+------+
|    1 |
+------+

OceanBase (root@db1)> select * from t2;
+------+
| c1   |
+------+
|    2 |
+------+

在t2上创建一个public的关键字t1,然后分别在db1和db2中执行相同的Query。由于没有为​​t1​​​显示指定Database,在查找​​t1​​时,SQL引擎先尝试在当前Session的Database中查找,如果查找不到则会到Public中查找。

因此下面的例子中,在db1中执行时查找到了db1中的table t1, 因此查询结果为1;在db2中执行时,当前Database中没有找到任何同名的Object,则去public中查找,发现了同义词t1(其为指向db1.t2的同义词),因此查询结果为2.

OceanBase (root@db1)> create public synonym t1 for t2;

OceanBase (root@db1)> select * from t1;
+------+
| c1   |
+------+
|    1 |
+------+

OceanBase (root@db1)> use db2;

OceanBase (root@db2)> select * from t1;
+------+
| c1   |
+------+
|    2 |
+------+
1 row in set (0.01 sec)

实现

同义词的元信息并不会占用很大的空间,其通过一张​​__all_synonyms​​表来记录同义词到对象之间的映射关系。

+--------------------+--------------+------+-----+----------------------+-------+
| Field              | Type         | Null | Key | Default              | Extra |
+--------------------+--------------+------+-----+----------------------+-------+
| gmt_create         | timestamp(6) | YES  |     | CURRENT_TIMESTAMP(6) |       |
| gmt_modified       | timestamp(6) | YES  |     | CURRENT_TIMESTAMP(6) |       |
| tenant_id          | bigint(20)   | NO   | PRI | NULL                 |       |
| synonym_id         | bigint(20)   | NO   | PRI | NULL                 |       |
| database_id        | bigint(20)   | NO   |     | NULL                 |       |
| schema_version     | bigint(20)   | NO   |     | NULL                 |       |
| synonym_name       | varchar(128) | NO   |     |                      |       |
| object_name        | varchar(128) | NO   |     |                      |       |
| object_database_id | bigint(20)   | NO   |     | NULL                 |       |
| is_public          | bigint(20)   | NO   |     | NULL                 |       |
+--------------------+--------------+------+-----+----------------------+-------+

在SQL引擎的语意解析阶段,在所有同义词能够出现的位置,加入同义词的解析流程,将同义词所指向的对象找到,将同义词替换为找到的对象来完成余下的SQL执行流程。

整个实现过程在逻辑上比较清晰,但是又有许多细节需要我们去处理。例如,同义词可以指向视图、视图又可以指向同义词,这时就需要处理出现循环的情况。再者,OceanBase具有计划缓存(Plan Cache)的功能,这就需要我们保证在同义词指向的对象发生变更时,Plan Cache中涉及到同义词的SQL也能够及时失效。

总结

OceanBase对同义词的支持是一个小而美的改进,积跬步、至千里!



文章转载自公众号:OceanBase

分类
标签
已于2022-10-10 16:12:37修改
收藏
回复
举报
回复
    相关推荐