Oracle:谈谈service_names和dbms_service的一点问题
Oracle:谈谈service_names和dbms_service的一点问题
services_name在在19C中官方明确提到已经弃用了,只保留兼容,且在未来版本中可能不再支持该初始化参数。传送门。
其次,无论是在12C或者11G,官方都表明了Oracle RAC或者Oracle Restart环境下,不通过直接修改services_name参数,而除此之外的单点环境就可以直接修改。
详情可以看:11G 、 12C 、 12C services_name
PS:可惜官档11G我没搜到参数的说明
然而我发现即便是在除了上述说的两个环境下,直接修改services_name也存在一些问题。
以11G为例子,做个测试。
通过直接修改services_name参数添加testsrv服务。防。
09:32:28 SYS@zkm(235)> show parameter service NAME TYPE VALUE ------------------------------------ --------------------------------- -------------------- service_names string pri_zkm, zkm 09:32:28 SYS@zkm(235)> select name from dba_services where name not in ('pri_zkm','zkm'); --排除上边两个,减少篇幅 NAME ------------------------- SYS$BACKGROUND SYS$USERS zkmXDB 09:32:42 SYS@zkm(235)> alter system set service_names='zkm','pri_zkm','testsrv' sid='*' scope=both; System altered. 09:33:12 SYS@zkm(235)> select name from dba_services where name not in ('SYS$USERS','SYS$BACKGROUND','zkmXDB','pri_zkm','zkm'); NAME ------------------------- testsrv
https://www.cnblogs.com/PiscesCanon/p/18190895
到这里都没毛病,但是如果此时想取消删除testsrv服务的话,存在一点小问题。
依旧是通过直接修改services_name参数,但是修改之后的dba_services和v$services还是存在该服务,即便是重启dba_services依然留有testsrv记录,篇幅问题重启步骤略。
09:35:42 SYS@zkm(235)> alter system set service_names='zkm','pri_zkm' sid='*' scope=both; System altered. 09:35:50 SYS@zkm(235)> select name from dba_services where name not in ('SYS$USERS','SYS$BACKGROUND','zkmXDB','pri_zkm','zkm'); NAME ------------------------- testsrv 09:36:08 SYS@zkm(235)> select name from v$services where name not in ('SYS$USERS','SYS$BACKGROUND','zkmXDB','pri_zkm','zkm'); NAME ------------------------- testsrv 09:36:14 SYS@zkm(235)> select name from v$active_services where name not in ('SYS$USERS','SYS$BACKGROUND','zkmXDB','pri_zkm','zkm'); no rows selected
为此我做了10046跟踪了下,发现修改services_name的时候,
如果是在services_name上追加新的服务名,则10046的trc文件中会有对表service$进行insert和update操作。
10046过程略,这里可以看看trc文件中的dml操作。
[oracle@oracle1 zkm]$ grep -E "insert|update|delete" zkm_ora_112482.trc insert /*+ RULE */ into service$ (service_id, name, name_hash, network_name, creation_date, deletion_date, flags) values (:1, :2, :3, :4, sysdate, null, :5) update /*+ RULE */ service$ set creation_date_hash = ora_hash(creation_date) where service_id = :1 insert into WRI$_ALERT_THRESHOLD_LOG (sequence_id, object_type, object_name, object_id, opcode) values (:1, :2, :3, :4, :5)
如果是在services_name上删减服务名,则并不会删除或修改表service$的条目。
而当你查询dba_services这个视图的时候,实际就是查询基表services$的数据(where DELETION_DATE is null)。
因此,即便是重启数据库,你依然能够发现能够查询到testsrv服务,
但是我们本意是从数据库中永久取消并删除testsrv服务名条目!
所以会显得有点奇怪。
PS:上诉还出现了视图v$services以及v$active_services,文档 ID 1496074.1提到了两者区别
DBA_SERVICES - 该视图列出了数据库中的所有服务。这包括启动和停止的服务。
V$SERVICES - 此视图仅列出自实例启动以来一段时间启动的服务。当您停止正在运行的服务时,该服务仍将在此视图中列出,直到下一个实例重新启动。
至于v$active_services则显示了当前正在活动的服务。
至于如何清除dba_services中testsrv的条目,可以通过dbms_service包来实现:
10:28:12 SYS@zkm(235)> exec dbms_service.delete_service('testsrv'); PL/SQL procedure successfully completed. 10:29:24 SYS@zkm(235)> select name from dba_services where name='testsrv'; no rows selected
对于服务名的添加修改操作,可以通过dbms_service来实现,可以通过dbms_service来避免上述问题。
但实际上对于dbms_service本身也有自己的问题,使用dbms_service.create_service添加新服务名并dbms_service.start_service的时候,只在memory层修改了services_name导致重启数据库新的服务名并不会随之启动。。。
需要每次启动数据库的时候手工启动,感觉有点蠢。
09:27:48 SYS@zkm(235)> show parameter service NAME TYPE VALUE ------------------------------------ --------------------------------- ---------------------------------------------------------------------------------------------------- service_names string pri_zkm, zkm 09:27:51 SYS@zkm(235)> exec dbms_service.create_service('testsrv','testsrv'); PL/SQL procedure successfully completed. 09:28:29 SYS@zkm(235)> exec dbms_service.start_service('testsrv'); PL/SQL procedure successfully completed. 此时警告日志: ALTER SYSTEM SET service_names='pri_zkm','zkm','testsrv' SCOPE=MEMORY SID='zkm'; 09:28:35 SYS@zkm(235)> show parameter service NAME TYPE VALUE ------------------------------------ --------------------------------- ---------------------------- service_names string pri_zkm, zkm, testsrv 09:28:52 SYS@zkm(235)> select name from dba_services where name not in ('SYS$BACKGROUND','SYS$USERS','zkmXDB','zkm','pri_zkm'); NAME ------------------------- testsrv
重启失效,略。
如果是在12c以上的pdb环境中,还能保存pdb状态实现重启pdb带上service启动。
11g想要启动数据库的时候启动服务名,要么在services_name参数追加服务名(有点蠢,我一开始直接修改services_name不就好了),要么就是通过创建触发器(增加了些许复杂度和管理成本,比如迁移要考虑这类对象,比如删除testsrv服务要同步记得先删除触发器)。
触发器模板:
create or replace trigger startsrv after startup on database begin dbms_service.start_service('testsrv'); end startsrv; /
PS:再次强调啊,本文讨论的是在非Oracle RAC和非Oracle Restart环境下。