目录
最近在工作中遇到有同事对Oracle表空间的理解有问题,所以写了这篇文章。我会从概念,管理及特别需要关注的点等几个维度对表空间进行一些介绍。本文以介绍表空间为主,涉及到的其他概念不展开描述。有问题的地方希望大家指正。
表空间概念
表空间属于逻辑结构,是Oracle物理结构与逻辑结构之间的桥梁。官方文档上是这样说的:
A tablespace is a logical storage container for segments. Segments are database objects, such as tables and indexes, that consume storage space. At the physical level, a tablespace stores data in one or more data files or temp files.
表空间在逻辑上包含段(常见的段有表和索引),段数据存储开销的存储空间由表空间提供;在物理上将数据存储在一个或多个数据文件或临时数据文件中。
一个数据库必须包含 SYSTEM 和 SYSAUX 表空间。下图是一个典型的数据库表空间示意图:
表空间分类
表空间大层面上可以分为永久表空间和临时表空间。我们通常所说的表空间指的都是永久表空间,以下如无特殊说明,提到表空间的地方默认都是指永久表空间。
永久表空间(Permanent Tablespaces)
永久表空间用来持久化存储用户对象数据。表空间中的用户对象数据最终物理的保存在表空间对应的数据文件上。
永久表空间的主要作用:
- 控制数据库数据的磁盘空间分配;
- 为数据库用户指定配额;
- 在不影响整体数据库可用性的情况下,为各表空间独立进行离线/上线操作;
- 对各个表空间独立进行备份恢复;
- 使用数据泵(Oracle Data Pump)工具进行数据的导入导出;
- 通过传输表空间,将表空间从一个数据库复制或移动到另一个数据库,甚至可以跨平台;
通过传输表空间移动数据要比导出/导入相同数据快几个数量级,因为传输表空间只涉及复制数据文件和集成表空间元数据。在传输表空间时,还可以移动索引数据。
XTTS(跨平台传输表空间)技术是现在最常用的数据迁移技术之一,其具备跨平台,跨版本迁移数据库的特点。
SYSTEM表空间
SYSTEM表空间是数据库创建时生成的一个必须的管理表空间,Oracle通过SYSTEM表空间来管理数据库。
SYSTEM表空间中所有对象的所有者都时SYS用户,主要包含以下信息:
- 数据字典;
- 数据库管理信息;
- 已编译的存储对象,如触发器、存储过程、包等;
SYSAUX表空间
SYSAUX表空间是SYSTEM表空间的辅助表空间。因为SYSAUX是许多Oracle数据库特性和产品(OEM,audit,AWR等)的默认表空间,这些特性和产品以前都需要自己的表空间,所以SYSAUX减少了数据库所需的表空间数量,还减少了系统表空间的负载。
在正常的数据库操作期间,数据库不允许删除或重命名SYSAUX表空间。如果SYSAUX表空间变得不可用,那么核心数据库功能仍然可以运行。使用SYSAUX表空间的数据库特性可能会失效,或者功能受限。
UNDO表空间
用来保存UNDO数据的表空间。Oracle官方建议UNDO使用自动管理模式。
一个数据库可以包含多个UNDO表空间,但一次只能使用一个。当实例打开数据库时,会自动选择第一个可用的UNDO表空间,如果没有可用的UNDO表空间,实例会将UNDO数据存放到SYSTEM表空间中,这是极其不推荐的。
UNDO是Oracle非常核心的功能,关于UNDO的管理以后会单独写文章。
临时表空间(Temporary Tablespaces)
临时表空间只包含会话期间留存的临时数据,不能存储持久化数据。临时表空间的数据存储在临时表空间文件上,与普通数据文件有区别。
临时表空间可以改善不适合内存排序的排序操作的并发性,同时改善排序期间空间管理的效率。(设计阶段应尽量避免非内存排序)
每个数据库用户都会分配一个默认临时表空间,可以在创建用户时指定,如果没有指定,则默认使用系统级别的默认临时表空间。
表空间大小
表空间空间管理方面可以分为大文件表空间(bigfile)和小文件(smallfile)表空间。默认创建的表空间都是小文件表空间。
小文件表空间最多支持1024个数据文件,每个数据文件最大32G(8K标准块),整个表空间最大32T;
大文件表空间有且仅有一个数据文件,最大32T(8K标准块)。
表空间管理
创建表空间
基本语法:
CREATE [BIGFILE/SMALLFILE] TABLESPACE tnsname
DATAFILE
[dbfpath] SIZE dbfsize [AUTOEXTEND ON] [NEXT nextsize] [MAXSIZE maxsize],
...;
- [ ]里面内容可选项;
- tnsname 根据需要自己定义;
- dbfpath 表示数据文件路径,在使用OMF的情况下,可以不写;否则要保证路径中的目录存在;
- dbfsize 为初始表空间大小,单位为K,M,G,T(建议初始值做好规划,一次给到位);
- AUTOEXTEND 是否自动扩展,值为ON或OFF;
- nextsize 为扩展时的一次扩展的大小(根据I/O性能及表空间增长情况设置适当值,不要太小);
- maxsize 为文件最大大小,指定UNLIMITED时表示不限大小(此时仍然受到单个数据文件32G(smallfile 8K)/32T(bigfile 8K)的限制);
- 如果表空间计划使用的会非常大,可以直接创建多个数据文件或使用bigfile表空间。
encryption,nologging,compression等高级特性不在这里详细解释,需要使用时查询官方文档;
区管理和段空间管理使用默认值即可,不用设置(EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO)。
示例:
CREATE TABLESPACE lmtbsb DATAFILE
'/u02/oracle/data/lmtbsb01.dbf' SIZE 500M AUTOEXTEND ON NEXT 50M MAXSIZE UNLIMITED,
'/u02/oracle/data/lmtbsb02.dbf' SIZE 500M AUTOEXTEND ON NEXT 50M MAXSIZE UNLIMITED;
CREATE BIGFILE TABLESPACE bigtbs DATAFILE
'/u02/oracle/data/bigtbs.dbf' SIZE 50G AUTOEXTEND ON NEXT 50M MAXSIZE UNLIMITED;
扩展表空间
扩展表空间有两种情况(针对smallfile表空间),扩展数据文件,增加数据文件。当单个数据文件扩展到最大限制后,还需要扩展时,必须选择增加数据文件。
基本语法:
扩展数据文件:
ALTER DATABASE DATAFILE [file_name/file_id] RESIZE filesize [AUTOEXTEND ON] [NEXT nextsize] [MAXSIZE maxsize];
增加数据文件:
ALTER TABLESPACE tbsname ADD DATAFILE dbfpath SIZE dbfsize [AUTOEXTEND ON] [NEXT nextsize] [MAXSIZE maxsize];
- 这里的file_name/file_id可以通过DBA_DATA_FILES查询得到;
- tbsname是需要扩展的表空间名,必须是存在的表空间,必须是smallfile表空间;
- 可以同时对数据文件的其他属性进行设置,具体设置项不再一一描述。
示例:
ALTER DATABASE DATAFILE '/u02/oracle/data/lmtbsb01.dbf' RESIZE 1G;
ALTER TABLESPACE lmtbsb ADD DATAFILE '/u02/oracle/data/lmtbsb03.dbf' SIZE 500M AUTOEXTEND ON NEXT 50M MAXSIZE UNLIMITED;
删除表空间
删除表空间属于极度高危的操作,生产环境谨慎操作。
基本语法:
--仅删除表空间
DROP TABLESPACE tnsname;
--删除表空间及数据文件
DROP TABLESPACE tnsname INCLUDING CONTENTS AND DATAFILES;
示例:
DROP TABLESPACE lmtbsb;
DROP TABLESPACE bigtbs INCLUDING CONTENTS AND DATAFILES;
表空间相关数据字典视图和动态性能视图
- DBA_TABLESPACES :描述数据库中的所有表空间
- DBA_DATA_FILES :描述数据库中的所有数据文件
- DBA_SEGMENTS :描述数据库中的所有段存储分配情况
- DBA_FREE_SPACE :描述数据库中所有表空间的空闲区情况
- DBA_HIST_TBSPC_SPACE_USAGE :显示历史表空间的使用情况的统计信息
- V$TABLESPACE :显示控制文件中的表空间信息
- V$DATAFILE :显示控制文件中的数据文件信息
表空间相关查询
查询表空间使用率
SELECT d.tablespace_name "Name", d.status "Status",
TO_CHAR (NVL (a.BYTES / 1024 / 1024, 0), '99,999,990.90') "Size (M)",
TO_CHAR (NVL (a.BYTES - NVL (f.BYTES, 0), 0) / 1024 / 1024,
'99,999,990.99'
) USE,
TO_CHAR (NVL ((a.BYTES - NVL (f.BYTES, 0)) / a.BYTES * 100, 0),
'990.00'
) "Used %"
FROM SYS.dba_tablespaces d,
(SELECT tablespace_name, SUM (BYTES) BYTES
FROM dba_data_files
GROUP BY tablespace_name) a,
(SELECT tablespace_name, SUM (BYTES) BYTES
FROM dba_free_space
GROUP BY tablespace_name) f
WHERE d.tablespace_name = a.tablespace_name(+)
AND d.tablespace_name = f.tablespace_name(+)
AND NOT (d.extent_management LIKE 'LOCAL' AND d.CONTENTS LIKE 'TEMPORARY')
UNION ALL
SELECT d.tablespace_name "Name", d.status "Status",
TO_CHAR (NVL (a.BYTES / 1024 / 1024, 0), '99,999,990.90') "Size (M)",
TO_CHAR (NVL (t.BYTES, 0) / 1024 / 1024, '99,999,990.99') USE,
TO_CHAR (NVL (t.BYTES / a.BYTES * 100, 0), '990.00') "Used %"
FROM SYS.dba_tablespaces d,
(SELECT tablespace_name, SUM (BYTES) BYTES
FROM dba_temp_files
GROUP BY tablespace_name) a,
(SELECT tablespace_name, SUM (bytes_cached) BYTES
FROM v$temp_extent_pool
GROUP BY tablespace_name) t
WHERE d.tablespace_name = a.tablespace_name(+)
AND d.tablespace_name = t.tablespace_name(+)
AND d.extent_management LIKE 'LOCAL'
AND d.CONTENTS LIKE 'TEMPORARY'
ORDER BY USE DESC;
查询表空间增长率
set linesize 200
col inc_ratex for a8
SELECT A.NAME,
B.TABLESPACE_ID,
B.DATETIME,
B.USED_SIZE_MB,
B.INC_MB,
CASE
WHEN SUBSTR (INC_RATE, 1, 1) = '.'
THEN
'0' || INC_RATE
WHEN SUBSTR (INC_RATE, 1, 2) = '-.'
THEN
'-0' || SUBSTR (INC_RATE, 2, LENGTH (INC_RATE))
ELSE
INC_RATE
END
AS INC_RATEX
FROM V$TABLESPACE A,
(SELECT TABLESPACE_ID,
DATETIME,
USED_SIZE_MB,
(DECODE (PREV_USE_MB, 0, 0, USED_SIZE_MB) - PREV_USE_MB)
AS INC_MB,
TO_CHAR (
ROUND (
( DECODE (PREV_USE_MB, 0, 0, USED_SIZE_MB)
- PREV_USE_MB)
/ DECODE (PREV_USE_MB, 0, 1, PREV_USE_MB)
* 100,
2))
|| '%'
AS INC_RATE
FROM ( SELECT TABLESPACE_ID,
TRUNC (TO_DATE (RTIME, 'mm/dd/yyyy hh24:mi:ss'))
DATETIME,
MAX (TABLESPACE_USEDSIZE * 8 / 1024)
USED_SIZE_MB,
LAG (MAX (TABLESPACE_USEDSIZE * 8 / 1024), 1, 0)
OVER (
PARTITION BY TABLESPACE_ID
ORDER BY
TRUNC (
TO_DATE (RTIME, 'mm/dd/yyyy hh24:mi:ss')))
AS PREV_USE_MB
FROM DBA_HIST_TBSPC_SPACE_USAGE
WHERE TRUNC (TO_DATE (RTIME, 'mm/dd/yyyy hh24:mi:ss')) >
TRUNC (SYSDATE - 30)
GROUP BY TABLESPACE_ID,
TRUNC (TO_DATE (RTIME, 'mm/dd/yyyy hh24:mi:ss')))) B
WHERE A.TS# = B.TABLESPACE_ID
ORDER BY B.TABLESPACE_ID, DATETIME;
本文主要参考文献为Oracle 12.2官方文档 ==> Database Concepts ==>Part IV Oracle Database Storage Structures ==> 12 Logical Storage Structures ==> Overview of Tablespaces