Oracle 表空间和数据文件遇到的坑 (转载于 微信公众号 JieKeXu DBA之路)
转载链接https://mp.weixin.qq.com/s/IKF_KrWkxZ5BJS-OacYWUw
前言
本文适用于普通的标准的 8k 块大小的 Oracle 企业版数据库,10g、11g、19c 均可适用,但对于 ODA,一体机可能有所区别,请慎重使用
1.db_files 的坑
记录一下年前遇到的一个关于表空间扩容的小问题,大家都知道对于 Oracle 普通的表空间直接 alter tablespace XX add datafile 添加数据文件则就可以扩容了。但是当执行此命令时却报错了 ORA-00059。
SQL> alter tablespace PROD_DATA add datafile '+DATA' size 30g; alter tablespace DWD_DATA add datafile '+DATA' size 30g * ERROR at line 1: ORA-00059: maximum number of DB_FILES exceeded SQL> exit Disconnected [oracle@JiekeXu ~]$ oerr ora 58 00058, 00000, "DB_BLOCK_SIZE must be %s to mount this database (not %s)" // *Cause: DB_BLOCK_SIZE initialization parameter is wrong for the database // being mounted. It does not match the value used to create the // database. // *Action: Fix the value of the DB_BLOCK_SIZE parameter or mount a database // that matches the value. [oracle@JiekeXu ~]$ oerr ora 59 00059, 00000, "maximum number of DB_FILES exceeded" // *Cause: The value of the DB_FILES initialization parameter was exceeded. // *Action: Increase the value of the DB_FILES parameter and warm start.
报错很明显,DB_FILES 达到最大值了,oerr 给出的答案也很合理,增加 DB_FILES 的值,然后重启数据库。
查看数据库 DB_FILES 参数,果然是默认的 200,刚好 dba_data_files 也已经达到了 200 个,所以添加数据文件时则直接报错 ORA-00059 了,查看后台 alert 日志报错一样。这就实属被坑了一把,生产环境又不能随便修改参数重启,只能申请变更窗口,坑呀。
SQL> show parameter DB_FILES NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_files integer 200 SQL> select count(*) from dba_data_files; COUNT(*) ---------- 200 -- 查看后台 alert 日志报错一样 2024-02-24T14:11:43.317617+08:00 alter tablespace PROD_DATA add datafile '+DATA' size 30g 2024-02-24T14:12:31.614611+08:00 ORA-59 signalled during: alter tablespace PROD_DATA add datafile '+DATA' size 30g...
DB_FILES 是 Oracle 比较重要的一个参数,当你的数据量不太大的时候(大概 5TB以内,200*30G),这个参数不用修改是没有问题的,但你不能保证这个库以后的数据增长量不大于5TB,所以一般在建库的时候随着其他核心参数一起调整了,
但这个库是前人 19年创建的,参数几乎都是默认值,也由于当时数据量较少的缘故,所以到现在也没去关注这个参数。
那么,这个参数应该改为多少才合适呢?对于 RAC+ADG 而言是否可以滚动重启实例呢?我们来看看官方文档吧。如下图所示,DB_FILES 的默认值为 200,可以在 PDB 级别修改,最小值则是数据库中数据文件的绝对文件数中最大值,最大值则取决于操作系统。
RAC 实例则需要全部重启方可生效,如果增加 DB_FILES 的值,则必须关闭并重新启动所有访问数据库的实例,新值才能生效。
如果您有一个主库和备库,那么它们应该具有相同的此参数值。https://docs.oracle.com/en/database/oracle/oracle-database/19/refrn/DB_FILES.html#GUID-DD8C2F18-F04D-43F7-A9C3-5EAAAB9E9DEE
考虑将数据文件添加到表空间时可能存在的限制
将数据文件添加到表空间时需要考虑一些限制。
-
您可以将数据文件添加到传统的小文件表空间,但要遵守以下限制:
-
操作系统通常对进程可以同时打开的文件数施加限制。当达到打开文件的操作系统限制时,无法创建更多数据文件。
-
操作系统对数据文件的数量和大小施加了限制。
-
该数据库对任何实例打开的任何 Oracle 数据库的数据文件数施加了最大限制。此限制是特定于操作系统的。
-
不能超过超过 DB_FILES 参数指定的数据文件数。
-
发出CREATE DATABASE或CREATE CONTROLFILE语句时,MAXDATAFILES参数指定控制文件的数据文件部分的初始大小。但是,如果尝试添加数量大于MAXDATAFILES但小于或等于DB_FILES的新文件,则控制文件将自动展开,以便数据文件部分可以容纳更多文件。
确定 DB_FILES 初始化参数的值
启动 Oracle Database 实例时,DB_FILES 初始化参数指示要为数据文件信息保留的 SGA 空间量,从而指示可以为实例创建的最大数据文件数。此限制适用于实例的生命周期。您可以更改 DB_FILES 的值(通过更改初始化参数设置),但新值在您关闭并重新启动实例之前不会生效。
在确定 DB_FILES 的值时,请考虑以下因素:
-
如果 DB_FILES 的值太低,则在不先关闭数据库的情况下,无法添加超出限制的数据文件。
-
如果 DB_FILES 的值太高,则不必要地消耗内存。
由此可见这个参数,主备库均要修改且重启生效,RAC 不能滚动重启,需要全部重启,ADG 备库也要修改并重启生效。那么这个值既然依赖操作系统,改为多少合适呢?以前运维的系统中有遇到过 1000、2000、4000、5000、8000 大概这几个值的,那么本次我们来修改为 100000 试试呢?通过测试在 Linux 虚拟机下可以看出 DB_FILES 参数最大支持 65534,则同一个库下数据文件最多有 65534 个。
SQL> show parameter spfile SQL> create pfile='/tmp/pfile_20240229.ora' from spfile; File created. SQL> show parameter db_files; NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_files integer 200 SQL> alter system set db_files=100000 scope=spfile; System altered. SQL> shu immediate; Database closed. Database dismounted. ORACLE instance shut down. SQL> startup ORA-01131: DB_FILES system parameter value 100000 exceeds limit of 65534 ORA-01078: failure in processing system parameters
既然已经知道了最大值,那么生产环境则可以选择一个适合的值,比如 2000、4000 等,也不能太大,不然和我上面测试一样,当设置为 65534 时需要 750M 左右的 shared pool 才能启动成功,设置为 10000 时需要 296M 的 shared pool 才能启动成功,无奈则设置成 5000 时可以正常启动。
SQL*Plus: Release 12.2.0.1.0 Production on Fri Mar 1 00:27:51 2024 Copyright (c) 1982, 2016, Oracle. All rights reserved. Connected to an idle instance. 00:27:52 SYS@JiekeXu> startup pfile='/tmp/pfile_20240229.ora' ORA-00371: not enough shared pool memory, should be at least 310153892 bytes 00:27:58 SYS@JiekeXu> !vi /tmp/pfile_20240229.ora 00:28:48 SYS@JiekeXu> startup pfile='/tmp/pfile_20240229.ora' ORACLE instance started. Total System Global Area 2147483648 bytes Fixed Size 8794848 bytes Variable Size 2080378144 bytes Database Buffers 50331648 bytes Redo Buffers 7979008 bytes Database mounted. Database opened. 00:29:11 SYS@JiekeXu> show parameter db_files NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_files integer 5000 00:29:19 SYS@JiekeXu> 00:31:06 SYS@JiekeXu> select 781994571/1024/1024/1024 from dual; 781994571/1024/1024/1024 ------------------------ .728289197 Elapsed: 00:00:00.00 00:31:35 SYS@JiekeXu> select 781994571/1024/1024 MB from dual; MB ---------- 745.768138 Elapsed: 00:00:00.00 00:31:42 SYS@JiekeXu> show parameter sga NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ allow_group_access_to_sga boolean FALSE lock_sga boolean FALSE pre_page_sga boolean TRUE sga_max_size big integer 2G sga_min_size big integer 0 sga_target big integer 0 unified_audit_sga_queue_size integer 1048576 00:31:50 SYS@JiekeXu> 00:32:14 SYS@JiekeXu> show parameter share NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ hi_shared_memory_address integer 0 max_shared_servers integer shared_memory_address integer 0 shared_pool_reserved_size big integer 13421772 shared_pool_size big integer 256M shared_server_sessions integer shared_servers integer 1 00:32:25 SYS@JiekeXu> select 310153892/1024/1024 MB from dual; MB ---------- 295.785801
解决生产问题
通过上面的验证测试我们已经知道了大概,接下来我们则需要对生产环境的参数进行修改和重启了。如下表空间使用率已经超过 90% 了,需要扩容但是由于 DB_FILES 默认为 200,dba_data_files 也已经达到了 200,所以我忙需要修改此参数为 2048 然后先重启备库再同时重启主库 RAC。
SQL> SELECT a.tablespace_name,round(total/1024/1024/1024) "Total g", 2 round(free/1024/1024/1024) "Free g",ROUND((total-free)/total,4)*100 "USED%" 3 FROM (SELECT tablespace_name,SUM(bytes) free FROM 4 DBA_FREE_SPACE 5 GROUP BY tablespace_name ) a, 6 (SELECT tablespace_name,SUM(bytes) total FROM DBA_DATA_FILES 7 GROUP BY tablespace_name) b 8 WHERE a.tablespace_name=b.tablespace_name and ROUND((total-free)/total,4)*100 >= 85 9 ORDER BY 4; TABLESPACE_NAME Total g Free g USED% ------------------------------ ---------- ---------- ---------- EW_DATA 334 49 85.21 OS_DATA 2516 261 89.61 DD_DATA 2195 176 91.98 SQL> alter tablespace DD_DATA add datafile '+DATA' size 30g; alter tablespace DD_DATA add datafile '+DATA' size 30g * ERROR at line 1: ORA-00059: maximum number of DB_FILES exceeded SQL> show parameter DB_FILES NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_files integer 200 SQL> select count(*) from dba_data_files; COUNT(*) ---------- 200 --后台 alert 日志告警信息 2024-02-24T14:11:43.317617+08:00 alter tablespace DD_DATA add datafile '+DATA' size 30g 2024-02-24T14:12:31.614611+08:00 ORA-59 signalled during: alter tablespace DD_DATA add datafile '+DATA' size 30g... --查看应用登录总连接 ps -ef | grep -i local=no | grep -v grep | awk '{print $2}' | wc -l $ sys SQL*Plus: Release 19.0.0.0.0 - Production on Sat Feb 24 14:08:14 2024 Version 19.15.0.0.0 Copyright (c) 1982, 2022, Oracle. All rights reserved. Connected to: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.15.0.0.0 SQL> SQL> alter system set db_files=2048 scope=spfile sid='*'; System altered. SQL> shu immediate Database closed. Database dismounted. ORACLE instance shut down. SQL> SQL> startup ORA-32004: obsolete or deprecated parameter(s) specified for RDBMS instance ORACLE instance started. Total System Global Area 1.6106E+11 bytes Fixed Size 37218432 bytes Variable Size 9.3952E+10 bytes Database Buffers 6.6572E+10 bytes Redo Buffers 499650560 bytes Database mounted. Database opened.
如上启动实例时报错 ORA-32004,有过期的参数倒也没有其他问题,可以忽略正常启动,也可以去 alert 日志中查找 Deprecated 过期的参数将其删除掉重启也行,看个人意愿了。
============================================ _serial_direct_read = "NEVER" _optim_peek_user_binds = FALSE pga_aggregate_target = 30G _optimizer_mjc_enabled = FALSE deferred_segment_creation= FALSE parallel_force_local = TRUE _optimizer_use_feedback = FALSE _sql_plan_directive_mgmt_control= 0 _optimizer_ads_use_result_cache= FALSE _optimizer_dsdir_usage_control= 0 optimizer_adaptive_plans = FALSE _optimizer_gather_stats_on_load_index= FALSE _optimizer_gather_stats_on_conventional_dml= FALSE diagnostic_dest = "/u01/app/oracle" Deprecated system parameters with specified values: cluster_database_instances SQL> show parameter cluster_database_instances NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ cluster_database_instances integer 2 SQL> show parameter db_files NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_files integer 2048 SQL>
表空间限制的坑
Oracle 数据库将表空间中的数据在物理上存储为数据文件。
每个非分区模式对象和对象的每个分区都存储在它自己的段中,它只属于一个表空间。例如,非分区表的数据存储在单个段中,最终也存储在一个表空间中。表空间和数据文件密切相关, 但又有重要区别:
-
每个表空间包含一个或多个数据文件, 这需要遵从运行 Oracle 数据库的操作系统。
-
数据库数据被集中地存储在位于每个数据库表空间的数据文件中。
-
段可以跨越一个或多个数据文件,但它不能跨多个表空间。
-
数据库必须有 SYSTEM 表空间和 SYSAUX 表空间。Oracle 数据库自动在数据库创建过程中为 SYSTEM 表空间分配数据库的第一个数据文件。
SYSTEM 表空间包含数据字典,它是包含数据库元数据的一组表。通常,数据库也有一个 UNDO 表空间和临时表空间 (通常称为 TEMP)。
大文件表空间扩容
对于大文件表空间而言只有一个数据文件,所以扩容就比较简单,如果有空闲存储空间的话,直接 resize 即可。
ALTER TABLESPACE ORCL_DAT RESIZE 11000G;
小文件表空间扩容
对于小文件表空间而言有一个或多个数据文件,如果有空闲存储空间的话,直接 resize 原有数据文件到仅小于 32G 即可,也可以直接添加数据文件。
alter tablespace ORCL_DATA add datafile '/var/ora_data02/oradata/ORCL/ORCL_DataB_1025.dbf' size 30G;
如下是一个 10g 库小文件扩容示例,仅供参考。
1)、查询数据库基本信息和块大小
SQL*Plus: Release 10.2.0.4.0 - Production on Thu Nov 19 20:42:49 2023 Copyright (c) 1982, 2007, Oracle. All Rights Reserved. Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production With the Partitioning, OLAP, Data Mining and Real Application Testing options SQL> set line 345 col instance_name for a15 col host_name for a30 select inst_id,INSTANCE_NAME,HOST_name,status,version,STARTUP_TIME from gv$instance; SQL> SQL> SQL> INST_ID INSTANCE_NAME HOST_NAME STATUS VERSION STARTUP_TIME ---------- --------------- ------------------------------ ------------ ----------------- ------------ 1 ORCL XF0000YX OPEN 10.2.0.4.0 06-NOV-21 SQL> show parameter db_block_size NAME TYPE VALUE ------------------------------------ -------------------------------- ------------------------------ db_block_size integer 8192
2)、查看表空间类型(是否为大文件表空间)
select name,bigfile from v$tablespace where name='&name'; SQL> select name ,bigfile from v$tablespace where name='&name'; Enter value for name: ORCL_DATAB old 1: select name ,bigfile from v$tablespace where name='&name' new 1: select name ,bigfile from v$tablespace where name='ORCL_DATAB' NAME BIG ------------------------------ --- ORCL_DATAB NO Elapsed: 00:00:00.01
3)、查看数据文件存放路径,大小:
SQL> set line 9999 pages 9999 SQL> col file_name for a66 select file_id,tablespace_name,file_name,bytes/1024/1024 mb ,autoextensible from dba_data_files where tablespace_name='ORCL_DATAB' order by tablespace_name desc; ----省略部分显示,总共 1023 行---- 2042 ORCL_DATAB /var/ora_data/oradata/ORCL/ORCL_DataB_1013.dbf 4096 NO 2043 ORCL_DATAB /var/ora_data/oradata/ORCL/ORCL_DataB_1014.dbf 4096 NO 2044 ORCL_DATAB /var/ora_data/oradata/ORCL/ORCL_DataB_1015.dbf 4096 NO 2045 ORCL_DATAB /var/ora_data/oradata/ORCL/ORCL_DataB_1016.dbf 4096 NO 2046 ORCL_DATAB /var/ora_data/oradata/ORCL/ORCL_DataB_1017.dbf 4096 NO 2047 ORCL_DATAB /var/ora_data/oradata/ORCL/ORCL_DataB_1018.dbf 4096 NO 2048 ORCL_DATAB /var/ora_data/oradata/ORCL/ORCL_DataB_1019.dbf 4096 NO 2049 ORCL_DATAB /var/ora_data/oradata/ORCL/ORCL_DataB_1020.dbf 4096 NO 2050 ORCL_DATAB /var/ora_data/oradata/ORCL/ORCL_DataB_1021.dbf 4096 NO 2051 ORCL_DATAB /var/ora_data/oradata/ORCL/ORCL_DataB_1022.dbf 4096 NO 2052 ORCL_DATAB /var/ora_data/oradata/ORCL/ORCL_DataB_1023.dbf 4096 NO 1023 rows selected. Elapsed: 00:00:01.09
4)、查看参数及 dba_data_files 总大小
SQL> select count(file_name) from dba_data_files; COUNT(FILE_NAME) ---------------- 2422 Elapsed: 00:00:00.28 SQL> show parameter db_files NAME TYPE VALUE ------------------------------------ -------------------------------- ------------------------------ db_files integer 5000
5)、查看表空间使用率及存储磁盘使用率
如下是以前的惠普 UNIX 系统
SQL> set pages 345 timing on col TABLESPACE_NAME for a28 SELECT a.tablespace_name,round(total/1024/1024/1024) "Total g",round(free/1024/1024/1024) "Free g",ROUND((total-free)/total,4)*100 "USED%" 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 ORDER BY 4; SQL> SQL> 2 3 TABLESPACE_NAME Total g Free g USED% ---------------------------- ---------- ---------- ---------- ORCL_UNDO 100 100 0 POWERCENTER 219 218 .55 UNDOTBS1 1002 981 2.18 SYSTEM 33 32 2.72 ANTIF_TB 192 183 4.46 USERS 54 48 9.52 SYSAUX 6 4 38.41 ORCL_DATAA 13512 4352 67.79 ORCL_DATAC 4140 1187 71.34 ORCL_INDEX 2584 677 73.8 ORCL_DATAB 6094 1467 75.92 11 rows selected. Elapsed: 00:00:04.62 SQL> !bdf Filesystem kbytes used avail %used Mounted on /dev/vg00/lvol3 1048576 392632 651712 38% / /dev/vg00/lvol1 1835008 562656 1262456 31% /stand /dev/vg00/lvol8 8912896 3246256 5628640 37% /var /dev/ORCLdatavg/ora_data_lv02 14410530816 11017427096 3366595912 77% /var/ora_data02 /dev/ORCLdatavg/ora_data_lv01 20955955200 20360127344 591174080 97% /var/ora_data /dev/vg00/lvol7 7405568 3782936 3594384 51% /usr /dev/vg00/lvol4 10485760 4700584 5740800 45% /tmp /dev/vg00/lvol6 11599872 6659344 4901976 58% /opt /dev/ORCLvg01/lvol_ORCL01 102400000 61129934 38696156 61% /opt/ORCL /dev/vg00/lvinstall 10485760 4085065 6000758 41% /install /dev/vg00/lvol5 2097152 35888 2045264 2% /home /dev/ORCLvg01/lvol_ORCL02 102400000 15970491 81027767 16% /home/ORCL /dev/archvg/archlv 5364776960 156564944 5167523472 3% /arch
附:UNIX 系统常用命令
bdf 以 KB 为单位查看大小 以G为单位查看文件夹/文件大小 du -sk * | awk '{print $1/1024/1024,$2}' du -sk *.dmp | awk '{print $1/1024/1024,$2}' 关机和重启 关机: shutdown -hy 0 重启: shutdown -ry 0 --如无法重启,可使用reboot 查看所有硬件信息:#print_manifest 查看CPU信息:#ioscan -fnkC processor 查看网卡:# lanscan 查看网卡的ip地址: # ifconfig lan0 # more /etc/rc.config.d/netconf 查看接口IP及掩码配置:# netstat -rnv 查看操作系统版本和 license:#uname -a 查看物理内存大小:# dmesg 查看硬盘 # ioscan -fnC disk 硬盘的个数 # ioscan -funC disk 硬盘的大小信息 # diskinfo /dev/rdsk/c1t0d0 查看扫描到的新磁盘: # ioscan -fNnkC disk # ioscan -m lun HP-UX主要使用HFS和VXFS两种文件系统 insf -e -C disk 扫描新盘 格式化磁盘(一般不进行此操作) #mediainit /dev/rdsk/c2t1d0 查看是否同一块盘 ## ioscan -m dsf HP-UX 11i v3 操作系统默认开启NMP,通过 scsimgr 命令进行确认: # scsimgr get_attr -a leg_mpath_enable 查看磁盘的wwid: scsimgr lun_map -D /dev/rdisk/disk41 |grep WWID #ioscan -fnC disk ioscan是扫描并列出所有设备和发现的其他设备, -f表示显示完整列表, -C表示类别, -k表示扫描内核的设备文件,默认是扫描机器实际有的, -n表示只列出/dev/下的设备文件。 fc 口查看 #ioscan -fnC fc #fcmsutil /dev/fcoc0 查看路由信息 #netstat -an
6)、扩容表空间
SQL> alter tablespace ORCL_DATAB add datafile '/var/ora_data02/oradata/ORCL/ORCL_DataB_1025.dbf' size 30G; alter tablespace ORCL_DATAB add datafile '/var/ora_data02/oradata/ORCL/ORCL_DataB_1025.dbf' size 30G * ERROR at line 1: ORA-01686: max # files (1023) reached for the tablespace ORCL_DATAB Elapsed: 00:02:10.89 SQL> SQL> select count(file_name) from dba_data_files where tablespace_name='ORCL_DATAB'; COUNT(FILE_NAME) ---------------- 1023 Elapsed: 00:00:00.18 --通过 oerr 也给出了解释办法,resize 已存在的数据文件,或者迁移一些对象到其他表空间。 $ oerr ORA 01686 01686, 00000, "max # files (%s) reached for the tablespace %s" // *Cause: The number of files for a given tablespace has reached its maximum // value // *Action: Resize existing files in the tablespace, or partition the objects // among multiple tablespaces, or move some objects to a different // tablespace. -- 后台 alert 日志记录如下: Thu Nov 19 20:28:07 2023 alter tablespace ORCL_DATAB add datafile '/var/ora_data02/oradata/ORCL/ORCL_DataB_1025.dbf' size 30G Thu Nov 19 20:30:18 2023 ORA-1686 signalled during: alter tablespace ORCL_DATAB add datafile '/var/ora_data02/oradata/ORCL/ORCL_DataB_1025.dbf' size 30G..
官方文档中也有对数据文件的描述:数据文件是操作系统的物理文件,用于存储数据库中所有逻辑结构的数据。必须为每个表空间显式地创建它们。Oracle 数据库为每个数据文件分配两个相关的文件号,一个是绝对文件号,另一个是相对文件号,用于唯一标识数据文件。下面介绍了这些编号:
-
绝对文件号:此文件号可用于许多引用数据文件而不使用文件名的 SQL 语句。绝对文件号可以在 VDATAFILE 或 VTEMPFILE 视图的 file# 列中,或在 DBA_DATA_FILES 或 DBA_TEMP_FILES 视图的 file_ID 列中找到。
-
相对文件号:对于中小型数据库,相对文件号通常与绝对文件号具有相同的值。然而,当数据库中的数据文件数量超过阈值(通常为1023)时,相对文件数量与绝对文件数量不同。在 bigfile 表空间中,相对文件号始终为 1024(在 OS/390 平台上为 4096)。
总 结
最后总结记录一下,对于 8k 大小的数据块而言,普通单个表空间(非大文件表空间)数据文件个数不能大于等于 1024 个(即每个表空间最大 1023 个数据文件),每个数据文件大小也不能超过 32G(即每个数据文件可以设置为 32767M),数据库总的数据文件最多有 65534 个,但也受操作系统和 shared pool 内存的限制,不能过大也不能过小,按照库数据量大小可设置为 2000、4000、6000、8000 等值。