干净实用的同义词
同义词(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