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环境下。

 

posted @ 2024-05-14 11:03  PiscesCanon  阅读(336)  评论(0编辑  收藏  举报