8i | 9i | 10g | 11g | 12c | 13c | 18c | 19c | 21c | 23c | Misc | PL/SQL | SQL | RAC | WebLogic | Linux

Home » Articles » 12c » Here

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.

Related articles.

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.

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.

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:

Hope this helps. Regards Tim...

Back to the Top.