oracle19c 多租户数据库在操作上和传统oracle有很大的不同,初学者往往无所适从,感觉无从下手,本文从操作层面阐述了多租户数据库的操作与维护步骤。
多租户数据库的维护分两个层面。第1个层面是根容器的管理与维护,第2个层面是可插拔数据库的操作与维护。本文以centos7下安装的oracle19c为例进行说明。
[oracle@orc19c ~]$ dbca
2. 选择 Manage Pluggable databases,点击next
3. 选择 Create a pluggable database,点击next
3. 选择 将要创建的PDB的宿主容器(或根容器),如果在操作系统中是以 oracle用户启动dbca时,User name 和 Password栏目可以为空,否则要输入根容器的sys及密码。
4. 选择创建 PDB的方式,一般选择从 PDB$SEED创建
5. 对要创建的PDB命名,设定该PDB的管理员账号和密码。
6. 对新创建的PDB数据文件的位置进行设定,并创建默认用户表空间。
When you create a PDB, the current container—CDB root or application root—determines the association of the PDB.the PDB belongs to the CDB root.
创建pdb,只能在根容器中进行。
[oracle@orc19c ~]$ sqlplus / as sysdba
SQL>CREATE PLUGGABLE DATABASE salespdb
ADMIN USER salesadm IDENTIFIED BY wyf****
ROLES = (dba)
DEFAULT TABLESPACE sales
DATAFILE '/opt/oracle/oradata/ORCLCDB/salespdb/sales01.dbf' SIZE 250M AUTOEXTEND ON
FILE_NAME_CONVERT = ('/opt/oracle/oradata/ORCLCDB/pdbseed/',
'/opt/oracle/oradata/ORCLCDB/salespdb/')
STORAGE UNLIMITED
PATH_PREFIX = '/opt/oracle/oradata/ORCLCDB/salespdb/';
SQL>show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 ORCLPDB1 READ WRITE NO
4 OAPDB READ WRITE NO
5 PDB_TEST READ WRITE NO
6 SALESPDB MOUNTED
--工具SQL窗口
select name,open_mode from v$pdbs;
--或
SELECT name,open_mode FROM V$CONTAINERS;
--查看数据文件
select file_id,file_name,tablespace_name,con_id from cdb_data_files ORDER BY con_id;
[oracle@orc19c ~]$ cd /opt/oracle/oradata/ORCLCDB/salespdb
[oracle@orc19c salespdb]$ ls -al
-rw-r----- 1 oracle oinstall 346038272 Jun 13 15:40 sysaux01.dbf
-rw-r----- 1 oracle oinstall 283123712 Jun 13 15:40 system01.dbf
-rw-r----- 1 oracle oinstall 37756928 Jun 13 15:40 temp012023-03-31_16-49-34-985-PM.dbf
-rw-r----- 1 oracle oinstall 104865792 Jun 13 15:40 undotbs01.dbf
SQL>ALTER PLUGGABLE DATABASE salespdb OPEN ;
SQL> show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 ORCLPDB1 READ WRITE NO
4 OAPDB READ WRITE NO
5 PDB_TEST READ WRITE NO
6 SALESPDB READ WRITE NO
--也可以用传统的方式启动 pdb数据库
--
SQL>startup;
[oracle@orc19c salespdb]$ ls -al
-rw-r----- 1 oracle oinstall 262152192 Jun 13 15:43 sales01.dbf
-rw-r----- 1 oracle oinstall 346038272 Jun 13 15:43 sysaux01.dbf
-rw-r----- 1 oracle oinstall 283123712 Jun 13 15:43 system01.dbf
-rw-r----- 1 oracle oinstall 37756928 Jun 13 15:40 temp012023-03-31_16-49-34-985-PM.dbf
-rw-r----- 1 oracle oinstall 104865792 Jun 13 15:43 undotbs01.dbf
--切换到根容器
[oracle@orc19c ORCLCDB]$ sqlplus / as sysdba
--或在SQLPLUS环境下
SQL>conn / as sysdba
--创建pdb测试数据库
CREATE PLUGGABLE DATABASE pdb_wyf
ADMIN USER pdb_wyf IDENTIFIED BY wyf****
ROLES = (dba)
FILE_NAME_CONVERT = ('/opt/oracle/oradata/ORCLCDB/pdbseed/',
'/opt/oracle/oradata/ORCLCDB/pdb_wyf/')
PATH_PREFIX = '/opt/oracle/oradata/ORCLCDB/pdb_wyf/';
--打开测试数据库
ALTER PLUGGABLE DATABASE pdb_wyf OPEN ;
--连接新建的测试数据库,由于没有配置tnsnames.ora,所以用全路径名连接
SQL> conn pdb_wyf/wyf****@localhost:1521/pdb_wyf
--查看默认永久表空间
SELECT property_value FROM database_properties
WHERE property_name ='DEFAULT_PERMANENT_TABLESPACE';
--输出如下
PROPERTY_VALUE
-----------------
SYSTEM
--以dba身份登录pdb数据库salespdb。
[oracle@orc19c salespdb]$ sqlplus salesadm/wyf****@localhost:1521/salespdb
SQL>create tablespace users datafile '/opt/oracle/oradata/ORCLCDB/salespdb/users01.dbf' size 50m;
SQL>alter pluggable database default users;
--查看操作系统下的目录结构
[oracle@orc19c ORCLCDB]$ cd salespdb/
[oracle@orc19c salespdb]$ ll
total 1024096
-rw-r----- 1 oracle oinstall 262152192 Jun 30 15:38 sales01.dbf
-rw-r----- 1 oracle oinstall 346038272 Jun 30 16:39 sysaux01.dbf
-rw-r----- 1 oracle oinstall 283123712 Jun 30 17:05 system01.dbf
-rw-r----- 1 oracle oinstall 37756928 Jun 30 15:34 temp012023-03-31_16-49-34-985-PM.dbf
-rw-r----- 1 oracle oinstall 104865792 Jun 30 17:05 undotbs01.dbf
-rw-r----- 1 oracle oinstall 52436992 Jun 30 17:01 users01.dbf
--查看可插拔数据库salespdb的默认表空间。
SQL>SELECT property_value FROM database_properties
WHERE property_name ='DEFAULT_PERMANENT_TABLESPACE';
PROPERTY_VALUE
------------------
USERS
--关闭salespdb
ALTER PLUGGABLE DATABASE salespdb CLOSE IMMEDIATE ;
--只读方式打开salespdb
ALTER PLUGGABLE DATABASE salespdb OPEN READ ONLY ;
--查看PDB的状态
SELECT * FROM V$PDBS;
--查看salespdb的数据文件路径。
select file_name from cdb_data_files where con_id=5;
--以salespdb 创建新的PDB数据库
CREATE PLUGGABLE DATABASE salespdb01 FROM salespdb FILE_NAME_CONVERT=('salespdb','salespdb01');
--打开新创建的pdB数据库
ALTER PLUGGABLE DATABASE salespdb01 OPEN ;
以克隆方式创建的PDP数据库,源数据库中创建的用户在新克隆出的PDB数据库中仍然有效。
[oracle@orc19c ~]$ sqlplus / as sysdba
SQL>show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 ORCLPDB1 READ WRITE NO
4 OAPDB READ WRITE NO
5 PDB_TEST READ WRITE NO
SQL>ALTER PLUGGABLE DATABASE salepdb CLOSE ;
SQL>DROP PLUGGABLE DATABASE salespdb INCLUDING DATAFILES ;
[oracle@orc19c ~]$ sqlplus / as sysdba
--oapdb 是可插拔数据的名字
[oracle@orc19c ~]$sqlplus oapdb_user01/[email protected]:1521/oapdb
--前提条件是在客户端正确配置了 tnsnames.ora 文件
--oapdb是TNS名称
[oracle@orc19c ~]$ sqlplus oapdb_user01/passwd@oapdb
--方法1 查看当前容器
SQL>SELECT sys_context('USERENV','CON_ID') con_id,
sys_context('USERENV','CON_NAME') con_name,
sys_context('USERENV','SESSION_USER') curr_user
FROM DUAL;
+------+--------+---------+
|CON_ID|CON_NAME|CURR_USER|
+------+--------+---------+
|1 |CDB$ROOT|SYS |
+------+--------+---------+
--方法2
SQL>Show con_name;
--根容器切换到PDB
SQL> alter session set container=OAPDB;
--PDB 切换到根容器,当前用户要有足够的权限,否则会显示
ERROR:
ORA-01031: insufficient privileges
SQL>alter session set container=CDB$ROOT;
--通过改变连接来切换
SQL>conn / as sysdba;
SQL>conn oapdb_user01/passwd@oapdb;
--查看PDB
SQL>show pdbs;
SQL>SELECT * FROM cdb_pdbs;
--查看当前用户下的表空间及数据文件
SQL>SELECT * FROM CDB_TABLESPACES;
SQL>SELECT * FROM CDB_DATA_FILES;
SQL>select * from v$tablespace;
表空间是数据库中最大的逻辑存储结构,为数据库提供使用空间,其对应物理结构是数据文件,一个表空间可以包含多个数据文件,但是一个数据文件只能属于一个表空间。表空间所包含的数据文件的大小,也就决定了表空间的大小,所以,表空间也是逻辑结构连接到物理结构的一个纽带。
以dba用户连接PDB数据库,所创建的表空间就属于本pdb数据库。但表空间这个逻辑机构所依托的物理数据文件可以存储在任何合适的位置,但通常会把数据文件存放在所属的PBD文件夹下,这样会便于管理。
[oracle@orc19c ORCLCDB]$ ll OAPDB/
oapdb_tablespace02.dbf
oapdb_tablespace.dbf
sysaux01.dbf
system01.dbf
temp012023-03-31_16-49-34-985-PM.dbf
undotbs01.dbf
user.dbf
select * from v$tablespace;
+---+----------------+---------------------------+
|TS#|NAME |INCLUDED_IN_DATABASE_BACKUP|
+---+----------------+---------------------------+
|0 |SYSTEM |YES |
|1 |SYSAUX |YES |
|2 |UNDOTBS1 |YES |
|3 |TEMP |NO |
|6 |OAPDB_TABLESPACE|YES |
|7 |OA_WYF |YES |
+---+----------------+---------------------------+
SELECT con_id,name FROM V$DATAFILE;
+------+--------------------------------------------------------+
|CON_ID|NAME |
+------+--------------------------------------------------------+
|4 |/opt/oracle/oradata/ORCLCDB/OAPDB/system01.dbf |
|4 |/opt/oracle/oradata/ORCLCDB/OAPDB/sysaux01.dbf |
|4 |/opt/oracle/oradata/ORCLCDB/OAPDB/undotbs01.dbf |
|4 |/opt/oracle/oradata/ORCLCDB/OAPDB/oapdb_tablespace.dbf |
|4 |/opt/oracle/oradata/ORCLCDB/OAPDB/oapdb_tablespace02.dbf|
|+------+--------------------------------------------------------+
SQL>CREATE TABLESPACE oa_wyf DATAFILE '/home/oracle/oa_wyf.dbf' SIZE 10M;
--服务器文件结构,新创建的表空间数据文件并不在原来的PDB数据库文件夹下。
[oracle@orc19c ORCLCDB]$ ll OAPDB/
oapdb_tablespace02.dbf
oapdb_tablespace.dbf
sysaux01.dbf
system01.dbf
temp012023-03-31_16-49-34-985-PM.dbf
undotbs01.dbf
user.dbf
[oracle@orc19c ORCLCDB]$ ll ~
oa_wyf.dbf
-- Oapdb下查看表空间
SELECT * FROM CDB_TABLESPACES;
或
select * from v$tablespace;
+----------------+----------+
|TABLESPACE_NAME |BLOCK_SIZE|
+----------------+----------+
|SYSTEM |8192 |
|SYSAUX |8192 |
|UNDOTBS1 |8192 |
|TEMP |8192 |
|OAPDB_TABLESPACE|8192 |
|OA_WYF |8192 |
+----------------+----------+
-- Oapdb环境下查看表空间所对应的数据文件
SELECT con_id,name FROM V$DATAFILE;
+------+--------------------------------------------------------+
|CON_ID|NAME |
+------+--------------------------------------------------------+
|4 |/opt/oracle/oradata/ORCLCDB/OAPDB/system01.dbf |
|4 |/opt/oracle/oradata/ORCLCDB/OAPDB/sysaux01.dbf |
|4 |/opt/oracle/oradata/ORCLCDB/OAPDB/undotbs01.dbf |
|4 |/opt/oracle/oradata/ORCLCDB/OAPDB/oapdb_tablespace.dbf |
|4 |/opt/oracle/oradata/ORCLCDB/OAPDB/oapdb_tablespace02.dbf|
|4 |/home/oracle/oa_wyf.dbf |
+------+--------------------------------------------------------+
SELECT * FROM CDB_DATA_FILES;
+--------------------------------------------------------+-------+----------------+
|FILE_NAME |FILE_ID|TABLESPACE_NAME |
+--------------------------------------------------------+-------+----------------+
|/opt/oracle/oradata/ORCLCDB/OAPDB/system01.dbf |21 |SYSTEM |
|/opt/oracle/oradata/ORCLCDB/OAPDB/sysaux01.dbf |22 |SYSAUX |
|/opt/oracle/oradata/ORCLCDB/OAPDB/undotbs01.dbf |23 |UNDOTBS1 |
|/opt/oracle/oradata/ORCLCDB/OAPDB/oapdb_tablespace.dbf |29 |OAPDB_TABLESPACE|
|/opt/oracle/oradata/ORCLCDB/OAPDB/oapdb_tablespace02.dbf|30 |OAPDB_TABLESPACE|
|/home/oracle/oa_wyf.dbf |58 |OA_WYF |
+--------------------------------------------------------+-------+----------------+
--查看UNDO表空间的使用模式(CDB$ROOT)
SELECT property_name, property_value
FROM database_properties
WHERE property_name='LOCAL_UNDO_ENABLED';
--在创建CDB时使用了SHARED UNDO MODE方式,如果后续想更改为LOCAL UNDO MODE,我们可以使用如下命令更改UNDO MODE为LOCAL UNDO MODE:
更改为local undo后CDB中的所有的PDB会自动创建自己的UNDO表空间。
startup upgrade
alter database local undo on;
shutdown immediate
startup
--更改为local undo后CDB中的所有的PDB会自动创建自己的UNDO表空间。
每个PDB都有自己的临时表空间,如果PDB没有自己的临时表空间文件,那么,PDB可以使用CDB$ROOT中的临时表空间。
--CDB$ROOT 下,显示所有PDB的TEMP
select con_id, tablespace_name from cdb_temp_files;
+------+---------------+
|CON_ID|TABLESPACE_NAME|
+------+---------------+
|1 |TEMP |
|4 |TEMP |
|6 |TEMP |
|3 |TEMP |
+------+---------------+
--PDB场景下,仅仅显示本PDB的TEMP
+------+---------------+
|CON_ID|TABLESPACE_NAME|
+------+---------------+
|4 |TEMP |
+------+---------------+
参数文件中只记录了根容器的参数信息,没有记录PDB级别的参数信息,在根容器中修改初始化参数,会被继承到所有的PDB中,在PDB中修改参数后,PDB的参数会覆盖CDB级别的参数,PDB级别的参数记录在根容器的pdb_spfile 视图中,但并不是所有的参数都可以在 P D B 中修改,可以通过 v 视图中,但并不是所有的参数都可以在PDB中修改,可以通过v 视图中,但并不是所有的参数都可以在PDB中修改,可以通过vsystem_parameter视图查看PDB中可修改的参数:
SELECT name FROM v$system_parameter
WHERE ispdb_modifiable = 'TRUE'
ORDER BY name;
-- PDB环境下有191个参数可以修改
--在跟容器下251个参数可以修改
CDB环境中只有一组控制文件,所有的PDB共用这组公共的控制文件,从任何PDB中添加数据文件都会记录到公共控制文件当中,公用用户连接根容器时,可对控制文件进行管理。
select CON_ID, name,status from v$controlfile;
+------+-----------------------------------------+------+
|CON_ID|NAME |STATUS|
+------+-----------------------------------------+------+
|0 |/opt/oracle/oradata/ORCLCDB/control01.ctl|null |
|0 |/opt/oracle/oradata/ORCLCDB/control02.ctl|null |
+------+-----------------------------------------+------+
在CDB环境中可以为CDB以及所有的PDB设置相同的时区,也可以为每个PDB设置单独的时区。
drop tablespace 表空间名 including contents and datafiles;
alter tablesapce 表空间名 add datafile '数据文件名' size 大小
[reuse]
[autoextend [on/off] next 大小]
[maxsize [unlimited|大小]];
alter tablespace 表空间名 [online] [offline] [read only|write];
alter tablespace 表空间名 offline;
alter database datafile '/opt/oracle/oradata/ORCLCDB/OAPDB/data01.dbf' offline;
alter database datafile '/opt/oracle/oradata/ORCLCDB/OAPDB/data01.dbf' online;
alter database datafile '/opt/oracle/oradata/ORCLCDB/OAPDB/data01.dbf' offline drop;
alter tablespace 表空间名 online;
alter database datafile '数据文件名'
[ [resize 大小| [autoextend [on/off] next 大小] [maxsize [unlimited|大小]] ];
--把表空间offline
alter tablespace 表空间名 offline;
--执行操作系统命令,迁移数据文件,cp和mv都可以,注意,cp和mv是操作系统的命令,不是sqlplus中Oracle的命令
mv data01.dbf data03.dbf
mv data02.dbf data04.dbf
--执行alter tablespace或alter database修改数据库文件名
alter tablespace 表空间名 rename datafile '/opt/oracle/oradata/ORCLCDB/OAPDB/data01.dbf' to '/opt/oracle/oradata/ORCLCDB/OAPDB/data03.dbf';
--把表空间online
alter tablespace 表空间名 online;
SELECT property_value
FROM database_properties
WHERE property_name ='DEFAULT_PERMANENT_TABLESPACE';
select username,default_tablespace from user_users;
--查看数据文件,数据文件存放在数据字典DBA_DATA_FILES中,用DBA权限执行以下SQL查询
select file_name,file_id,tablespace_name,bytes,status,autoextensible,
maxbytes,user_bytes,online_status
from DBA_DATA_FILES order by tablespace_name,file_name;
==输出如下
+--------------------------------------------------------+-------+----------------+
|FILE_NAME |FILE_ID|TABLESPACE_NAME |
+--------------------------------------------------------+-------+----------------+
|/opt/oracle/oradata/ORCLCDB/OAPDB/oapdb_tablespace.dbf |29 |OAPDB_TABLESPACE|
|/opt/oracle/oradata/ORCLCDB/OAPDB/oapdb_tablespace02.dbf|30 |OAPDB_TABLESPACE|
|/home/oracle/oa_wyf.dbf |58 |OA_WYF |
|/opt/oracle/oradata/ORCLCDB/OAPDB/sysaux01.dbf |22 |SYSAUX |
|/opt/oracle/oradata/ORCLCDB/OAPDB/system01.dbf |21 |SYSTEM |
|/opt/oracle/oradata/ORCLCDB/OAPDB/undotbs01.dbf |23 |UNDOTBS1 |
+--------------------------------------------------------+-------+----------------+
--查看表空间使用情况
select a.tablespace_name "表空间名",total "表空间大小",
(total - free) "已使用大小",free "表空间剩余大小",
round(total/(1024*1024)) "表空间大小M",
round((total-free)/(1024*1024)) "已使用大小M",
round(free/(1024*1024)) "表空间剩余大小M",
round((total-free)/total,4)*100 "使用率%"
from
(select tablespace_name,sum(bytes) free from DBA_FREE_SPACE group by tablespace_name) a,
(select tablespace_name,sum(bytes) total from DBA_DATA_FILES group by tablespace_name) b
where a.tablespace_name = b.tablespace_name;
CREATE USER C##yyh identified by yyh;
创建完成公用用户,需要为公用用户赋予所有可插拔数据库的权限,公用用户才可以访问其他PDB,如果在连接根容器时仅仅为公用用户赋予了相关权限,那么该权限不会被传递到所有的可插拔数据库中,必须为公用用户赋予能够传递到PDB中的权限,可以创建公用角色然后赋予公用用户,或者在为公共用户付权时指定子句container=ALL;
grant dba to c##yyh container=all;
在PDB中创建的普通用户,只有在创建它的PDB中才会存在该用户,并且PDB中只能创建本地用户。
--查看用户
select username,COMMON,CON_ID from cdb_users where account_status='OPEN';
select * from user_role_privs;
select * from user_users;
以数据库开发工具datagrip为例,在这个数据库开发工具中,分别建立三个连接:一是以系统管理员sys连接根容器,在这个连接中可以对根容器数据库进行全方位管理;第二个连接是以sys用户连接欲管理的 pdb数据库,在这个连接中可以对本pdb数据库进行完全管理工作;第三个是以普通用户连接PDP数据库,对数据库进行日常管理操作。
另外可以远程连接数据库,使用SQLPLUS对数据库进行一些特殊的操作。
--创建数据表空间DATA
create tablespace DATA datafile '/opt/oracle/oradata/ORCLCDB/OAPDB/data01.dbf' size 128M;
--创建索引表空间INDEXS
create tablespace INDEXS datafile '/opt/oracle/oradata/ORCLCDB/OAPDB/INDEXS01.dbf' size 128M;
--创建表空间时,可以指定多个数据文件,但致少要指定一个数据文件,数据文件由Oracle自动创建,不需要事先在磁盘上手工的创建文件。
create user girl identified by pwd*** default tablespace DATA;
create table T_GIRL
(
id char(4) not null, -- 编号
name varchar2(30) not null, -- 姓名
yz varchar2(20) null, -- 颜值
sc varchar2(20) null -- 身材
) tablespace DATA;
alter table T_GIRL add constraint PK_GIRL primary key(id) using index tablespace INDEXS;
create index IDX_GIRL_1 on T_GIRL(name) tablespace INDEXS;