8i | 9i | 10g | 11g | 12c | 13c | 18c | 19c | 21c | 23c | Misc | PL/SQL | SQL | RAC | WebLogic | Linux
Oracle File System (OFS) and Database File System (DBFS) Enhancements in Oracle Database 12c Release 2 (12.2)
Oracle has a long history of functionality to present the database as a file system, with the latest incarnation being Oracle File System (OFS), available in Oracle Database 12.2 onward. OFS makes the setup and management of database backed file systems much simpler, as well as simplifying the management of FUSE to mount the file systems on the database server. This functionality can also be used to front existing file systems created with Database File System (DBFS).
Thanks to Dominic, Gregg, Margaret and Jose from Oracle for clearing up some of my doubts on this feature.
- Introduction
- OFS Server mounting an OFS File System
- OFS Server mounting a DBFS File System
- NFS Access via OFS Server
- OFS Miscellaneous
- DBFS POSIX File Locking
Related articles.
- Oracle Database File System (DBFS) in Oracle Database 11g Release 2
- Oracle Database File System (DBFS) PL/SQL APIs
- Oracle Database File System (DBFS) Enhancements in Oracle Database 12c Release 1 (12.1)
Introduction
Oracle 12.2 includes a new background process called OFSD, which manages file server worker threads.
$ ps -ef | grep [o]fs oracle 2663 1 0 May11 ? 00:36:56 ora_ofsd_cdb1 $
The performance of the OFS file server can be influenced by the OFS_THREADS
parameter, which defaults to the value 4, but has valid values between 2 and 128.
The OFS file server can currently front two types of database file system.
- OFS : A new database file system that is specific to OFS, and distinct from the DBFS file system of previous releases.
- DBFS : The database file system available from Oracle 11gR2 to present. You can read about this here.
Regardless of the underlying file system used (OFS or DBFS), the OFS server can be used to automatically mount the file system to a directory on the database server using FUSE. The OS mount point can optionally be exported using an NFS server, allowing NFS access to the database-backed file system.
FUSE Setup
Perform the following actions as the "root" user on the database server. If you are running in a RAC environment, you will need to perform these actions on all nodes in the cluster.
Make sure FUSE is installed on the Linux server. If you used the "oracle-database-server-12cR2-preinstall.x86_64" package as part of the server setup the following packages should already be installed.
# yum install kernel-devel fuse fuse-libs
Edit the "/etc/fuse.conf" file, un-commenting the "user_allow_other" option. The contents should look like this.
# mount_max = 1000 user_allow_other
Make sure "fusermount" is executable by all users.
# chmod +x /usr/bin/fusermount
Reboot the server.
# reboot
OFS Server mounting an OFS File System
Create a directory to be used as a mount point on the database server file system. If you create a new location as the "root" user, make sure it is owned by "oracle:oinstall". If the location is created as the "oracle" user, it will already have the correct ownership.
$ mkdir -p /u01/ofs/ofs_fs1
The following actions can only be performed in the root container of a multitenant instance, or in a non-CDB instance.
Create a new tablespace to hold the file system. In this case we are using Oracle Managed Files (OMF) so there is no need to specify the datafile location. If you are not using OMF, you will need to specify a file location. Notice the size of 500M.
CONN / AS SYSDBA CREATE TABLESPACE ofs_ts DATAFILE SIZE 500M AUTOEXTEND ON NEXT 1M;
Create a new OFS file system using the MAKE_ORACLE_FS
procedure in the DBMS_FS
package. The file system name specified by the FSNAME
parameter is used as part of the OFS object names. The FSOPTIONS
parameter allows us to specify the tablespace used during the object creation.
BEGIN DBMS_FS.make_oracle_fs ( fstype => 'ofs', fsname => 'ofs_fs1', fsoptions => 'TABLESPACE=ofs_ts'); END; /
We can see the tables used to define the OFS file system have been created.
COLUMN owner FORMAT A30 COLUMN table_name FORMAT A30 SELECT owner, table_name FROM dba_tables WHERE tablespace_name = 'OFS_TS' ORDER BY 1, 2; OWNER TABLE_NAME ------------------------------ ------------------------------ SYS OFS$OBJDATA_OFS_FS1 SYS OFS$OBJ_OFS_FS1 SQL>
We mount the OFS file system to the OS mount point using the MOUNT_ORACLE_FS
procedure, specifying the OFS file system name and the OS mount point, along with the mount options. The "persist" option means the mount will be automatically mounted on instance startup and unmounted on instance shutdown.
BEGIN DBMS_FS.mount_oracle_fs ( fstype => 'ofs', fsname => 'ofs_fs1', mount_point => '/u01/ofs/ofs_fs1', mount_options => 'default_permissions, allow_other, persist' ); END; /
Information about the mounts can be displayed using the V$OFSMOUNT
and V$OFS_STATS
views.
-- Mount information SET LINESIZE 200 COLUMN ofs_mntpath FORMAT A20 COLUMN ofs_fspath FORMAT A10 COLUMN ofs_mntopts FORMAT A45 COLUMN ofs_nodenm FORMAT A20 COLUMN ofs_fstype FORMAT A10 SELECT * FROM v$ofsmount; OFS_MNTPATH OFS_FSPATH OFS_MNTOPTS OFS_MNT CON_ID OFS_NODENM OFS_FSID OFS_FSTYPE -------------------- ---------- --------------------------------------------- ------- ---------- -------------------- ---------- ---------- /u01/ofs/ofs_fs1 ofs_fs1 default_permissions, allow_other, persist MOUNTED 1 ol7-122.localdomain 1 ofs SQL> -- Mount statistics SELECT * FROM v$ofs_stats ORDER BY 1;
We can see the mount point is available from the OS. Notice the size of the file system is incorrect. This is a known issue mentioned in the documentation.
$ df -h | grep fuse /dev/fuse 32G 0 32G 0% /u01/ofs/ofs_fs1 $
The file system can be used in the normal way.
$ echo "This is a test." >> /u01/ofs/ofs_fs1/test.txt $ cat /u01/ofs/ofs_fs1/test.txt This is a test. $ rm /u01/ofs/ofs_fs1/test.txt $
If we manually unmount the file system, the OFS server will no longer automatically mount it on instance startup. We have to manually unmount the file system using the UNMOUNT_ORACLE_FS
procedure before removing it.
CONN / AS SYSDBA BEGIN DBMS_FS.unmount_oracle_fs ( fsname => 'ofs_fs1', mount_point => '/u01/ofs/ofs_fs1', umount_options => 'force' ); END; /
Once unmounted we can remove the file system from the database using the DESTROY_ORACLE_FS
procedure.
BEGIN DBMS_FS.destroy_oracle_fs ( fstype => 'ofs', fsname => 'ofs_fs1' ); END; / SELECT owner, table_name FROM dba_tables WHERE tablespace_name = 'OFS_TS' ORDER BY 1, 2; no rows selected SQL>
It's now safe to drop the tablespace if you no longer need it.
DROP TABLESPACE ofs_ts INCLUDING CONTENTS AND DATAFILES;
OFS Server mounting a DBFS File System
We can use the OFS server to mount a file system created using DBFS. Although DBFS allows you to create the file system objects in a PDB and mount them using FUSE via the DBFS_CLIENT utility, if you want to use OFS to mount the DBFS file system it must be built in the root container of a multitenant instance, or in a non-CDB instance.
Create a directory to be used as a mount point on the database server file system. If you create a new location as the "root" user, make sure it is owned by "oracle:oinstall". If the location is created as the "oracle" user, it will already have the correct ownership.
$ mkdir -p /u01/dbfs/dbfs_fs1
Switch to the "$ORACLE_HOME/rdbms/admin" directory and start SQL*Plus.
cd $ORACLE_HOME/rdbms/admin sqlplus / as sysdba
Create a new tablespace to hold the file system. In this case I'm using Oracle Managed Files (OMF) so there is no need to specify the datafile location. If you are not using OMF, you will need to specify a file location.
CREATE TABLESPACE dbfs_ts DATAFILE SIZE 500M AUTOEXTEND ON NEXT 1M;
Manually create the DBFS objects using the "bfs_create_filesystem.sql" script, passing in the tablespace name and the file system name.
@dbfs_create_filesystem.sql dbfs_ts dbfs_fs1 No errors. SQL>
Mount the new file system using the MOUNT_ORACLE_FS
procedure, similar to the way it was done in the previous example. Notice the FSTYPE
parameter is set to 'dbfs'.
BEGIN DBMS_FS.mount_oracle_fs ( fstype => 'dbfs', fsname => 'dbfs_fs1', mount_point => '/u01/dbfs/dbfs_fs1', mount_options => 'default_permissions, allow_other, persist' ); END; /
Information about the mounts is available using the V$OFSMOUNT
and V$OFS_STATS
views.
-- Mount information SET LINESIZE 200 COLUMN ofs_mntpath FORMAT A20 COLUMN ofs_fspath FORMAT A10 COLUMN ofs_mntopts FORMAT A45 COLUMN ofs_nodenm FORMAT A20 COLUMN ofs_fstype FORMAT A10 SELECT * FROM v$ofsmount; OFS_MNTPATH OFS_FSPATH OFS_MNTOPTS OFS_MNT CON_ID OFS_NODENM OFS_FSID OFS_FSTYPE -------------------- ---------- --------------------------------------------- ------- ---------- -------------------- ---------- ---------- /u01/dbfs/dbfs_fs1 dbfs_fs1 default_permissions, allow_other, persist MOUNTED 1 ol7-122.localdomain 7 dbfs SQL>
We can see the mount point is available from the OS. Notice the size of the file system is incorrect. This is a known issue mentioned in the documentation.
$ df -h | grep fuse /dev/fuse 1.2G 128K 1.2G 1% /u01/dbfs/dbfs_fs1 $
The file system can be used in the normal way.
$ echo "This is a test." >> /u01/dbfs/dbfs_fs1/test.txt $ cat /u01/dbfs/dbfs_fs1/test.txt This is a test. $ rm /u01/dbfs/dbfs_fs1/test.txt $
If we manually unmount the file system, the OFS server will no longer automatically mount it on instance startup. We have to manually unmount the file system using the UNMOUNT_ORACLE_FS
procedure before removing it.
BEGIN DBMS_FS.unmount_oracle_fs ( fsname => 'dbfs_fs1', mount_point => '/u01/dbfs/dbfs_fs1', umount_options => 'force' ); END; /
Once unmounted we can remove the file system from the database using the "dbfs_drop_filesystem.sql" script, passing in the file system name.
@dbfs_drop_filesystem.sql dbfs_fs1 No errors. SQL>
It's now safe to drop the tablespace if you no longer need it.
DROP TABLESPACE dbfs_ts INCLUDING CONTENTS AND DATAFILES;
NFS Access via OFS Server
Once OFS has been used to mount the file system, it can be exported by a NFS server. You can read more about NFS configuration here, but the following is a simple example of using NFS with OFS. This example assumes you have completed the example in the Oracle File System (OFS) section above.
Install and enable the NFS server.
# yum install nfs-utils -y # # Using service command. # service nfs start # chkconfig nfs on # # Using systemctl command (RHEL7/OL7/CentOS7). # systemctl start nfs # systemctl enable nfs
Edit (or create if missing) the "/etc/exports" file, appending the following contents.
/u01/ofs/ofs_fs1 *(rw,fsid=1)
Reload the NFS configuration.
# exportfs -ra # showmount -e
Create a mount point and mount the NFS share to it.
# mkdir -p /mnt/ofs_fs1 # mount ol7-122.localdomain:/u01/ofs/ofs_fs1 /mnt/ofs_fs1 -t nfs -o vers=3
You can unmount the NFS share as follows.
# umount /mnt/ofs_fs1
OFS Miscellaneous
Here are some miscellaneous points about OFS.
- The current version of the OFS functionality is not multitenant friendly. This may change in future. You can still use DBFS in a PDB and manually mount it using FUSE and the
dbfs_client
utility, as you did in previous versions, since that connects using a service. You can't use OFS to manage a DBFS file system stored in a PDB or in a different user in the root container. - The reliance on FUSE means that the OFS functionality is a Linux-only feature at this point.
- As mentioned previously, the performance of the OFS file server can be influenced by the
OFS_THREADS
parameter. This defaults to the value 4, but has valid values between 2 and 128. The documentation states all RAC nodes should use the same value. - The mounts to the OS using FUSE seem to function consistently, but the NFS functionality over FUSE can be a little erratic. Not surprisingly, you need to make sure the NFS mount happens after FUSE has mounted the file system. A number of times I had to manually restart the NFS service to get things working again after a server restart.
- You shouldn't attempt to manually unmount the file system using
umount
orfusermount
. It will leave the file system in an inconsistent state. - If you do a
SHUTDOWN ABORT
on the instance you will need to unmount and mount the file system using theUNMOUNT_ORACLE_FS
andMOUNT_ORACLE_FS
procedures to mount it properly and make it auto-mount in future. - You can read some more of my opinions and answers to some questions about OFS here.
DBFS POSIX File Locking
In Oracle 12.2 DBFS supports POSIX file locking (full-file locking only) when DBFS is access using the DBFS_CLIENT (included mounts via FUSE) or the PL/SQL APIs. You can read about this support here.
For more information see:
- Introducing Network File System (NFS)
- DBMS_FS
- OFS_THREADS
- Oracle Database File System (DBFS) in Oracle Database 11g Release 2
- Oracle Database File System (DBFS) PL/SQL APIs
- Oracle Database File System (DBFS) Enhancements in Oracle Database 12c Release 1 (12.1)
Hope this helps. Regards Tim...