Oracle Database File System (DBFS) in Oracle Database 11g Release 2
Oracle has quite a long history with database file systems. The Oracle Internet File System (iFS) was released in the Oracle 8i days. This product was later renamed to Oracle Content Management SDK. The introduction of XML DB in Oracle 9i Release 2 brought with it a database file system accessible from HTTP, FTP and WebDAV for the storage of XML files. Now Oracle 11g Release 2 introduces DBFS, the Oracle Database File System.DBFS creates a file system interface on top of database tables that store files as SecureFile LOBs. External access to the file system is via a client program (dbfs_client), which is only available for Linux and Solaris platforms. The client is already installed on the database server, but can also be installed on client machines, giving them access to the centralized database file system. On Linux platforms the dbfs_client can be used to mount the database file system on a regular mount point. This done using the "Filesystem in Userspace" (FUSE) project. This allows Linux machines to access DBFS like any other physical file system.
In this article I'll show the steps necessary to mount the DBFS on a Linux server. I'm not going to discuss the DBFS Content API, DBFS SecureFile Store or DBFS Hierarchical Store directly, although some of these are called by scripts used in this article.
- FUSE Installation
- Creating a File System
- Mounting a File System
- Wallet Creation
- Using /etc/fstab
- dbfs_client Command Interface
FUSE Installation
In order to mount the DBFS we need to install the "Filesystem in Userspace" (FUSE) software. If you are not planning to mount the DBFS or you are running on an Non-Linux platform, this section is unnecessary.Check to see if the "kernel-devel" package is installed.
If not, then install it using the following command.rpm -q kernel-devel kernel-devel-2.6.18-128.el5 #
Download the FUSE 2.7.3 package from http://fuse.sourceforge.net/.# yum install kernel-devel
Determine the kernel directory.
Install the FUSE package as the "root" user using the following commands, substituting your kernel directory.# echo /usr/src/kernels/`uname -r`-`uname -p` /usr/src/kernels/2.6.18-128.el5-x86_64 #
# tar -xzvf fuse-2.7.3.tar.gz # cd fuse-2.7.3 # ./configure --prefix=/usr --with-kernel=/usr/src/kernels/2.6.18-128.el5-x86_64 # make # make install # /sbin/depmod # /sbin/modprobe fuse # chmod 666 /dev/fuse # echo "/sbin/modprobe fuse" >> /etc/rc.modules # chmod 700 /etc/rc.modules
Creating a File System
First we must create a tablespace to hold the file system.Next, we create a user, grant DBFS_ROLE to the user and make sure it has a quota on the tablespace. Trying to create a file system from the SYS user fails, so it must be done via another user.CONN / AS SYSDBA CREATE TABLESPACE dbfs_ts DATAFILE '/u01/app/oracle/oradata/DB11G/dbfs01.dbf' SIZE 1M AUTOEXTEND ON NEXT 1M;
Next we create the file system in tablespace by running the "dbfs_create_filesystem.sql" script as the test user. The script accepts two parameters identifying the tablespace and file system name.CONN / AS SYSDBA CREATE USER dbfs_user IDENTIFIED BY dbfs_user DEFAULT TABLESPACE dbfs_ts QUOTA UNLIMITED ON dbfs_ts; GRANT CONNECT, CREATE TABLE, CREATE PROCEDURE TO dbfs_user; GRANT dbfs_role TO dbfs_user;
The script created a partitioned file system. Although Oracle consider this the best option from a performance and scalability perspective, it can have two drawbacks:cd $ORACLE_HOME/rdbms/admin sqlplus dbfs_user/dbfs_user SQL> @dbfs_create_filesystem.sql dbfs_ts staging_area
- Space cannot be shared between partitions. If the size of the files is small compared to the total file system size this is not a problem, but if individual files form a large proportion of the total file system size, then ENOSPC errors may be produced.
- File rename operations may require the file to be rewritten, which can be problematic for large files.
If we later wish to drop a file system, this can be done using the "dbfs_drop_filesystem.sql" script with the file system name.
cd $ORACLE_HOME/rdbms/admin sqlplus test/test SQL> @dbfs_drop_filesystem.sql staging_area
Mounting a File System
The dbfs_client tool is used to mount file systems on Linux servers. The usage is displayed if you call it without any parameters.
$ dbfs_client
usage: dbfs_client <db_user>@<db_server> [options] <mountpoint>
db_user: Name of Database user that owns DBFS content repository filesystem(s)
db_server: A valid connect string for Oracle database server
(for example, hrdb_host:1521/hrservice)
mountpoint: Path to mount Database File System(s)
All the file systems owned by the database user will be seen at the mountpoint.
DBFS options:
-o direct_io Bypass the Linux page cache. Gives much better performance for large files.
Programs in the file system cannot be executed with this option.
This option is recommended when DBFS is used as an ETL staging area.
-o wallet Run dbfs_client in background.
Wallet must be configured to get credentials.
-o failover dbfs_client fails over to surviving database instance with no data loss.
Some performance cost on writes, especially for small files.
-o allow_root Allows root access to the filesystem.
This option requires setting 'user_allow_other' parameter in '/etc/fuse.conf'.
-o allow_other Allows other users access to the file system.
This option requires setting 'user_allow_other' parameter in '/etc/fuse.conf'.
-o rw Mount the filesystem read-write. [Default]
-o ro Mount the filesystem read-only. Files cannot be modified.
-o trace_file=STR Tracing <filename> | 'syslog'
-o trace_level=N Trace Level: 1->DEBUG, 2->INFO, 3->WARNING, 4->ERROR, 5->CRITICAL [Default: 4]
-h help
-V version
[oracle@oel5-11gr2 admin]$
First we need to create a mount point with the necessary privileges as the "root" user.The file system we've just created is mounted with the one of the following commands.# mkdir /mnt/dbfs # chown oracle:oinstall /mnt/dbfs
The wallet authentication is really the only sensible method to use as all other methods potentially expose the credentials. Creation of a wallet is discussed later.$ # Connection prompts for password and holds session. $ dbfs_client dbfs_user@DB11G /mnt/dbfs $ # Connection retrieves password from file and releases session. $ nohup dbfs_client dbfs_user@DB11G /mnt/dbfs < passwordfile.f & $ # Connection authenticates using wallet and releases session. $ nohup dbfs_client -o wallet /@DB11G_DBFS_USER /mnt/dbfs &
Once mounted, the "staging_area" file system is now available for use.
To unmount the file system issue the following command.$ ls -al /mnt/dbfs total 8 drwxr-xr-x 3 root root 0 Jan 6 17:02 . drwxr-xr-x 3 root root 4096 Jan 6 14:18 .. drwxrwxrwx 3 root root 0 Jan 6 16:37 staging_area $ ls -al /mnt/dbfs/staging_area total 0 drwxrwxrwx 3 root root 0 Jan 6 16:37 . drwxr-xr-x 3 root root 0 Jan 6 17:02 .. drwxr-xr-x 7 root root 0 Jan 6 14:00 .sfs $
$ fusermount -u /mnt/dbfs
Wallet Creation
To create a wallet issue the following commands.Add the following lines to the "$ORACLE_HOME/network/admin/sqlnet.ora" file.$ mkdir -p $HOME/oracle/wallet $ mkstore -wrl $HOME/oracle/wallet -create
Add the credentials to the wallet for a specific connect string. This could be the existing connect string (DB11G in mycase), but in this example I've used something a little more specific (DB11G_DBFS_USER).WALLET_LOCATION = (SOURCE = (METHOD = FILE) (METHOD_DATA = (DIRECTORY = $HOME/oracle/wallet) ) ) SQLNET.WALLET_OVERRIDE = TRUE
Make sure the connect string is present in the "$ORACLE_HOME/network/admin/tnsnames.ora" file. In this case I just copied my existing connect string and gave it the new name.mkstore -wrl $HOME/oracle/wallet -createCredential DB11G_DBFS_USER dbfs_user dbfs_user
DB11G_DBFS_USER =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = oel5-11gr2.localdomain)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = DB11G.WORLD)
)
)
The file system can now be mounted using the wallet.$ nohup dbfs_client -o wallet /@DB11G_DBFS_USER /mnt/dbfs &
Using /etc/fstab
Warning: The documentation for this step is not complete and even when I try to fill in the gaps I'm not left with a working mount point. I've left this section in the document because I'm sure someone will very quickly inform me of my mistake. :)Apart from having a familiar syntax, the use of the "/etc/fstab" file for mounting seems a little pointless since FUSE does not support automount, so you will still have to manually mount the file systems after a reboot. Actually this is fortunate as the automount would probably happen before the database was up, which would of course would be an issue.
To allow mount operations from the "/etc/fstab", issue the following commands as the "root" user.
Add the following line into the "/etc/fstab" file.# ln -s /u01/app/oracle/product/11.2.0/db_1/bin/dbfs_client /sbin/mount.dbfs # groupadd fuse # usermod -a -G fuse oracle
Append the following lines into the "/etc/ld.so.conf" file./sbin/mount.dbfs#/@DB11G_DBFS_USER /mnt/dbfs fuse rw,user,noauto 0 0
Issue the following command./u01/app/oracle/product/11.2.0/db_1/lib /usr/lib
The drive should now be mounted using the following command from the "oracle" user.# ldconfig
Note. At present this doesn't work for me. The command hangs, like it needs "nohup /mnt/dbfs &", but any access to the file system results in an "input/output error" message.$ mount /mnt/dbfs
$ ls -al /mnt/dbfs ls: /mnt/dbfs: Input/output error $
dbfs_client Command Interface
As only Linux clients will be able to mount the file system, the majority of clients will access the file system via the dbfs_client command line, which provides a variety of UNIX-like file system command using the following syntax.Commands include some typical UNIX file system commands like ls, cp, rm, mkdir. Arguments are typically file or directory names. The available switches are -a (all files), -l (long format) and -R (recursive).dbfs_client <db_user>@<db_serverr> --command <command> [switches] [arguments]
Paths within the DBFS are referenced using the "dbfs:/file-system-name/" prefix. If this is not present, the path is assumed to be on the local filesystem of the machine running the client software.
Here are some examples of commands using the dbfs_client with the file system and wallet created earlier.
The command list is quite limited at the moment, but the message returned from unsupported commands suggests more are on their way.$ # Directory listing. $ dbfs_client /@DB11G_DBFS_USER --command ls -a -l dbfs:/staging_area/ drwxr-xr-x root root 0 Jan 06 19:32 .sfs $ $ # Make a directory and get directory listing. $ dbfs_client /@DB11G_DBFS_USER --command mkdir dbfs:/staging_area/test_dir $ $ dbfs_client /@DB11G_DBFS_USER --command ls -a -l dbfs:/staging_area/ drwx------ oracle oinstall 0 Jan 07 11:41 dbfs:/staging_area/test_dir drwxr-xr-x root root 0 Jan 06 19:32 .sfs $ $ # Copy files to and from DBFS $ dbfs_client /@DB11G_DBFS_USER --command cp /tmp/test.txt dbfs:/staging_area/test_dir/ /tmp/test.txt -> dbfs:/staging_area/test_dir/test.txt $ $ dbfs_client /@DB11G_DBFS_USER --command cp dbfs:/staging_area/test_dir/test.txt /tmp/test_copy.txt dbfs:/staging_area/test_dir/test.txt -> /tmp/test_copy.txt $ $ # Remove file $ dbfs_client /@DB11G_DBFS_USER --command rm dbfs:/staging_area/test_dir/test.txt Unlinking file dbfs:/staging_area/test_dir/test.txt $
Switches must applied separately (-a -l), not grouped (-al) or the results are unpredictable. Also, wildcards do not work.$ dbfs_client /@DB11G_DBFS_USER --command rmdir dbfs:/staging_area/test_dir rmdir is not supported right now $
For more information see:
- Oracle Database File System (DBFS) PL/SQL APIs
- Introducing the Oracle Database File System
- DBFS File System Client
Back to the Top.
