© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2022
D. Kuhn, T. KyteExpert Oracle Database Architecturehttps://doi.org/10.1007/978-1-4842-7499-6_3

3. Files

Darl Kuhn1   and Thomas Kyte2
(1)
Morrison, CO, USA
(2)
Denver, CO, USA
 
In this chapter, we will examine the eight major file types that make up a database and an instance. The files associated with an instance are simply
  • Parameter files: These files tell the Oracle instance where to find the control files, and they also specify certain initialization parameters that define how big certain memory structures are, and so on. We will investigate the two options available for storing database parameter files.

  • Trace files: These are diagnostic files created by a server process, generally in response to some exceptional error condition.

  • Alert files: These are similar to trace files, but they contain information about “expected” events, and they also alert the DBA in a single, centralized file of many database events.

The files that make up the database are
  • Datafiles: These are for the database; they hold your tables, indexes, and all other data segment types.

  • Temp files: These are used for disk-based sorts and temporary storage.

  • Control files: These tell you where the datafiles, temp files, and redo log files are, as well as other relevant metadata about their state. They also contain backup information maintained by RMAN (Recovery Manager, the backup and recovery tool).

  • Redo log files: These are your transaction logs.

  • Password files: These are used to authenticate users performing administrative activities over the network. We will not discuss these files in any great detail. These files are required if you want to connect remotely (over the network) as the SYS user to an instance. These files are required in a Data Guard configuration (primary and standby database).

There are a couple of optional file types that are used by Oracle to facilitate faster backup and faster recovery operations. These two files are
  • Change tracking file: This file facilitates a true incremental backup of Oracle data. It does not have to be located in the Fast Recovery Area, but as it relates purely to database backup and recovery, we’ll discuss it in the context of that area.

  • Flashback log files: These files store “before images” of database blocks in order to facilitate the FLASHBACK DATABASE command.

We’ll also take a look at other types of files commonly associated with the database, such as
  • Data Pump files: These files are generated by the Oracle Data Pump Export process and consumed by the Data Pump Import process. This file format may also be created and consumed by external tables.

  • Flat files: These are plain old files you can view in a text editor. You normally use these for loading data into the database.

The most important files in these lists are the datafiles and the redo log files, because they contain the data you worked so hard to accumulate. I can lose any and all of the remaining files and still get to my data. If I lose my redo log files, I may start to lose some data. If I lose my datafiles and all of their backups, I’ve definitely lost that data forever.

We will now take a look at the types of files, where they are usually located, how they are named, and what we might expect to find in them.

Parameter Files

There are many different parameter files associated with an Oracle database, from a tnsnames.ora file on a client workstation (used to “find” a server on the network), to a listener.ora file on the server (for the network listener startup), to the sqlnet.ora, cman.ora, and ldap.ora files, to name a few. The most important parameter file, however, is the database’s parameter file—without this, we can’t even get an instance started. The remaining files are important; they are all related to networking and getting connected to the database. However, they are beyond the scope of our discussion. For information on their configuration and setup, I refer you to the Database Net Services Administrator’s Guide. These files are typically set up by the DBA (and not the developer).

The parameter file for a database is commonly known as an init file, or an init.ora file . This is due to its historic default name, which is init<ORACLE_SID>.ora. I call it “historic” because Oracle has since implemented a vastly improved method of storing parameter settings for the database: the server parameter file, or simply SPFILE. This file has the default name of spfile<ORACLE_SID>.ora. We’ll take a look at both kinds of parameter files.

Note

For those who are unfamiliar with the term SID or ORACLE_SID, a full definition is called for. The SID is a site identifier. It and ORACLE_HOME (where the Oracle software is installed) are hashed together in UNIX/Linux to create a unique key name for creating or attaching a Shared Global Area (SGA) memory region. If your ORACLE_SID or ORACLE_HOME is not set correctly and you are using a local (not network based) connection, you’ll get the ORACLE NOT AVAILABLE error, since you can’t attach to a shared memory segment that is identified by this unique key. On Windows, shared memory isn’t used in the same fashion as on UNIX/Linux, but the SID is still important. You can have more than one database under the same ORACLE_HOME, so you need a way to uniquely identify the instance associated with each one, along with their configuration files.

Without a parameter file, you can’t start an Oracle database. This makes the parameter file fairly important, and Oracle’s backup and recovery tool Recovery Manager (RMAN) recognizes this file’s importance and will allow you to include the server parameter file (but not the legacy init.ora parameter file type) in your backup set. However, since the init.ora file is simply a plain text file that you can create with any text editor, it is not a file you have to necessarily guard with your life. You can re-create it, as long as you know what was in it (e.g., you can retrieve that information from the database’s alert log, if you have access to that, and reconstruct your entire init.ora parameter file).

We will now examine both types of database startup parameter files (init.ora and SPFILE) in turn, but before we do that, let’s see what a database parameter file looks like.

What Are Parameters?

In simple terms, a database parameter may be thought of as a key/value pair. To see the current value of an instance parameter, you can query the V$ view V$PARAMETER. Alternatively, in SQL*Plus you can use the SHOW PARAMETER command , for example:
$ sqlplus / as sysdba
SQL> select value from v$parameter where name = 'db_block_size';
VALUE
-------
8192
SQL> show parameter db_block_s
NAME                                 TYPE        VALUE
------------------------------------ ----------- -------
db_block_size                        integer     8192

Both outputs show basically the same information, although you can get more information from V$PARAMETER (there are many more columns to choose from than displayed in this example). But SHOW PARAMETER wins for me in ease of use and the fact that it “wildcards” automatically. Notice that I typed in only db_block_s; SHOW PARAMETER adds % to the front and back.

Note

All V$ views and all dictionary views are fully documented in the Oracle Database Reference manual. Please regard that manual as the definitive source of what is available in a given view.

If you were to execute the preceding example as a less-privileged user (EODA has been granted the DBA role for the purposes of this book), you would see instead
SQL> connect scott/tiger@PDB1
Connected.
SQL> select value from v$parameter where name = 'db_block_size';
  select value from v$parameter where name = 'db_block_size'
                  *
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> show parameter db_block_s
ORA-00942: table or view does not exist
“Normal” accounts are not granted access to the V$ performance views by default. You’ll have to grant select on V$PARAMETER to SCOTT. As a DBA account, do the following:
$ sqlplus / as sysdba
SQL> alter session set container=PDB1;
SQL> grant select on sys.v_$parameter to scott;
If you connect back to the SCOTT schema , you should be able to view the parameters now. It’s worth mentioning that there is a third way to view the database parameters via the DBMS_UTILITY package (you’ll still need select access on the internal view to retrieve parameter values this way). Here’s an example:
SQL> conn scott/tiger@PDB1
SQL> create or replace
  function get_param( p_name in varchar2 )
  return varchar2
  as
      l_param_type  number;
      l_intval      binary_integer;
      l_strval      varchar2(256);
      invalid_parameter exception;
      pragma exception_init( invalid_parameter, -20000 );
  begin
      begin
          l_param_type :=
          dbms_utility.get_parameter_value
          ( parnam => p_name,
              intval => l_intval,
            strval => l_strval );
      exception
          when invalid_parameter
          then
              return '*access denied*';
      end;
      if ( l_param_type = 0 )
      then
          l_strval := to_char(l_intval);
      end if;
      return l_strval;
  end get_param;
/
Function created.
If you execute this function in SQL*Plus, you’ll see
SQL> set serverout on
SQL> exec dbms_output.put_line( get_param( 'db_block_size' ) );
8192
PL/SQL procedure successfully completed.
Not every parameter is available via the dbms_utility.get_parameter_value API call. Specifically, the memory-related parameters such as sga_max_size, db_cache_size, pga_aggregate_target, and the like are not visible. We deal with that in the code on lines 17 through 21—we return '*access denied*' when we hit a parameter that we are not allowed to see. If you are curious about the entire list of restricted parameters, you can (as can any account that has been granted EXECUTE on this function) issue the following query:
$ sqlplus scott/tiger@PDB1
SQL> select name, scott.get_param( name ) val
      from v$parameter
     where scott.get_param( name ) = '*access denied*';
NAME                           VAL
------------------------------ --------------------
sga_max_size                   *access denied*
shared_pool_size               *access denied*
large_pool_size                *access denied*
java_pool_size                 *access denied*
streams_pool_size              *access denied*
...
client_result_cache_lag        *access denied*
olap_page_pool_size            *access denied*
33 rows selected.
Note

You’ll see different results for this query on different versions. You should expect the number and values of inaccessible parameters to go up and down over time as the number of parameters changes.

The number of parameters (and their names) varies by release. Most parameters, like db_block_size, are very long-lived (they won’t go away from release to release), but over time many other parameters become obsolete as implementations change. For example, there was a distributed_transactions parameter that could be set to some positive integer and that controlled the number of concurrent distributed transactions the database could perform. It was available in prior releases, but it is not found in any recent release of Oracle. In fact, attempting to use that parameter with subsequent releases raises an error. For example:
$ sqlplus / as sysdba
SQL> alter system set distributed_transactions = 10;
alter system set distributed_transactions = 10
*
ERROR at line 1:
ORA-25138: DISTRIBUTED_TRANSACTIONS initialization parameter has been made
obsolete

If you would like to review the parameters and get a feeling for what is available and what each parameter does, refer to the Oracle Database Reference manual. The first chapter of this manual examines every documented parameter in detail. On the whole, the default value assigned to each parameter (or the derived value for parameters that obtain their default settings from other parameters) is sufficient for most systems. In general, the values of parameters, such as the control_files parameter (which specifies the location of the control files on your system), db_block_size, various memory-related parameters, and so on, need to be set uniquely for each database.

Notice I used the term “documented” in the preceding paragraph. There are undocumented parameters as well. You can identify these because their names begin with an underscore (_). There is a great deal of speculation about these parameters. Since they are undocumented, some people believe they must be “magical,” and many people assume that they are well known and used by Oracle insiders. In fact, I find the opposite to be true. They are not well known and they are hardly ever used. Most of these undocumented parameters are rather boring, actually, as they represent deprecated functionality and backward compatibility flags. Others help in the recovery of data, not of the database itself; for example, some of them enable the database to start up in certain extreme circumstances, but only long enough to get data out. You have to rebuild after that.

Unless you are so directed by Oracle Support, there is no reason to have an undocumented parameter in your configuration. Many have side effects that could be devastating. In my production database, I don’t want to use any undocumented settings.

Caution

Use undocumented parameters only at the request of Oracle Support. Their use can be damaging to a database, and their implementation can—and will—change from release to release.

You may set the various parameter values in one of two ways: either just for the current instance or persistently. It is up to you to make sure that the parameter files contain the values you want them to. When using legacy init.ora parameter files, this is a manual process. To change a parameter value persistently, to have that new setting be in place across server restarts, you must manually edit and modify the init.ora parameter file. With server parameter files, you’ll see that this has been more or less fully automated for you in a single command.

Legacy init.ora Parameter Files

The legacy init.ora file is a very simple file in terms of its construction. It is a series of variable key/value pairs. A sample init.ora file might look like this:
control_files='/opt/oracle/oradata/CDB/control01.ctl'
db_block_size=8192
db_name='CDB'

In fact, this is pretty close to the most basic init.ora file you could get away with in real life, though if the block size I was using was the default on my platform (the default block size varies by platform), I could remove that parameter. The parameter file is used at the very least to get the name of the database and the location of the control files. The control files tell Oracle the location of every other file, so they are very important to the “bootstrap” process that starts the instance.

Now that you know what these legacy database parameter files are and where to get more details about the valid parameters you can set, you also need to know where to find them on disk. The naming convention for this file by default is
init$ORACLE_SID.ora    (UNIX/Linux environment variable)
init%ORACLE_SID%.ora   (Windows environment variable)
and by default it will be found in
$ORACLE_HOME/dbs       (UNIX/Linux)
%ORACLE_HOME%DATABASE (Windows)
It is interesting to note that, in many cases, you’ll find the entire contents of this parameter file to be something like
IFILE= /some/path/to/somewhere/init.ora'

The IFILE directive works in a similar fashion to an #include file in C. It includes in the current file the contents of the named file. Here, this directive includes an init.ora file from a nondefault location.

It should be noted that the parameter file does not have to be in any particular location. When starting an instance, you can use the pfile=filename option to the startup command. This is most useful when you’d like to try out different init.ora parameters on your database to see the effects of different settings.

Legacy parameter files can be maintained by using any text editor. For example, on UNIX/Linux, I’d use vi; on the many Windows operating system versions, I’d use Notepad; and on a mainframe, I would perhaps use Xedit. It is important to note that you are fully responsible for editing and maintaining this file. There are no commands within the Oracle database itself that you can use to maintain the values in the init.ora file. For example, when you use the init.ora parameter file, issuing an ALTER SYSTEM command to change the size of an SGA component would not be reflected as a permanent change in that file. If you want that change to be made permanent—in other words, if you’d like it to be the default for subsequent restarts of the database—it’s up to you to make sure all init.ora parameter files that might be used to start this database are manually updated.

The last interesting point of note is that the legacy parameter file is not necessarily located on the database server. One of the reasons the server parameter file (that we’ll discuss shortly) was introduced was to remedy this situation. The legacy parameter file must be present on the client machine attempting to start the database, meaning that if you run a UNIX/Linux server but administer it using SQL*Plus installed on your Windows desktop machine over the network, then you need the parameter file for the database on your desktop.

I still remember how I made the painful discovery that the parameter files are not stored on the server. This goes back many years to when a brand-new (now retired) tool called SQL*DBA was introduced. This tool allowed us to perform remote operations, specifically, remote administrative operations. From my server (running SunOS at the time), I was able to connect remotely to a mainframe database server. I was also able to issue the shutdown command. However, it was at that point I realized I was in a bit of a jam—when I tried to start up the instance, SQL*DBA would complain about not being able to find the parameter file. I learned that these parameter files—the init.ora plain text files—were located on the machine with the client; they had to exist on the client machine—not on the server. SQL*DBA was looking for a parameter file on my local system to start the mainframe database. Not only did I not have any such file, I had no idea what to put into one to get the system started up again! I didn’t know the db_name or control file locations (even just getting the correct naming convention for the mainframe files would have been a bit of a stretch), and I didn’t have access to log in to the mainframe system itself. I’ve not made that same mistake since; it was a painful lesson to learn.

When DBAs realized that the init.ora parameter file had to reside on the client’s machine that starts the database, it led to a proliferation of these files. Every DBA wanted to run the administrative tools from their desktop, so every DBA needed a copy of the parameter file on their desktop machine. Tools such as Oracle Enterprise Manager (OEM) would add yet another parameter file to the mix. These tools would attempt to centralize the administration of all databases in an enterprise on a single machine, sometimes referred to as a management server. This single machine would run software that would be used by all DBAs to start up, shut down, back up, and otherwise administer a database. That sounds like a perfect solution: centralize all parameter files in one location and use the GUI tools to perform all operations. But the reality is that sometimes it’s much more convenient to issue the administrative startup command from within SQL*Plus on the database server machine itself during the course of some administrative task, so we ended up with multiple parameter files again: one on the management server and one on the database server. These parameter files would then get out of sync with each other, and people would wonder why the parameter change they made last month might “disappear,” then reappear in seemingly randomly manner.

Enter the server parameter file (SPFILE), which can now be a single source of truth for the database.

Server Parameter Files (SPFILEs)

SPFILEs represent a fundamental change in the way Oracle accesses and maintains parameter settings for the instance. An SPFILE eliminates the two serious issues associated with legacy parameter files:
  • It stops the proliferation of parameter files: An SPFILE is always stored on the database server; the SPFILE must exist on the server machine itself and can’t be located on the client machine. This makes it practical to have a single source of “truth” with regard to parameter settings.

  • It removes the need (in fact, it removes the ability) to manually maintain parameter files outside of the database using a text editor: The ALTER SYSTEM command lets you write values directly into the SPFILE. Administrators no longer have to find and maintain all of the parameter files by hand.

The naming convention for this file by default is
$ORACLE_HOME/dbs/spfile$ORACLE_SID.ora    (UNIX/Linux environment variable)
%ORACLE_HOME/database/spfile%ORACLE_SID%.ora   (Windows environment variable)

I strongly recommend using the default location; doing otherwise defeats the simplicity SPFILEs represent. When an SPFILE is in its default location, everything is more or less done for you. Moving the SPFILE to a nondefault location means you have to tell Oracle where to find the SPFILE, leading to the original problems of legacy parameter files all over again!

Note

In Oracle RAC environments, the spfile is usually located on shared ASM disks in a directory like +DATA/<dbname>/PARAMETERFILE. You view the location via the SRVCTL utility.

Converting to SPFILEs

Suppose you have a database that is using a legacy parameter file. The move to an SPFILE is quite simple—you use the CREATE SPFILE command.

Note

You can also use a “reverse” command to create a parameter file (PFILE) from an SPFILE. I’ll explain shortly why you might want to do that.

So, assuming you have an init.ora parameter file and that init.ora parameter file is in the default location on the server, you simply issue the CREATE SPFILE command and restart your server instance. You need to be connected to the root container as a privileged account to perform this task:
$ sqlplus / as sysdba
SQL> show parameter spfile;
NAME                                 TYPE        VALUE
------------------------------------ ----------- -------
spfile                               string
SQL> create spfile from pfile;
File created.
SQL> startup force;
ORACLE instance started.
Database mounted.
Database opened.
SQL> show parameter spfile;
NAME                                 TYPE        VALUE
------------------------------------ ----------- --------------------------
spfile                               string      /opt/oracle/product/21c/dbhome_1/dbs/spfileCDB.ora

To recap, we used the SHOW PARAMETER command here to show that initially we were not using an SPFILE, but after we created one and restarted the instance, we were using one and it had the default name.

Note

In a clustered environment, using Oracle RAC, all instances share the same SPFILE, so this process of converting over to an SPFILE from a PFILE should be done in a controlled fashion. The single SPFILE can contain all of the parameter settings, even instance-specific settings, but you’ll have to merge all of the necessary parameter files into a single PFILE using the format that follows.

In a RAC environment, in order to convert from individual PFILEs to an SPFILE shared by all, you’d merge your individual PFILEs into a single file resembling this:
*.cluster_database=true
*.control_files='+DATA/CDB/CONTROLFILE/current.261.1064287219','+RECO/CDB/CONTROLFILE/current.256.1064287219'
*.db_block_size=8192
*.db_create_file_dest='+DATA'
*.db_name='cdb'
*.db_recovery_file_dest='+RECO'
*.db_recovery_file_dest_size=12207m
*.diagnostic_dest='/u01/app/oracle'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=cdbXDB)'
*.enable_pluggable_database=true
cdb1.instance_number=1
cdb2.instance_number=2
*.local_listener='-oraagent-dummy-'
*.nls_language='AMERICAN'
*.nls_territory='AMERICA'
*.pga_aggregate_target=256m
*.remote_login_passwordfile='exclusive'
*.sga_target=2000m
cdb2.thread=2
cdb1.thread=1
cdb1.undo_tablespace='UNDOTBS1'
cdb2.undo_tablespace='UNDOTBS2'
That is, parameter settings that are common to all instances in the cluster would start with the “*.” string. Parameter settings that are specific to a single instance, such as the INSTANCE_NUMBER and the THREAD of redo to be used, are prefixed with the instance name (the Oracle SID). In the preceding example
  • The PFILE would be for a two-node cluster with instances named CDB1 and CDB2.

  • The *.db_name = 'CDB' assignment indicates that all instances using this SPFILE will be mounting a database named CDB.

  • cdb1.undo_tablespace='UNDOTBS1' indicates that the instance named CDB1 will use that specific undo tablespace, and so on.

Setting Values in SPFILEs

Once our database is up and running on the SPFILE, the next question relates to how we set and change values contained therein. Remember, SPFILEs are binary files and we can’t just edit them using a text editor. The answer is to use the ALTER SYSTEM command, which has the following syntax (portions in <> are optional, and the presence of the pipe symbol indicates “one of the list”):
Alter system set parameter=value <comment='text'> <deferred>
                 <scope=memory|spfile|both> <sid='sid|*'>
                 <container=current|all>

The ALTER SYSTEM SET command , by default, will update the currently running instance and make the change to the SPFILE for you—or in the case of a pluggable database, in the data dictionary of that pluggable database (see the following section on pluggable databases for more information). This greatly eases administration, and it eliminates the problems that arose when you used ALTER SYSTEM to add or modify parameter settings, but you forgot to update or missed an init.ora parameter file.

Let’s take a look at each element of the command:
  • The parameter=value assignment supplies the parameter name and the new value for the parameter. For example, pga_aggregate_target = 1024m would set the pga_aggregate_target parameter to a value of 1024MB (1GB).

  • comment='text' is an optional comment you can associate with this setting of the parameter. The comment will appear in the UPDATE_COMMENT field of the V$PARAMETER view. If you use the option to save the change to the SPFILE, the comment will be written into the SPFILE and preserved across server restarts as well, so future restarts of the database will see the comment.

  • deferred specifies whether the system change takes place for subsequent sessions only (not currently established sessions, including the one making the change). By default, the ALTER SYSTEM command will take effect immediately, but some parameters can’t be changed immediately—they can be changed only for newly established sessions. We can use the following query to see what parameters mandate the use of deferred:

SQL> select name  from v$parameter where issys_modifiable='DEFERRED';
NAME
----------------------------------------
backup_tape_io_slaves
recyclebin
session_cached_cursors
private_temp_table_prefix
audit_file_dest
object_cache_optimal_size
object_cache_max_size_percent
sort_area_size
sort_area_retained_size
client_statistics_level
olap_page_pool_size
Note

Your results may differ; from version to version, the list of which parameters may be set online—but must be deferred—can and will change.

The code shows that SORT_AREA_SIZE is modifiable at the system level, but only in a deferred manner. The following code shows what happens if we try to modify its value with and without the deferred option:
SQL> alter system set sort_area_size = 65536;
alter system set sort_area_size = 65536
                                      *
ERROR at line 1:
ORA-02096: specified initialization parameter is not modifiable with this option
SQL> alter system set sort_area_size = 65536 deferred;
System altered.
  • SCOPE=MEMORY|SPFILE|BOTH indicates the “scope” of this parameter setting. Here are our choices for setting the parameter value:
    • SCOPE=MEMORY changes the setting in the instance(s) only; it will not survive a database restart. The next time you start the database, the setting will be whatever was already recorded in the SPFILE.

    • SCOPE=SPFILE changes the value in the SPFILE only. The change will not take place until the database is restarted and the SPFILE is processed again. Some parameters can be changed only by using this option. For example, the processes parameter must use SCOPE=SPFILE, as you can’t change the active instance value.

    • SCOPE=BOTH means the parameter change takes place both in memory and in the SPFILE. The change will be reflected in the current instance, and, the next time you start, this change will still be in effect. This is the default value for scope when using an SPFILE. With an init.ora parameter file, the default and only valid value is SCOPE=MEMORY. This is the default if the instance was started with an SPFILE.

  • sid='sid|*' is useful mostly in a clustered environment; sid='*' is the default. This lets you specify a parameter setting uniquely for any given instance in the cluster. Unless you are using Oracle RAC, you will not need to specify the sid= setting.

  • container=current|all is used in a multitenant database to determine the scope of the change. If the ALTER SYSTEM is executed in a root container database, the setting may be propagated down to every pluggable database by using the all option. Otherwise, by default, only the current container or pluggable database is affected by the change. Note that pluggable database–specific settings are not recorded in the SPFILE but are stored in the data dictionary of the pluggable database, so that when it is moved to another container, its specific settings will move with it.

A typical use of this command might be simply
SQL> alter system set pga_aggregate_target=512m;
System altered.
Note

The preceding command—and in fact many of the ALTER SYSTEM commands in this book—may fail on your system. If you use other settings that are incompatible with my example (other memory parameters, for example), you may well receive an error. That doesn’t mean the command doesn’t work, but, rather, the settings you attempted to use are not compatible with your overall setup.

Better yet, perhaps, would be using the COMMENT= assignment to document when and/or why a particular change was made:
SQL> alter system set pga_aggregate_target=512m  comment = 'AWR recommendation';
System altered.
SQL> select value, update_comment  from v$parameter  where name = 'pga_aggregate_target';
VALUE                UPDATE_COMMENT
-------------------- ----------------------------------------
536870912            AWR recommendation

Unsetting Values in SPFILEs

The next question that arises is, how do we unset a value that we previously set? In other words, we don’t want that parameter setting in our SPFILE anymore. Since we can’t edit the file using a text editor, how do we accomplish that? This, too, is done via the ALTER SYSTEM command, but using the RESET clause:
Alter system reset parameter <scope=memory|spfile|both> sid='sid|*'
So, for example, if we wanted to remove the sort_area_size parameter, to allow it to assume the default value we specified previously, we could do so as follows:
SQL> alter system reset sort_area_size scope=spfile ;
System altered.
The sort_area_size is removed from the SPFILE, which you can verify by issuing the following:
SQL> create pfile='/tmp/pfile.tst' from spfile;
File created.

You can then review the contents of /tmp/pfile.tst, which will be generated on the database server. You’ll find the sort_area_size parameter does not exist in the parameter file anymore.

Creating PFILEs from SPFILEs

The CREATE PFILE...FROM SPFILE command we just saw is the opposite of CREATE SPFILE. It takes the binary SPFILE and creates a plain text file from it—one that can be edited in any text editor and subsequently used to start up the database. You might use this command for at least two things on a regular basis:
  • To create a one-time parameter file with some special settings, to start up the database for maintenance. So, you’d issue CREATE PFILE...FROM SPFILE and edit the resulting text PFILE, modifying the required settings. You’d then start the database, using the PFILE=<FILENAME> option to specify your PFILE instead of the SPFILE. After you finished, you’d just start up normally without specifying the PFILE=<FILENAME>, and the database would use the SPFILE.

  • To maintain a history of commented changes. In the past, many DBAs heavily commented their parameter files with a change history. If they changed the size of the SGA 20 times, for example, they would have 20 comments in front of the sga_target init.ora parameter setting, stating the date and reason for making the change. The SPFILE does not support this, but you can achieve the same effect if you get into the habit of doing the following:
    SQL> connect / as sysdba
    Connected.
    SQL> create pfile='init_10_feb_2021_CDB.ora' from spfile;
    File created.
    SQL> alter system set pga_aggregate_target=512m comment = 'Changed 10-feb-2021, AWR recommendation';
    System altered.

In this way, your history will be saved in the series of parameter files over time.

Fixing Corrupted SPFILEs

The last question that comes up with regard to SPFILEs is, “SPFILEs are binary files, so what happens if one gets corrupted and the database won’t start? At least the init.ora file was just text, so we could edit it and fix it.” Well, SPFILEs shouldn’t go corrupt any more than should a datafile, redo log file, control file, and so forth. However, in the event one does—or if you have set a value in your SPFILE that does not allow the database to start—you have a couple of options.

First, the amount of binary data in the SPFILE is very small. If you are on a UNIX/Linux platform, a simple strings command will extract all of your settings:
$ strings $ORACLE_HOME/dbs/spfile$ORACLE_SID.ora
*.audit_sys_operations=false
*.audit_trail='none'
*.commit_logging='batch'
*.commit_wait='nowait'...

On Windows, simply open the file with write.exe (WordPad). WordPad will display all of the clear text in the file, and by simply cutting and pasting into init<ORACLE_SID>.ora, you can create a PFILE to use to start your instance.

In the event that the SPFILE has just “gone missing” (for whatever reason—not that I’ve seen an SPFILE disappear), you can also resurrect the information for your parameter file from the database’s alert log (more on the alert log shortly). Every time you start the database, the alert log will contain a section like this:
System parameters with non-default values:
  processes                = 300
  nls_language             = "AMERICAN"
  nls_territory            = "AMERICA"
  filesystemio_options     = "setall"
  sga_target               = 2152M
  control_files            = "/opt/oracle/oradata/CDB/control01.ctl”
  db_block_size            = 8192
...
<lots more rows here removed for brevity>

From this section, you can easily create a PFILE to be converted into a new SPFILE using the CREATE SPFILE command.

Pluggable Databases

Pluggable databases are designed to be a set of files you can move from one root container database to another. That is, we can unplug a pluggable database, and upon plugging it back into either the same root container database or some other root container database, we would have our original pluggable database back—with all of the application schemas, users, metadata, grants, data, and even our pluggable database parameter settings (settings that were not inherited from the root container). This is achieved by storing pluggable database–specific parameter settings in a data dictionary table: SYS.PDB_SPFILE$. You can view parameters modifiable at the PDB level via this query:
SQL> SELECT name, value
FROM   v$system_parameter
WHERE  ispdb_modifiable = 'TRUE'
ORDER BY name;
NAME                           VALUE
------------------------------ ------------------------------
adg_account_info_tracking
allow_deprecated_rpcs
allow_rowid_column_type
approx_for_aggregation
approx_for_count_distinct
approx_for_percentile
aq_tm_processes
asm_diskstring
auto_start_pdb_services
awr_pdb_autoflush_enabled
bitmap_merge_area_size
blank_trimming
blockchain_table_max_no_drop
...
<lots more rows here removed for brevity>
You set the PDB level parameters by using the ALTER SYSTEM ... CONTAINER clause or by connecting the pluggable database and issuing the ALTER SYSTEM command:
$ sqlplus / as sysdba
SQL> alter session set container=pdb1;
SQL> alter system set statistics_level=all;

It is in this fashion that pluggable databases can override a parameter setting for some parameters in an SPFILE and have those parameter settings travel with them as they move from root container database to root container database.

Parameter File Wrap-Up

In this section, we covered the basics of managing Oracle initialization parameters and parameter files. We looked at how to set parameters, view parameter values, and have those settings persist across database restarts. We explored the two types of database parameter files: legacy PFILEs (simple text files) and the newer SPFILEs. For all existing databases, using SPFILEs is recommended for the ease of administration and clarity they bring. The ability to have a single source of parameter “truth” for the database, along with the ability of the ALTER SYSTEM command to persist the parameter values, makes SPFILEs a compelling feature. I started using them the instant they became available and haven’t looked back.

Trace Files

Trace files are a source of debugging information. When the server encounters a problem, it generates a trace file full of diagnostic information. When a developer executes DBMS_MONITOR.SESSION_TRACE_ENABLE, the server generates a trace file full of performance-related information. Trace files are available to us because Oracle is a heavily instrumented piece of software. By “instrumented,” I mean that the programmers who wrote the database kernel put in debugging code—lots and lots of it. And they left it in, on purpose.

I’ve met many developers who consider debugging code to be overhead—something that must be ripped out before an application goes into production in a vain attempt to squeeze every ounce of performance out of the code. Later, of course, they discover that their code has a bug or it isn’t running as fast as it should (which end users tend to call a bug as well; to an end user, poor performance is a bug). At that point, they really wish that the debug code was still in the code (or had been in there if it never was), especially since you can’t drop debug code into the production system. You have to test any new code before putting it into a production environment, and that’s not something you do at the drop of a hat.

The Oracle database (and Application Server and Oracle applications and various tools such as Application Express (APEX)) is heavily instrumented. Signs of this instrumentation in the database are
  • V$ views: Most V$ views contain “debug” information. V$WAITSTAT, V$SESSION_EVENT, and many others exist solely to let us know what is going on deep in the kernel.

  • The AUDIT command: This command allows you to specify what events the database should record for later analysis.

  • Resource Manager (DBMS_RESOURCE_MANAGER): This feature lets you micromanage resources (CPU, I/O, and the like) within the database. What makes a Resource Manager in the database possible is that it has access to all of the runtime statistics describing how the resources are being used.

  • Oracle events: These enable you to ask Oracle to produce trace or diagnostic information as needed.

  • DBMS_TRACE: This facility within the PL/SQL engine exhaustively records the call tree of stored procedures, exceptions raised, and errors encountered.

  • Database event triggers: These triggers, such as ON SERVERERROR, allow you to monitor and log any condition you feel is “exceptional” or out of the ordinary. For example, you can log the SQL that was running when an “out of temp space” error was raised.

  • DBMS_MONITOR: This is used to view the exact SQL, wait events, and other performance/behavior-related diagnostic information generated by running your application. The SQL Trace facility is also available in an extended fashion via the 10046 Oracle event.

Instrumentation is vital in application design and development, and the Oracle database becomes better instrumented with each release. Oracle 10g took code instrumentation in the kernel to a whole new level with the introduction of the Automatic Workload Repository (AWR) and Active Session History (ASH) features. Oracle 11g took that further with options such as the Automatic Diagnostic Repository (ADR) and the SQL Performance Analyzer (SPA). Oracle 12c advanced even further with the addition of a DDL log to track all DDL operations in a database (something that shouldn’t be happening in many typical production databases day to day) and the debug log to track exceptional conditions in the database.

In this section, we’re going to focus on the information you can find in various types of trace files. We’ll cover what they are, where they are stored, and what we can do with them.

There are two general types of trace files, and what we do with each kind is very different:
  • Trace files you expected and want: These are, for example, the result of enabling DBMS_MONITOR.SESSION_TRACE_ENABLE. They contain diagnostic information about your session and will help you tune your application to optimize its performance and diagnose any bottlenecks it is experiencing.

  • Trace files you were not expecting but the server generated as the result of an ORA-00600 “Internal Error,” ORA-03113 “End of file on communication channel,” or ORA-07445 “Exception Encountered” type of error: These traces contain diagnostic information that is most useful to an Oracle Support analyst and, beyond showing where in our application the internal error was raised, are of limited use to us.

Requested Trace Files

The trace files you typically expect to be generated as the result of enabling trace via DBMS_MONITOR or using the extended trace facility via the 10046 event might be as follows:
SQL> alter session set events '10046 trace name context forever, level 12';
Session altered.

These trace files contain diagnostic and performance-related information. They provide invaluable insights into the inner workings of your database application. You will see these trace files more often than any other kind of trace file in a normally operating database.

File Locations

Whether you use DBMS_MONITOR or the extended trace facility, Oracle will start generating a trace file on the database server derived from the setting of the DIAGNOSTIC_DEST initialization parameter. The structure of the directory specified by DIAGNOSTIC_DEST is as follows:
<diagnostic_dest>/diag/rdbms/<dbname>/<instname>
This location is known as the Automatic Diagnostic Repository (ADR) Home. For example, if the database name is CDB and the instance name is CDB, the ADR home directory would be <diagnostic_dest>/diag/rdbms/cdb/CDB. You can view the directory settings with this query:
SQL> select name, value from v$diag_info;
AME                 VALUE
-------------------- ------------------------------------------------------
Diag Enabled         TRUE
ADR Base             /opt/oracle
ADR Home             /opt/oracle/diag/rdbms/cdb/CDB
Diag Trace           /opt/oracle/diag/rdbms/cdb/CDB/trace
Diag Alert           /opt/oracle/diag/rdbms/cdb/CDB/alert
Diag Incident        /opt/oracle/diag/rdbms/cdb/CDB/incident
Diag Cdump           /opt/oracle/diag/rdbms/cdb/CDB/cdump
Health Monitor       /opt/oracle/diag/rdbms/cdb/CDB/hm
Default Trace File   /opt/oracle/diag/rdbms/cdb/CDB/trace/CDB_ora_15884.trc
...
The most important rows are
  • Diag Trace: This is where the text-based alert log goes along with the trace file.

  • Diag Alert: This is where the XML-based alert log file is written.

As a DBA, you’ll spend time working with files in the Diag Trace directory. These files are used so often (debugging and maintenance) that DBAs will often create aliases that will take them to that directory directly and tail the alert log. For example:
$ alias cda='cd /opt/oracle/diag/rdbms/cdb/CDB/trace'
$ alias ta='tail -f /opt/oracle/diag/rdbms/cdb/CDB/trace/alert_CDB.log'

The aliases create shortcuts for working with these critical files.

Naming Convention

The trace file naming convention changes from time to time in Oracle, but if you have an example trace file name from your system, it is easy to see the template in use. For example, on my various UNIX/Linux servers, a trace file name has this general format:
<sid>_ora_<PROCESS_ID>.trc
The trace file name can be broken down as follows:
  • The first part of the file name is the ORACLE_SID.

  • The next bit of the file name is just ora.

  • The number in the trace file name is the process ID of your dedicated server, available to you from the V$PROCESS view.

A query, then, to generate your trace file name could be
SQL> column trace new_val TRACE format a100
SQL> select i.value || '/' || d.instance_name || '_ora_' || a.spid || '.trc' trace
from v$process a, v$session b, v$diag_info i , v$instance d
where a.addr = b.paddr
and b.audsid = userenv('sessionid')
and i.name='Diag Trace';
TRACE
---------------------------------------------------------------------------
/opt/oracle/diag/rdbms/cdb/CDB/trace/CDB_ora_16908.trc
And this just shows that if the file exists, you’ll be able to access it via that name (assuming you have the permissions to read the trace directory). The following example generates a trace file, showing how the file is created once the trace is enabled:
SQL> !ls &TRACE
ls: cannot access /opt/oracle/diag/rdbms/cdb/CDB/trace/CDB_ora_16908.trc: No such file or directory
SQL> exec dbms_monitor.session_trace_enable
PL/SQL procedure successfully completed.
SQL> !ls &TRACE
/opt/oracle/diag/rdbms/cdb/CDB/trace/CDB_ora_16908.trc

As you can see, before we enabled tracing in that session, no file existed; as soon as tracing is enabled, however, we are able to see it.

And if you’re using Windows, it should be obvious that you’d replace the / with .

Tagging Trace Files

There is a way to “tag” your trace file so that you can find it even if you are not permitted access to V$PROCESS and V$SESSION. Assuming you have access to read the trace directory, you can use the session parameter tracefile_identifier. With this, you can add a uniquely identifiable string to the trace file name, for example:
SQL> alter session set tracefile_identifier = 'Look_For_Me';
Session altered.
SQL> !ls /opt/oracle/diag/rdbms/cdb/CDB/trace/*Look_For_Me*
ls: cannot access /opt/oracle/diag/rdbms/cdb/CDB/trace/*Look_For_Me*: No such file or directory
SQL> exec dbms_monitor.session_trace_enable
PL/SQL procedure successfully completed.
SQL> !ls /opt/oracle/diag/rdbms/cdb/CDB/trace/*Look_For_Me*
/opt/oracle/diag/rdbms/cdb/CDB/trace/CDB_ora_15972_Look_For_Me.trc
/opt/oracle/diag/rdbms/cdb/CDB/trace/CDB_ora_15972_Look_For_Me.trm

The * character is a wildcard instructing ls to look for any files with the string of Look_For_Me included in the file name. As you can see, the trace file is now named in the standard <ORACLE_SID>_ora_<PROCESS_ID> format, but it also has the unique string we specified associated with it, making it easy to find “our” trace file name. The trace file ends with the extension of .trc. There’s also a corresponding trace map file (with the extension of .trm) which contains structural information about the trace file. Usually, you’ll only be interested in the contents of the .trc file.

Trace Files Generated in Response to Internal Errors

I’d like to close this section with a discussion about those other kinds of trace files—the ones we did not expect that were generated as a result of an ORA-00600 or some other internal error. Is there anything we can do with them? The short answer is that, in general, they are not for you and me. They are useful to Oracle Support. However, they can be helpful when we file a service request with Oracle Support. That point is crucial: if you are getting internal errors, the only way they will ever be corrected is if you file a service request (SR). If you just ignore them, they will not get fixed by themselves, except by accident.

For example, in Oracle 10g Release 1, if you create the following table and run the query, you may well get an internal error (or not; it was filed as a bug and is corrected in later patch releases):
SQL> create table t ( x int primary key );
Table created.
SQL> insert into t values ( 1 );
1 row created.
SQL> exec dbms_stats.gather_table_stats( user, 'T' );
PL/SQL procedure successfully completed.
SQL> select count(x) over ()   from t;
       *
ERROR at line 2:
ORA-00600: internal error code, arguments: [12410], [], [], [], [], [], [], []

Now, suppose you are the DBA and all of a sudden this trace file pops up in the trace area. Or you are the developer and your application raises an ORA-00600 error, and you want to find out what happened. There is a lot of information in that trace file (some 35,000 lines, in fact), but in general it’s not useful to you and me. We would generally just compress the trace file and upload it as part of our service request processing.

A command-line tool, in conjunction with a user interface via Enterprise Manager, allows you to review the trace information in the ADR and package and transmit it to Oracle Support. The Automatic Diagnostic Repository Command Interpreter (ADRCI) utility allows you to review “problems” (critical errors in the database) and incidents (occurrences of those critical errors) and to package them up for transmission to support. The packaging step includes retrieving not only the trace information but also details from the database alert log and other configuration/test case information. For example, I set up a situation in my database that raised a critical error. (No, I won’t say what it is. You have to generate your own critical errors.) I knew I had a “problem” in my database because the ADRCI tool told me so:
$ adrci
adrci> show problem
ADR Home = /opt/oracle/diag/rdbms/cdb/CDB:
*************************************************************************
PROBLEM_ID           PROBLEM_KEY                                                 LAST_INCIDENT        LASTINC_TIME
-------------------- ----------------------------------------------------------- -------------------- ----------------------------------------
1                    ORA 700 [pga physmem limit]                                 19209                2021-02-15 00:37:58.332000 +00:00
There was recently an ORA-700 error in my database. I can now see what was affected by that error by issuing the show incident command:
adrci> show incident
INCIDENT_ID  PROBLEM_KEY                  CREATE_TIME
------------ ---------------------------  -------------------------
1            ORA 700 [pga physmem limit]   021-01-24 19:33:31.863000 +00:00
2402         ORA 700 [pga physmem limit]   021-01-24 19:34:50.006000 +00:00
4803         ORA 700 [pga physmem limit]   021-01-24 19:35:20.619000 +00:00
7204         ORA 700 [pga physmem limit]   021-01-24 19:42:03.463000 +00:00
9605         ORA 700 [pga physmem limit]   021-01-24 19:49:46.391000 +00:00
I can see there are several incidents, and I can identify the information related to each incident via the show tracefile command:
adrci> show tracefile -I 2402
     diag/rdbms/cdb/CDB/incident/incdir_2402/CDB_ora_5317_i2402.trc
This shows me the location of the trace file for the incident number listed. Further, I can see a lot of detail about the incident if I so choose:
adrci> show incident -mode detail -p "incident_id=2402"
ADR Home = /opt/oracle/diag/rdbms/cdb/CDB:
*************************************************************************
**********************************************************
INCIDENT INFO RECORD 1
**********************************************************
   INCIDENT_ID                   2402
   STATUS                        ready
   CREATE_TIME                   2021-01-24 19:34:50.006000 +00:00
   PROBLEM_ID                    1
   CLOSE_TIME                    <NULL>
   FLOOD_CONTROLLED              none
   ERROR_FACILITY                ORA
   ERROR_NUMBER                  700
   ERROR_ARG1                    pga physmem limit
...
<lot of output here>

And, finally, I can create a “package” of the incident that is useful for support. The package will contain everything a support analyst needs to begin working on the problem.

This section is not intended to be a full overview or introduction to the ADRCI utility, which is documented fully in the Oracle Database Utilities manual. Rather, I just wanted to introduce the existence of the tool—a tool that makes using trace files easy.

The database information is important to have when you go to http://support.oracle.com to file the service request or to search to see if what you are experiencing is a known problem. In addition, you can see the Oracle instance on which the error occurred. It is quite common to have many instances running concurrently, so isolating the problem to a single instance is useful.

Here’s another section of the trace file to be aware of:
*** SESSION ID:(266.55448) 2021-02-15T15:39:09.939349+00:00
*** CLIENT ID:() 2021-02-15T15:39:09.939354+00:00
*** SERVICE NAME:(SYS$USERS) 2021-02-15T15:39:09.939358+00:00
*** MODULE NAME:(sqlplus@localhost (TNS V1-V3)) 2021-02-15T15:39:09.939364+00:00
*** ACTION NAME:() 2021-02-15T15:39:09.939368+00:00
*** CLIENT DRIVER:(SQL*PLUS) 2021-02-15T15:39:09.939372+00:00
*** CONTAINER ID:(1) 2021-02-15T15:39:09.939376+00:00

This part of the trace file shows the session information available in the columns ACTION and MODULE from V$SESSION. Here, we can see that it was a SQL*Plus session that caused the error to be raised (you and your developers can and should set the ACTION and MODULE information; some environments such as Oracle Forms and APEX already do this for you).

Additionally, we have the SERVICE NAME. This is the actual service name used to connect to the database—SYS$USERS, in this case—indicating we didn’t connect via a TNS service. If we logged in using user/pass@CDB, we might see
*** SERVICE NAME:(CDB) 2021-02-15T15:55:42.704845+00:00

Here, CDB is the service name (not the TNS connect string; rather, it’s the ultimate service registered in a TNS listener to which it connected). This is also useful in tracking down which process or module is affected by this error.

Lastly, before we get to the actual error, we can see the session ID (266 in this example), session serial number (55448 in this example), and related date/time information (all releases) as further identifying information:
*** SESSION ID:(266.55448) 2021-02-15T15:39:09.939349+00:00

From here, you can dig further into the trace file and try to determine what is causing the problem. The other important pieces of information are the error code (typically 600, 3113, or 7445) and other arguments associated with the error code. Using these, along with some of the stack trace information that shows the set of Oracle internal subroutines that were called in order, we might be able to find an existing bug (and workarounds, patches, and so on).

Typically, you’ll do a Google search of any relevant error messages. If you don’t readily find an answer, you can create a service request with Oracle Support and attach the trace files to the request. Oracle Support can help you identify if you’ve hit a bug or provide options on workarounds.

Trace File Wrap-Up

You now know the two types of general trace files, where they are located, and how to find them. Hopefully, you’ll use trace files mostly for tuning and increasing the performance of your application, rather than for filing service requests. As a last note, Oracle Support does have access to many undocumented “events” that are very useful for dumping out tons of diagnostic information whenever the database hits any error. For example, if you are getting an ORA-01555 Snapshot Too Old that you absolutely feel you should not be getting, Oracle Support can guide you through the process of setting such diagnostic events to help you track down precisely why that error is getting raised, by creating a trace file every time that error is encountered.

Alert Log File

The alert file (also known as the alert log) is the diary of the database. It is a simple text file written to from the day the database is “born” (created) to the end of time (when you erase it). In this file, you’ll find a chronological history of your database—the log switches; the internal errors that might be raised; when tablespaces were created, taken offline, put back online; and so on. It is an incredibly useful file for viewing the history of a database. I like to let mine grow fairly large before “rolling” (archiving) it. The more information, the better, I believe, for this file. I will not describe everything that goes into an alert log—that’s a fairly broad topic. I encourage you to take a look at yours, however, and see the wealth of information it holds.

To determine the location of the text-based alert log for your database, run the following query:
SQL> select value from v$diag_info, v$instance where name = 'Diag Trace';
VALUE
---------------------------------------------------------------------------
/opt/oracle/diag/rdbms/cdb/CDB/trace
The name of the alert log will be of this format:
alert_<ORACLE_SID>.log
You can generate the location and name of the alert log with the following query:
SQL> select value || '/alert_' || instance_name || '.log' from v$diag_info, v$instance
          where name = 'Diag Trace';
VALUE||'/ALERT_'||INSTANCE_NAME||'.LOG'
--------------------------------------------------------------------------
/opt/oracle/diag/rdbms/cdb/CDB/trace/alert_CDB.log
If you want to view the location of the XML-based alert log, run this query:
SQL> select value from v$diag_info where name = 'Diag Alert';
It’s worth noting that there is an internal table, X$DBGALERTEXT, that you can query from SQL*Plus which derives its information from the alert log. This table requires SYS privileges to view. For example, as SYS, you can query the alert log for ORA- errors as follows:
$ sqlplus / as sysdba
SQL> select record_id,
    to_char(originating_timestamp,'DD.MM.YYYY HH24:MI:SS'),
    message_text
from x$dbgalertext
where message_text like '%ORA-%';
Tip

Oracle Support has a note on how to edit, read, and query the alert log (Doc ID 1072547.1).

In addition to using an external table to query the alert log, you can easily view the alert log using the ADRCI tool. That tool lets you find, edit (review), and monitor (interactively display new records as they appear in the alert log). Also, Enterprise Manager provides access to the alert log.

Generally speaking, when the need arises to view the alert log, most DBAs will navigate directly to the alert log location. Once there, they’ll use operating system utilities such as vi, tail, and grep to extract information.

Tip

With Oracle 19c and above, there’s also an attention.log file that contains information regarding critical events in your database (startup, shutdown, invalid memory parameters, and so on). It is located in the $ORACLE_BASE/diag/rdbms/<database_name>/<instance_name>/log directory.

Datafiles

Datafiles , along with redo log files, are the most important type of files in the database. This is where all of your data will ultimately be stored. Every database has at least one datafile associated with it and typically has many more than one. You can view the datafiles for your database by querying the data dictionary. The names of the datafiles will vary depending on whether you’re using RAC (with datafiles on ASM disk) and/or Oracle Managed Files (OMF). For example, here are the datafiles in a RAC container database, using ASM disks, and the OMF naming convention:
SQL> select name from v$datafile;
NAME
--------------------------------------------------------------
+DATA/CDB/DATAFILE/system.257.1064287113
+DATA/CDB/DATAFILE/sysaux.258.1064287137
+DATA/CDB/DATAFILE/undotbs1.259.1064287153
+DATA/CDB/86B637B62FE07A65E053F706E80A27CA/DATAFILE/system.265.1064287787
+DATA/CDB/86B637B62FE07A65E053F706E80A27CA/DATAFILE/sysaux.266.1064287787
+DATA/CDB/DATAFILE/users.260.1064287153
+DATA/CDB/86B637B62FE07A65E053F706E80A27CA/DATAFILE/undotbs1.267.1064287787
+DATA/CDB/DATAFILE/undotbs2.269.1064288035
+DATA/CDB/BB1C6AAC137C6A4DE0536638A8C06678/DATAFILE/system.274.1064288517
+DATA/CDB/BB1C6AAC137C6A4DE0536638A8C06678/DATAFILE/sysaux.275.1064288517

The prior output shows three SYSTEM datafiles (where the Oracle data dictionary is stored). One is for the root container database, and the other two are associated with pluggable databases. The long random string in the directory path is the GUID (unique identifier) associated with the pluggable databases when using OMF files.

Listed next are the datafiles in a single instance container database (not using OMF):
SQL> select name from v$datafile;
NAME
---------------------------------------------------------------------------
/opt/oracle/oradata/CDB/system01.dbf
/opt/oracle/oradata/CDB/sysaux01.dbf
/opt/oracle/oradata/CDB/undotbs01.dbf
/opt/oracle/oradata/CDB/pdbseed/system01.dbf
/opt/oracle/oradata/CDB/pdbseed/sysaux01.dbf
/opt/oracle/oradata/CDB/users01.dbf
/opt/oracle/oradata/CDB/pdbseed/undotbs01.dbf
/opt/oracle/oradata/CDB/PDB1/system01.dbf
/opt/oracle/oradata/CDB/PDB1/sysaux01.dbf
/opt/oracle/oradata/CDB/PDB1/undotbs01.dbf
/opt/oracle/oradata/CDB/PDB1/users01.dbf
/opt/oracle/oradata/CDB/PDB2/system01.dbf
/opt/oracle/oradata/CDB/PDB2/sysaux01.dbf
/opt/oracle/oradata/CDB/PDB2/undotbs01.dbf
/opt/oracle/oradata/CDB/PDB2/users01.db
The datafiles in this directory /opt/oracle/oradata/CDB belong to the root container. The datafiles in subdirectories belong to pluggable databases. Each database will usually (minimally) have the following datafiles:
  • SYSTEM: Stores the Oracle data dictionary

  • SYSAUX: Contains other non-dictionary objects

  • UNDO: Stores the undo segments used for rollback operations

  • USERS: A default tablespace to be used for application data (if no other tablespace is designated)

After a brief review of file system types, we’ll discuss how Oracle organizes these files and how data is organized within them. To understand this, you need to know what tablespaces, segments, extents, and blocks are. These are the units of allocation that Oracle uses to hold objects in the database, and I describe them in detail shortly.

A Brief Review of File System Mechanisms

There are three file system mechanisms in which to store your data in Oracle. By your data, I mean your data dictionary, redo, undo, tables, indexes, LOBs, and so on—the data you personally care about at the end of the day. Briefly, they are
  • “Cooked” operating system (OS) file systems: These are files that appear in the file system just like your word processing documents do. You can see them in Windows Explorer; you can see them in UNIX/Linux as the result of an ls command. You can use simple OS utilities such as xcopy on Windows or cp on UNIX/Linux to move them around. Cooked OS files are historically the most popular method for storing data in Oracle. In RAC environments, the ASM disk type is used (more on that in a moment). Cooked file systems are typically buffered as well, meaning that the OS will cache information for you as you read and, in some cases, write to disk.

  • Automatic Storage Management (ASM) : ASM is a file system designed exclusively for use by the database. An easy way to think about it is as a database file system. You won’t store your shopping list in a text file on this particular file system—you’ll store only database-related information here: tables, indexes, backups, control files, parameter files, redo logs, archives, and more. But even in ASM, the equivalent of a datafile exists; conceptually, data is still stored in files, but the file system is ASM. ASM is designed to work in either a single machine or clustered environment. Since Oracle 11g Release 2, ASM provides not only this database file system but optionally a clustered file system as well, which is described next.

  • Clustered file system : This is specifically for a RAC (clustered) environment and provides what looks like a cooked file system that is shared by many nodes (computers) in a clustered environment. A traditional cooked file system is usable by only one computer in a clustered environment. So, while it is true that you could NFS mount or Samba share (a method of sharing disks in a Windows/UNIX/Linux environment similar to NFS) a cooked file system among many nodes in a cluster, it represents a single point of failure. If the node owning the file system and performing the sharing failed, that file system would be unavailable. In releases of Oracle prior to 11g Release 2, the Oracle Cluster File System (OCFS) is Oracle’s offering in this area and is currently available for Windows and UNIX/Linux only. Other third-party vendors provide certified clustered file systems that work with Oracle as well. Oracle 11g Release 2 provides another option in the form of the Oracle Automatic Storage Management Cluster File System (ACFS). A clustered file system brings the comfort of a cooked file system to a clustered environment.

The interesting thing is that a database might consist of files from any or all of the preceding file systems—you don’t need to pick just one. You could have a database whereby portions of the data were stored in conventional cooked file systems, some on raw partitions, others in ASM, and yet other components in a clustered file system. This makes it rather easy to move from technology to technology or to just get your feet wet in a new file system type without moving the entire database into it. Now, since a full discussion of file systems and all of their detailed attributes is beyond the scope of this book, we’ll dive back into the Oracle file types. Regardless of whether the file is stored on cooked file systems, in raw partitions, within ASM, or on a clustered file system, the following concepts always apply.

Note

Raw partitions are deprecated in Oracle 11g and are no longer supported at all in Oracle 12c.

The Storage Hierarchy in an Oracle Database

A database is made up of one or more tablespaces. A tablespace is a logical storage container in Oracle that comes at the top of the storage hierarchy and is made up of one or more datafiles. These files might be cooked files in a file system, raw partitions, ASM-managed database files, or files on a clustered file system. A tablespace contains segments, as described next.

Segments

Segments are the major organizational structure within a tablespace. Segments are simply your database objects that consume storage—typically objects such as tables, indexes, undo segments, and so on. Most times, when you create a table, you create a table segment. When you create a partitioned table, you are not creating a table segment, rather you create a segment per partition. When you create an index, you normally create an index segment, and so on. Every object that consumes storage is ultimately stored in a single segment. There are undo segments, temporary segments, cluster segments, index segments, and so on.

Note

It might be confusing to read “Every object that consumes storage is ultimately stored in a single segment.” You will find many CREATE statements that create multisegment objects. The confusion lies in the fact that a single CREATE statement may ultimately create objects that consist of zero, one, or more segments! For example, CREATE TABLE T ( x int primary key, y clob ) will create four segments: one for the TABLE T, one for the index that will be created in support of the primary key, and two for the CLOB (one segment for the CLOB is the LOB index, and the other segment is the LOB data itself). On the other hand, CREATE TABLE T ( x int, y date ) cluster MY_CLUSTER will create zero segments (the cluster is the segment in this case). We’ll explore this concept further in Chapter 10.

Extents

Segments consist of one or more extents . An extent is a logically contiguous allocation of space in a file. (Files themselves, in general, are not contiguous on disk; otherwise, we would never need a disk defragmentation tool! Also, with disk technologies such as Redundant Array of Independent Disks (RAID), you might find that a single file also spans many physical disks.) Traditionally, every segment starts with at least one extent. Oracle 11g Release 2 has introduced the concept of a “deferred” segment—a segment that will not immediately allocate an extent, so in that release and going forward, a segment might defer allocating its initial extent until data is inserted into it. When an object needs to grow beyond its initial extent, it will request another extent be allocated to it. This second extent will not necessarily be located right next to the first extent on disk—it may very well not even be allocated in the same file as the first extent. The second extent may be located very far away from the first extent, but the space within an extent is always logically contiguous in a file. Extents vary in size from one Oracle data block (explained shortly) to gigabytes.

Blocks

Extents, in turn, consist of blocks. A block is the smallest unit of space allocation in Oracle. Blocks are where your rows of data, or index entries, or temporary sort results are stored. A block is what Oracle typically reads from and writes to disk. Blocks in Oracle are generally one of four common sizes: 2KB, 4KB, 8KB, or 16KB (although 32KB is also permissible in some cases; there are restrictions in place as to the maximum size by operating system).

Note

Per Oracle’s database reference documentation, the minimum block size is 2048, and larger block sizes must be a multiple of the operating system physical block size.

The relationship between segments, extents, and blocks is shown in Figure 3-1.
../images/319655_4_En_3_Chapter/319655_4_En_3_Fig1_HTML.jpg
Figure 3-1

Segments, extents, and blocks

A segment is made up of one or more extents, and an extent is a logically contiguous allocation of blocks. A database may have up to six different block sizes in it.

Note

This feature of multiple block sizes was introduced for the purpose of making transportable tablespaces usable in more cases. The ability to transport a tablespace allows a DBA to move or copy the already formatted datafiles from one database and attach them to another—for example, to immediately copy all of the tables and indexes from an Online Transaction Processing (OLTP) database to a data warehouse (DW). However, in many cases, the OLTP database might be using a small block size, such as 2KB or 4KB, whereas the DW would be using a much larger one (8KB or 16KB). Without support for multiple block sizes in a single database, you wouldn’t be able to transport this information. Tablespaces with multiple block sizes should be used to facilitate transporting tablespaces; they are not generally used for anything else.

There will be the database default block size, which is the size specified in the initialization file during the CREATE DATABASE command. The SYSTEM tablespace will have this default block size always, but you can then create other tablespaces with nondefault block sizes of 2KB, 4KB, 8KB, 16KB, and, depending on the operating system, 32KB. The total number of block sizes is six if and only if you specified a nonstandard block size (not a power of two) during database creation. Hence, for all practical purposes, a database will have at most five block sizes: the default size and then four other nondefault sizes.

Any given tablespace will have a consistent block size, meaning that every block in that tablespace will be the same size. A multisegment object, such as a table with a LOB column, may have each segment in a tablespace with a different block size, but any given segment (which is contained in a tablespace) will consist of blocks of exactly the same size.

Most blocks, regardless of their size, have the same general format, which looks something like Figure 3-2.
../images/319655_4_En_3_Chapter/319655_4_En_3_Fig2_HTML.jpg
Figure 3-2

The structure of a block

Exceptions to this format include LOB segment blocks and hybrid columnar compressed blocks in Exadata storage, for example, but the vast majority of blocks in your database will resemble the format in Figure 3-2. The block header contains information about the type of block (table block, index block, and so on), transaction information when relevant (only blocks that are transaction managed have this information—a temporary sort block would not, for example) regarding active and past transactions on the block, and the address (location) of the block on the disk.

The next two block components are found on the most common types of database blocks, those of heap-organized tables. We’ll cover database table types in much more detail in Chapter 10, but suffice it to say that most tables are of this type.

The table directory, if present, contains information about the tables that store rows in this block (data from more than one table may be stored on the same block). The row directory contains information describing the rows that are to be found on the block. This is an array of pointers to where the rows are to be found in the data portion of the block. These three pieces of the block are collectively known as the block overhead, which is space used on the block that is not available for your data, but rather is used by Oracle to manage the block itself.

The remaining two pieces of the block are straightforward: there may be free space on a block, and then there will generally be used space that is currently storing data.

Now that you have a cursory understanding of segments, which consist of extents, which consist of blocks, let’s take a closer look at tablespaces and then at exactly how files fit into the big picture.

Tablespaces

As noted earlier, a tablespace is a container—it holds segments. Each segment belongs to exactly one tablespace. A tablespace may have many segments within it. All of the extents for a given segment will be found in the tablespace associated with that segment. Segments never cross tablespace boundaries. A tablespace itself has one or more datafiles associated with it. An extent for any given segment in a tablespace will be contained entirely within one datafile. However, a segment may have extents from many different datafiles. Graphically, a tablespace might look like Figure 3-3.
../images/319655_4_En_3_Chapter/319655_4_En_3_Fig3_HTML.jpg
Figure 3-3

A tablespace containing two datafiles, three segments, and four extents

Figure 3-3 shows a tablespace named USER_DATA. It consists of two datafiles, user_data01.dbf and user_data02.dbf. It has three segments allocated to it: T1, T2, and I1 (probably two tables and an index). The tablespace has four extents allocated in it, and each extent is depicted as a logically contiguous set of database blocks. Segment T1 consists of two extents, one extent in each file. Segments T2 and I1 each have one extent depicted. If we need more space in this tablespace, we could either resize the datafiles already allocated to the tablespace or we could add a third datafile to it.

A tablespace is a logical storage container in Oracle. As developers, we will create segments in tablespaces. We will never get down to the raw file level—we don’t specify that we want our extents to be allocated in a specific file (we can, but in general we don’t). Rather, we create objects in tablespaces and Oracle takes care of the rest. If at some point in the future, the DBA decides to move our datafiles around on disk to more evenly distribute I/O, that is OK with us. It will not affect our processing at all.

Storage Hierarchy Summary

In summary, the hierarchy of storage in Oracle is as follows:
  1. 1.

    A database is made up of one or more tablespaces.

     
  2. 2.

    A tablespace is made up of one or more datafiles. These files might be cooked files in a file system, raw partitions, ASM-managed database files, or a file on a clustered file system. A tablespace contains segments.

     
  3. 3.

    A segment (TABLE, INDEX, and so on) is made up of one or more extents. A segment exists in a tablespace, but may have data in many datafiles within that tablespace.

     
  4. 4.

    An extent is a logically contiguous set of blocks on disk. An extent is in a single tablespace and, furthermore, is always in a single file within that tablespace.

     
  5. 5.

    A block is the smallest unit of allocation in the database. A block is the smallest unit of I/O used by a database on datafiles.

     

Temp Files

Temporary datafiles (temp files) in Oracle are a special type of datafile. Oracle will use temporary files to store the intermediate results of large sort operations and hash operations, as well as to store global temporary table data, or resultset data, when there is insufficient memory to hold it all in RAM. Temporary tablespaces can also hold the UNDO generated by operations performed on global temporary tables. Permanent data objects, such as a table or an index, will never be stored in a temp file, but the contents of a temporary table and its indexes would be. So, you’ll never create your application tables in a temp file, but you might store data there when you use a temporary table.

Temp files are treated in a special way by Oracle. Normally, every change you make to an object will be recorded in the redo logs; these transaction logs can be replayed at a later date to “redo a transaction,” which you might do during recovery from failure. Temp files are excluded from this process. Specifically, transactions in global temporary tables (located in temp files) never have REDO generated for them, although they can have UNDO generated. Thus, there may be REDO generated working with temporary tables since UNDO is always protected by REDO, as you will see in detail in Chapter 9. The UNDO generated for global temporary tables is to support rolling back work you’ve done in your session, either due to an error processing data or because of some general transaction failure. A DBA never needs to back up a temporary datafile, and, in fact, attempting to do so would be a waste of time, as you can never recover a temporary datafile.

Note

In Oracle 12c and above, the UNDO generated for global temporary tables may be stored in the temporary tablespace. By default, UNDO will be generated into the permanent UNDO tablespace, just like prior releases. An init.ora system-level setting, or a TEMP_UNDO_ENABLED session-level settable parameter, may be set to TRUE to enable the UNDO generated for global temporary tables to be stored in a temp file. In this manner, no REDO will be generated for these operations. We will investigate this further in Chapter 9.

One of the nuances of true temp files is that if the OS permits it, the temporary files will be created sparse—that is, they will not actually consume disk storage until they need to. You can see that easily in this example (on Oracle Linux):
SQL> !df -h /tmp
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root
                       50G  6.5G   41G  14% /
SQL> create temporary tablespace temp_huge tempfile '/tmp/temp_huge.dbf' size 2g;
Tablespace created.
SQL> !df -h /tmp
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root
                       50G  6.5G   41G  14% /
SQL> !ls -l /tmp/temp_huge.dbf
-rw-r-----. 1 oracle oinstall 2147491840 Feb 15 18:06 /tmp/temp_huge.dbf
Note

The UNIX/Linux command df shows “disk free” space. This command showed that I have 41GB free in the file system containing /tmp before I added a 2GB temp file to the database. After I added that file, I still had 41GB free in the file system.

Apparently, it didn’t take much storage to hold that file. If we look at the ls output, it appears to be a normal 2GB file, but it is, in fact, consuming only a few kilobytes of storage currently. So we could actually create hundreds of these 2GB temporary files, even though we have roughly 41GB of disk space free. Sounds great—free storage for all! The problem is, as we start to use these temp files and they start expanding out, we would rapidly hit errors stating “no more space.” Since the space is allocated or physically assigned to the file as needed by the OS, we stand a definite chance of running out of room (especially if after we create the temp files, someone else fills up the file system with other stuff).

How to solve this differs from OS to OS. On UNIX/Linux, you can use dd to fill the file with data, causing the OS to physically assign disk storage to the file, or use cp to create a nonsparse file, for example:
SQL> !cp --sparse=never /tmp/temp_huge.dbf /tmp/temp_huge_not_sparse.dbf
SQL> !df -h /tmp
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root
                       50G  8.5G   39G  19% /
SQL> drop tablespace temp_huge including contents and datafiles;
Tablespace dropped.
SQL> create temporary tablespace temp_huge tempfile '/tmp/temp_huge_not_sparse.dbf' reuse;
Tablespace created.

After copying the sparse 2GB file to /tmp/temp_huge_not_sparse.dbf and creating the temporary tablespace using that temp file with the REUSE option, we are assured that temp file has allocated all of its file system space, and our database actually has 2GB of temporary space to work with.

Note

In my experience, Windows NTFS does not do sparse files, and this applies to UNIX/Linux variants. On the plus side, if you have to create a 15GB temporary tablespace on UNIX/Linux and have temp file support, you’ll find it happens very fast (instantaneously); just make sure you have 15GB free and reserve it in your mind.

Control Files

Control files are fairly small files (usually megabytes in size) that contain a directory of the other files Oracle needs. The parameter file tells the instance where the control files are, and the control files tell the instance where the database and online redo log files are. You can view the location of the control files via the following:
SQL> show parameter control_files
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
control_files                        string      /opt/oracle/oradata/CDB/control01.ctl, /opt/oracle/oradata/C
                                                 DB/control02.ctl

The control files also tell Oracle other things, such as information about checkpoints that have taken place, the name of the database (which should match the db_name parameter in the parameter file), the timestamp of the database as it was created, an archive redo log history (this can make a control file large in some cases), RMAN information, and so on.

Control files should be multiplexed either by hardware (RAID) or by Oracle when RAID or mirroring is not available. More than one copy should exist, and the copies should be stored on separate disks to avoid losing them in case you have a disk failure. It is not fatal to lose your control files—it just makes recovery that much harder.

Control files are something a developer will probably never have to actually deal with. To a DBA, they are an important part of the database, but to a software developer they are not really relevant.

Redo Log Files

Redo log files are crucial to the Oracle database. These are the transaction logs for the database. They are generally used only for recovery purposes, but they can be used for the following as well:
  • Instance recovery after a system crash

  • Media recovery after a datafile restore from backup

  • Standby database processing

  • Input into GoldenGate—redo log mining processes for information sharing (a fancy way of saying replication)

  • Allow administrators to inspect historical database transactions through the Oracle LogMiner utility

Their main purpose in life is to be used in the event of an instance or media failure or as a method of maintaining a standby database for failover. If the power goes off on your database machine, causing an instance failure, Oracle will use the online redo logs to restore the system to exactly the point it was at immediately prior to the power outage. If your disk drive containing your datafile fails permanently, Oracle will use archived redo logs, as well as online redo logs, to recover a backup of that drive to the correct point in time. Additionally, if you “accidentally” drop a table or remove some critical information and commit that operation, you can restore a backup and have Oracle restore it to the point just before the accident using these online and archived redo log files.

Virtually every operation you perform in Oracle generates some amount of redo to be written to the online redo log files. When you insert a row into a table, the end result of that insert is written to the redo logs. When you delete a row, the fact that you deleted that row is written. When you drop a table, the effects of that drop are written to the redo log. The data from the table you dropped is not written; however, the recursive SQL that Oracle performs to drop the table does generate redo. For example, Oracle will delete a row from the SYS.OBJ$ table (and other internal dictionary objects), and this will generate redo, and if various modes of supplemental logging are enabled, the actual DROP TABLE statement will be written into the redo log stream.

Some operations may be performed in a mode that generates as little redo as possible. For example, I can create an index with the NOLOGGING attribute. This means that the initial creation of the index data will not be logged, but any recursive SQL Oracle performed on my behalf will be. For example, the insert of a row into SYS.OBJ$ representing the existence of the index will be logged, as will all subsequent modifications of the index using SQL inserts, updates, and deletes. But the initial writing of the index structure to disk will not be logged.

I’ve referred to two types of redo log file: online and archived. We’ll take a look at each in the sections that follow. In Chapter 9, we’ll take another look at redo in conjunction with undo segments, to see what impact they have on you as a developer. For now, we’ll just concentrate on what they are and what their purpose is.

Online Redo Log

Every Oracle database has at least two online redo log file groups. Each redo log group consists of one or more redo log members (redo is managed in groups of members). The individual redo log file members of these groups are true mirror images of each other. These online redo log files are fixed in size and are used in a circular fashion. Oracle will write to log file group 1, and when it gets to the end of this set of files, it will switch to log file group 2 and overwrite the contents of those files from start to end. When it has filled log file group 2, it will switch back to log file group 1 (assuming we have only two redo log file groups; if we have three, it would, of course, proceed to the third group). This is shown in Figure 3-4.
../images/319655_4_En_3_Chapter/319655_4_En_3_Fig4_HTML.jpg
Figure 3-4

Writing to log file groups

The act of switching from one log file group to another is called a log switch. It is important to note that a log switch may cause a temporary “pause” in a poorly configured database. Since the redo logs are used to recover transactions in the event of a failure, we must be certain we won’t need the contents of a redo log file before we are able to use it. If Oracle isn’t sure that it won’t need the contents of a log file, it will suspend operations in the database momentarily and make sure that the data in the cache that this redo “protects” is safely written (checkpointed) onto disk. Once Oracle is sure of that, processing will resume and the redo file will be reused.

We’ve just started to talk about a key database concept: checkpointing . To understand how online redo logs are used, you’ll need to know something about checkpointing, how the database buffer cache works, and what a process called database block writer (DBWn) does. The database buffer cache and DBWn are covered in more detail later on, but we’ll skip ahead a little anyway and touch on them now.

The database buffer cache is where database blocks are stored temporarily. This is a structure in Oracle’s SGA. As blocks are read, they are stored in this cache, hopefully so we won’t have to physically reread them later. The buffer cache is first and foremost a performance tuning device. It exists solely to make the very slow process of physical I/O appear to be much faster than it is. When we modify a block by updating a row on it, these modifications are done in memory to the blocks in the buffer cache. Enough information to redo or to replay this modification is stored in the redo log buffer, another SGA data structure. When we COMMIT our modifications, making them permanent, Oracle does not go to all of the blocks we modified in the SGA and write them to disk. Rather, it just writes the contents of the redo log buffer out to the online redo logs. As long as that modified block is in the buffer cache and not on disk, we need the contents of that online redo log in case the database fails. If, at the instant after we committed, the power was turned off, the database buffer cache would be wiped out.

If this happens, the only record of our change is in that redo log file. Upon restart of the database, Oracle will actually replay our transaction, modifying the block again in the same way we did and committing it for us. So, as long as that modified block is cached and not written to disk, we can’t reuse (overwrite) that redo log file.

This is where DBWn comes into play. This Oracle background process is responsible for making space in the buffer cache when it fills up and, more important, for performing checkpoints. A checkpoint is the writing of dirty (modified) blocks from the buffer cache to disk. Oracle does this in the background for us. Many things can cause a checkpoint to occur, the most common being a redo log switch.

As we filled up log file 1 and switched to log file 2, Oracle initiated a checkpoint. At this point, DBWn started writing to disk all of the dirty blocks that are protected by log file group 1. Until DBWn flushes all of these blocks protected by that log file, Oracle can’t reuse (overwrite) it. If we attempt to use it before DBWn has finished its checkpoint, we’ll get a message like this in our database’s ALERT log:
...
Thread 1 cannot allocate new log, sequence 16
Checkpoint not complete
  Current log# 3 seq# 15 mem# 0: /opt/oracle/oradata/CDB/redo03.log...

So, when this message appeared, processing was suspended in the database while DBWn hurriedly finished its checkpoint. Oracle gave all the processing power it could to DBWn at that point in the hope it would finish faster.

This is a message you never want to see in a nicely tuned database instance. If you do see it, you know for a fact that you have introduced artificial, unnecessary waits for your end users. This can always be avoided. The goal (and this is for the DBA, not the developer necessarily) is to have enough online redo log files allocated so that you never attempt to reuse a log file before the checkpoint (initiated by the log switch) completes. If you see this message frequently, it means a DBA has not allocated sufficient online redo logs for the application, or that DBWn needs to be tuned to work more efficiently.

Different applications will generate different amounts of redo log. A decision support system (DSS, query only) or DW system will naturally generate significantly less online redo logging than an OLTP (transaction processing) system would, day to day. A system that does a lot of image manipulation in Binary Large Objects (BLOBs) in the database may generate radically more redo than a simple order entry system. An order entry system with 100 users will probably generate a tenth the amount of redo 1000 users would generate. Thus, there is no “right” size for your redo logs, although you do want to ensure they are large enough for your unique workload.

You must take many things into consideration when setting both the size of and the number of online redo logs. Many of them are beyond the scope of this book, but I’ll list some of them to give you an idea:
  • Peak workloads: You’d like your system to not have to wait for checkpoint-not-complete messages, to not get bottlenecked during your peak processing. You should size your redo logs not for average hourly throughput, but rather for your peak processing. If you generate 24GB of log per day, but 10GB of that log is generated between 9:00 am and 11:00 am, you’ll want to size your redo logs large enough to carry you through that two-hour peak. Sizing them for an average of 1GB per hour would probably not be sufficient.

  • Lots of users modifying the same blocks: Here, you might want large redo log files. Since everyone is modifying the same blocks, you’d like to update them as many times as possible before writing them out to disk. Each log switch will fire a checkpoint, so you’d like to switch logs infrequently. This may, however, affect your recovery time.

  • Mean time to recover: If you must ensure that a recovery takes as little time as possible, you may be swayed toward smaller redo log files, even if the previous point is true. It will take less time to process one or two small redo log files than a gargantuan one upon recovery. The overall system will run slower than it absolutely could day to day perhaps (due to excessive checkpointing), but the amount of time spent in recovery will be shorter. There are other database parameters that may also be used to reduce this recovery time, as an alternative to the use of small redo log files.

Archived Redo Log

The Oracle database can run in one of two modes: ARCHIVELOG mode and NOARCHIVELOG mode . The difference between these two modes is simply what happens to a redo log file when Oracle goes to reuse it. “Will we keep a copy of that redo or should Oracle just overwrite it, losing it forever?” is an important question to answer. Unless you keep this file, you can’t recover data from a backup to that point in time.

Say you take a backup once a week on Saturday. Now, on Friday afternoon, after you have generated hundreds of redo logs over the week, your hard disk fails. If you have not been running in ARCHIVELOG mode, the only choices you have right now are as follows:
  • Drop the tablespace(s) associated with the failed disk. Any tablespace that had a file on that disk must be dropped, including the contents of that tablespace. If the SYSTEM tablespace (Oracle’s data dictionary) or some other important system-related tablespace like your UNDO tablespace is affected, you can’t do this. You will have to use the next option instead.

  • Restore last Saturday’s data and lose all of the work you did that week.

Neither option is very appealing. Both imply that you lose data. If you had been executing in ARCHIVELOG mode, on the other hand, you simply would have found another disk and restored the affected files from Saturday’s backup onto it. Then, you would have applied the archived redo logs and, ultimately, the online redo logs to them (in effect replaying the week’s worth of transactions in fast-forward mode). You lose nothing. The data is restored to the point of the failure.

People frequently tell me they don’t need ARCHIVELOG mode for their production systems. I have yet to meet anyone who was correct in that statement. I believe that a system is not a production system unless it is in ARCHIVELOG mode. A database that is not in ARCHIVELOG mode will, someday, lose data. It is inevitable; you will lose data (not might, but will) if your database is not in ARCHIVELOG mode.

“We are using RAID-5, so we are totally protected” is a common excuse. I’ve seen cases where, due to a manufacturing error, all disks in a RAID set froze, all at about the same time. I’ve seen cases where the hardware controller introduced corruption into the datafiles, so people safely protected corrupt data with their RAID devices. RAID also does not do anything to protect you from operator error, one of the most common causes of data loss. RAID does not mean the data is safe, it might be more available, it might be safer, but data solely on a RAID device will be lost someday; it is a matter of time.

“If we had the backups from before the hardware or operator error and the archives were not affected, we could have recovered.” The bottom line is that there is no excuse for not being in ARCHIVELOG mode on a system where the data is of any value. Performance is no excuse; properly configured archiving adds little to no overhead. This, and the fact that a fast system that loses data is useless, means that even if archiving added 100 percent overhead, you still need to do it. A feature is overhead if you can remove it and lose nothing important; overhead is like icing on the cake. Preserving your data and making sure you don’t lose your data isn’t overhead—it’s the DBA’s primary job!

Only a test or maybe a development system should execute in NOARCHIVELOG mode. Most development systems should be run in ARCHIVELOG mode for two reasons:
  • This is how you will process the data in production; you want development to act and react as your production system would.

  • In many cases, the developers pull their code out of the data dictionary, modify it, and compile it back into the database. The development database holds the current version of the code. If the development database suffers a disk failure in the afternoon, what happens to all of the code you compiled and recompiled all morning? It’s lost.

Don’t let anyone talk you out of being in ARCHIVELOG mode. You spent a long time developing your application, so you want people to trust it. Losing their data will not instill confidence in your system.

Note

There are some cases in which a large DW could justify being in NOARCHIVELOG mode—if it made judicious use of READ ONLY tablespaces and was willing to fully rebuild any READ WRITE tablespace that suffered a failure by reloading the data.

Password Files

The password file is an optional file that permits the remote SYSDBA or administrator access to the database. When you attempt to start Oracle, there is no database available that can be consulted to verify passwords. When you start Oracle on the local system (i.e., not over the network, but from the machine the database instance will reside on), Oracle will use the OS to perform the authentication.

When Oracle was installed, the person performing the installation was asked to specify an OS group for the administrators. Normally, on UNIX/Linux, this group will be DBA by default, and ORA_DBA on Windows. It can be any legitimate group name on that platform, however. That group is “special,” in that any user in that group can connect to Oracle “as SYSDBA” without specifying a username or password.

However, what happens if you attempt to connect as SYSDBA over the network to a remote database:
$ sqlplus sys/foo@localhost:1521/CDB as sysdba
ERROR:
ORA-01017: invalid username/password; logon denied

OS authentication won’t work over the network for SYSDBA, even if the very unsafe (for security reasons) parameter REMOTE_OS_AUTHENT is set to true. So, OS authentication won’t work, and, as discussed earlier, if you’re trying to start up an instance to mount and open a database, then by definition there’s no database yet in which to look up authentication details. It is the proverbial chicken and egg problem.

Enter the password file. The password file stores a list of usernames and passwords that are allowed to remotely authenticate as SYSDBA over the network. Oracle must use this file to authenticate them, not the normal list of passwords stored in the database.

So, let’s correct our situation. First, verify that the REMOTE_LOGIN_PASSWORDFILE parameter is set to the default of EXCLUSIVE, meaning only one database uses a given password file:
SQL> show parameter remote_login_passwordfile
NAME                                 TYPE        VALUE
------------------------------------ ----------- ----------
remote_login_passwordfile            string      EXCLUSIVE
Note

Other valid values for this parameter are NONE, meaning there is no password file (there are no remote SYSDBA connections), and SHARED (more than one database can use the same password file).

The next step is to use the command-line tool (on UNIX/Linux and Windows) named orapwd to create and populate the initial password file:
$ orapwd
Usage: orapwd file=<fname> entries=<users> force=<y/n> asm=<y/n>
       dbuniquename=<dbname> format=<legacy/12> sysbackup=<y/n> sysdg=<y/n>
       syskm=<y/n> delete=<y/n> input_file=<input-fname>
Usage: orapwd describe file=<fname>
  where
    ...
  There must be no spaces around the equal-to (=) character.
The command we’ll use when logged into the operating system account that owns the Oracle software is
$ orapwd file=orapw$ORACLE_SID password=foo entries=20

This creates a password file named orapwCDB in my case (my ORACLE_SID is CDB). That’s the naming convention for this file on most UNIX/Linux platforms (see your installation/OS admin guide for details on the naming of this file on your platform), and it resides in the $ORACLE_HOME/dbs directory. On Windows, this file is named PW%ORACLE_SID%.ora, and it’s located in the %ORACLE_HOME%database directory. You should navigate to the correct directory prior to running the command to create that file, or move that file into the correct directory afterward.

Now, currently the only user in that file is SYS, even if there are other SYSDBA accounts on that database (they are not in the password file yet). Using that knowledge, however, we can for the first time connect as SYSDBA over the network:
$ sqlplus sys/foo@localhost:1521/CDB as sysdba
SQL> show user
USER is "SYS"
Note

If you experience an ORA-12505 “TNS:listener does not currently know of SID given in connect Descriptor” error during this step, that means that the database listener is not configured with a static registration entry for this server. The DBA has not permitted remote SYSDBA connections when the database instance is not up. You would need to configure static server registration in your listener.ora configuration file. Please search for "Configuring Static Service Information" (in quotes) on the OTN (Oracle Technology Network) documentation search page for the version of the database you are using for details on configuring this static service. If you encounter an ORA-12528 “TNS:listener: all appropriate instances are blocking new connections” error, you can also configure the tnsnames.ora file with the UR=A parameter that will allow you to connect to a blocked instance.

We have been authenticated, so we are in. We can now successfully start up, shut down, and remotely administer this database using the SYSDBA account. Now, we have another user, TKYTE, who has been granted SYSDBA, but will not be able to connect remotely yet:
$ sqlplus tkyte/foobar@PDB1 as sysdba
ERROR:
ORA-01017: invalid username/password; logon denied
The reason for this is that TKYTE is not yet in the password file. In order to get TKYTE into the password file, we need to “regrant” that account the SYSDBA privilege:
$ sqlplus / as sysdba
SQL> alter session set container=PDB1;
 SQL> grant sysdba to tkyte;
Grant succeeded.
SQL> exit
$ sqlplus tkyte/foobar@PDB1 as sysdba
SQL>

This created an entry in the password file for us, and Oracle will now keep the password in sync. If TKYTE alters their password, the old one will cease working for remote SYSDBA connections, and the new one will start working. The same process is repeated for any user who was a SYSDBA but is not yet in the password file.

Change Tracking File

The change tracking file is an optional file for use with Oracle 10g Enterprise Edition and above. The sole purpose of this file is to track what blocks have modified since the last incremental backup. With this, the Recovery Manager (RMAN) tool can back up only the database blocks that have actually been modified without having to read the entire database.

As Oracle is running, and as blocks are modified, Oracle optionally maintains a file that tells RMAN what blocks have been changed. Creating this change tracking file is rather simple and is accomplished via the ALTER DATABASE command:
$ mkdir -p /opt/oracle/product/btc
$ sqlplus / as sysdba
SQL> alter database enable block change tracking using file '/opt/oracle/product/btc/changed_blocks.btc';
Database altered.
Caution

I’ll say this from time to time throughout the book: please bear in mind that commands that set parameters, modify the database, or make fundamental changes should not be done lightly and definitely should be tested prior to performing them on your “real” system. The preceding command will, in fact, cause the database to do more work. It will consume resources.

To turn off and remove the block change tracking file, you’d use the ALTER DATABASE command once again:
SQL> alter database disable block change tracking;
Database altered.

Note that this command will erase the block change tracking file. It does not just disable the feature—it removes the file as well.

Note

On certain operating systems, such as Windows, you might find that if you run my example—creating a block change tracking file and then disabling it—the file appears to still exist. This is an OS-specific issue—it does not happen on many operating systems. It will happen only if you CREATE and DISABLE the change tracking file from a single session. The session that created the block change tracking file will leave that file open, and some operating systems will not permit you to erase a file that has been opened by a previous process (e.g., the session process that created the file). This is harmless; you just need to remove the file yourself later.

You can enable this new block change tracking feature in either ARCHIVELOG or NOARCHIVELOG mode. But remember, a database in NOARCHIVELOG mode, where the redo log generated daily is not retained, can’t recover all changes in the event of a media (disk or device) failure! A NOARCHIVELOG mode database will lose data someday. We will cover these two database modes in more detail in Chapter 9.

Flashback Logs

Flashback logs are used to support the FLASHBACK DATABASE command. Flashback logs contain “before images” of modified database blocks that can be used to return the database to the way it was at some prior point in time.

Flashback Database

The FLASHBACK DATABASE command was introduced to speed up the otherwise slow process of point-in-time database recovery. It can be used in place of a full database restore and a rolling forward using archive logs, and it is primarily designed to speed up the recovery from an “accident.” For example, let’s take a look at what a DBA might do to recover from an accidentally dropped schema, in which the right schema was dropped, just in the wrong database (it was meant to be dropped in the test environment). The DBA immediately recognizes the mistake they have made and shuts down the database right away. Now what?

Prior to the FLASHBACK DATABASE capability, what would probably happen is this:
  1. 1.

    The DBA would shut down the database.

     
  2. 2.

    The DBA would restore the last full backup of the database from tape (typically), generally a long process. Typically, this would be initiated with RMAN via RESTORE DATABASE UNTIL <point in time>.

     
  3. 3.

    The DBA would restore all archive redo logs generated since the backup that were not available on the system.

     
  4. 4.

    Using the archive redo logs (and possibly information in the online redo logs), the DBA would roll the database forward and stop rolling forward at a point in time just before the erroneous DROP USER command. Steps 3 and 4 in this list would typically be initiated with RMAN via RECOVER DATABASE UNTIL <point in time>.

     
  5. 5.

    The database would be opened with the RESETLOGS option.

     

This was a nontrivial process with many steps and would generally consume a large piece of time (time when no one could access the database, of course). The causes of a point-in-time recovery like this are many: an upgrade script gone awry, an upgrade gone bad, an inadvertent command issued by someone with the privilege to issue it (a mistake, probably the most frequent cause), or some process introducing data integrity issues into a large database (again, an accident; maybe it was run twice instead of just once, or maybe it had a bug). Whatever the reason, the net effect was a large period of downtime.

The steps to recover, assuming you configured the Flashback Database capability, would be as follows:
  1. 1.

    The DBA shuts down the database.

     
  2. 2.

    The DBA startup-mounts the database and issues the Flashback Database command, using either an SCN (the Oracle internal clock), a restore point (which is a pointer to an SCN), or a timestamp (wall clock time), which would be accurate to within a couple of seconds.

     
  3. 3.

    The DBA opens the database with resetlogs.

     

When flashing back, you can flashback either the entire container database (including all pluggable databases) or just a particular pluggable database. When flashing back the pluggable database, you would use restore points that you created for the entire database or for a specific pluggable database. Flashing back a pluggable database does not require that you open the database with resetlogs, but it does require that you issue the RECOVER DATABASE command while connected to the pluggable database you flashed back.

To use the flashback feature, your database must be in archivelog mode, and you must have a Fast Recovery Area (FRA) setup (because the flashback logs are stored in the FRA). To use normal restore points, you must enable flashback logging in the database. Guaranteed restore points do not require flashback logging in the database.

To view the flashback logging status, run the following query:
SQL> select flashback_on from v$database;
FLASHBACK_ON
------------------
NO
To enable flashback logging, do as follows in the root container:
$ sqlplus / as sysdba
SQL> alter database flashback on;

The final point here is that you need to set up the flashback capability before you ever need to use it. It is not something you can enable after the damage is done; you must make a conscious decision to use it, whether you have it on continuously or whether you use it to set restore points.

Fast Recovery Area (FRA)

The FRA in Oracle is a location where the database will manage many of the files related to database backup and recovery. In this area (an area being a part of a disk set aside for this purpose; a directory, for example), you could find the following:
  • RMAN backup pieces (full and/or incremental backups)

  • RMAN image copies (byte-for-byte copies of datafiles and control files)

  • Online redo logs

  • Archived redo logs

  • Multiplexed control files

  • Flashback logs

Oracle uses this new area to manage these files, so the server will know what is on disk and what is not on disk (and perhaps on tape elsewhere). Using this information, the database can perform operations like a disk-to-disk restore of a damaged datafile or the flashing back (a “rewind” operation) of the database to undo an operation that should not have taken place. For example, you could use the FLASHBACK DATABASE command to put the database back the way it was five minutes ago (without doing a full restore of the database and a point-in-time recovery). That would allow you to “undrop” that accidentally dropped user account.

To set up an FRA, you need to set two parameters: db_recovery_file_dest_size and db_recovery_file_dest. You can view the current settings of these parameters via
SQL> show parameter db_recovery_file_dest
NAME                                 TYPE        VALUE
------------------------------------ ----------- --------------------------
db_recovery_file_dest                string      /opt/oracle/fra
db_recovery_file_dest_size           big integer 100G

The Fast Recovery Area is more of a logical concept. It is a holding area for the file types discussed in this chapter. Its use is optional—you don’t need to use it, but if you want to use some advanced features, such as the Flashback Database, you must use this area to store the information.

Data Pump Files

Data Pump is a file format used by at least two tools in Oracle. External tables can load and unload data in the Data Pump format, and the import/export tools IMPDP and EXPDP use this file format. They are cross-platform (portable) binary files that contain metadata (not stored in CREATE/ALTER statements, but rather in XML) and possibly data. That they use XML as a metadata representation structure is actually relevant to you and me as end users of the tools. IMPDP and EXPDP have some sophisticated filtering and translation capabilities. This is in part due to the use of XML and to the fact that a CREATE TABLE statement is not stored as a CREATE TABLE, but rather as a marked-up document. This permits easy implementation of a request like “Please replace all references to tablespace FOO with tablespace BAR.” IMPDP just has to apply a simple XML transformation to accomplish the same. FOO, when it refers to a TABLESPACE, would be surrounded by <TABLESPACE>FOO</TABLESPACE> tags (or some other similar representation).

In Chapter 15, we’ll take a closer look at these tools. Before we get there, however, let’s see how we can use this Data Pump format to quickly extract some data from database A and move it to database B. We’ll be using an “external table in reverse” here.

External tables give us the ability to read flat files—plain old text files—as if they were database tables. We have the full power of SQL to process them. They are read-only and designed to get data from outside Oracle in. External tables can go the other way: they can be used to get data out of the database in the Data Pump format to facilitate moving the data to another machine or another platform. To start this exercise, we’ll need a DIRECTORY object, telling Oracle the location to unload to:
SQL> create or replace directory tmp as '/tmp';
Directory created.
SQL> create table all_objects_unload
    organization external
    ( type oracle_datapump
      default directory TMP
      location( 'allobjects.dat' )
    )
    as
    select * from all_objects
    /
Table created.
And that literally is all there is to it: we have a file in /tmp named allobjects.dat that contains the contents of the query select * from all_objects. We can peek at this information:
SQL> !strings /tmp/allobjects.dat | head
x86_64/Linux 2.4.xx
AL32UTF8
19.00.00.00.00
001:001:000001:000001
i<?xml version="1.0" encoding="UTF-8"?
...
That’s just the head, or top, of the file. Now, using a binary SCP, you can move that file to any other platform where you have Oracle installed and by issuing a CREATE DIRECTORY statement (to tell the database where the file is) and a CREATE TABLE statement, such as this:
SQL> create table t
( OWNER            VARCHAR2(30),
  OBJECT_NAME      VARCHAR2(30),
  SUBOBJECT_NAME   VARCHAR2(30),
  OBJECT_ID        NUMBER,
  DATA_OBJECT_ID   NUMBER,
  OBJECT_TYPE      VARCHAR2(19),
  CREATED          DATE,
  LAST_DDL_TIME    DATE,
  TIMESTAMP        VARCHAR2(19),
  STATUS           VARCHAR2(7),
  TEMPORARY        VARCHAR2(1),
  GENERATED        VARCHAR2(1),
  SECONDARY        VARCHAR2(1)
)
organization external
( type oracle_datapump
  default directory TMP
  location( 'allobjects.dat' ));

You would be set to read that unloaded data using SQL immediately. That is the power of the Data Pump file format: immediate transfer of data from system to system, over “sneakernet” if need be. Think about that the next time you’d like to take a subset of data home to work with over the weekend while testing.

Even if the database character sets differ (they did not in this example), Oracle has the ability now to recognize the differing character sets due to the Data Pump format and deal with them. Character set conversion can be performed on the fly as needed to make the data “correct” in each database’s representation.

Again, we’ll come back to the Data Pump file format in Chapter 15, but this section should give you an overall feel for what it is about and what might be contained in the file.

Flat Files

Flat files have been around since the dawn of electronic data processing. We see them literally every day. The text alert log described previously is a flat file. I found the following definition for “flat file” on the Internet and feel it pretty much wraps things up:

An electronic record that is stripped of all specific application (program) formats. This allows the data elements to be migrated into other applications for manipulation. This mode of stripping electronic data prevents data loss due to hardware and proprietary software obsolescence.

A flat file is simply a file whereby each “line” is a “record,” and each line has some text delimited, typically by a comma or pipe (vertical bar). Flat files are easily read by Oracle using either the legacy data loading tool SQLLDR or external tables. In fact, I will cover this in detail in Chapter 15.

Occasionally, a user will request data in a flat file format such as one of the following:
  • Character (or comma) separated values (CSV) : These are easily imported into tools such as spreadsheets.

  • HyperText Markup Language (HTML) : Used to display pages displayed in web browsers.

  • JavaScript Object Notation (JSON) : Standard text-based format for representing structured data and used for transmitting data in web browsers.

I’ll briefly demonstrate generating each of the file types in the following sections.

Generating a CSV File

You can easily generate CSV flat files from SQL*Plus. You can either use the -m 'csv on' switch from the operating system prompt or use SET MARKUP CSV after starting a SQL*Plus session, for example:
$ sqlplus scott/tiger@PDB1
SQL> set markup csv on delimiter , quote off
SQL> SELECT * FROM dept;
DEPTNO,DNAME,LOC
10,ACCOUNTING,NEW YORK
20,RESEARCH,DALLAS
30,SALES,CHICAGO
40,OPERATIONS,BOSTON
Here is an example of using the -m 'csv on' switch at the command line:
$ sqlplus -markup 'csv on quote off' scott/tiger@PDB1
SQL> select * from emp where rownum < 3;
EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO
7369,SMITH,CLERK,7902,17-DEC-80,800,,20
7499,ALLEN,SALESMAN,7698,20-FEB-81,1600,300,30
Tip

When you use the -markup 'csv on' switch, SQL*Plus sets variables such as ROWPREFETCH, STATEMENTCACHE, and PAGESIZE to optimize I/O performance.

Generating HTML

Similar to generating a CSV file, you can generate an HTML file from SQL*Plus by setting SET MARKUP HTML ON before running your query:
SQL> set markup html on
SQL> select * from dept;
<br>
<p>
<table border='1' width='90%' align='center' summary='Script output'>
<tr>
<th scope="col">
DEPTNO
</th>
<th scope="col">
DNAME
... <lots more output here removed for brevity>
You can also specify the -markup 'html on' switch at the command line to generate HTML output:
$ sqlplus -markup 'html on' scott/tiger@PDB1

In this manner, you can easily produce HTML output based on the contents of a table.

Generating a JSON File

The JSON_OBJECT function is used to convert table data into JSON. For example:
SQL> set heading off feedback off
SQL> set heading off feedback off
SQL> select json_object('deptNO' is d.deptno, 'dName' is d.dname) departments from dept d;
{"deptNO":10,"dName":"ACCOUNTING"}
{"deptNO":20,"dName":"RESEARCH"}
{"deptNO":30,"dName":"SALES"}
{"deptNO":40,"dName":"OPERATIONS"}

The prior technique provides you a quick and efficient way of generating JSON output directly from SQL*Plus.

Note

There are also numerous other tools you can use to generate flat files such as TOAD, APEX, SQL Developer, and Enterprise Manager.

Summary

In this chapter, we explored the important types of files used by the Oracle database, from lowly parameter files (without which you won’t even be able to get started) to the all-important redo log and datafiles. We examined the storage structures of Oracle from tablespaces to segments and extents and finally down to database blocks, the smallest unit of storage. We briefly reviewed how checkpointing works in the database, and we even started to look ahead at what some of the physical processes or threads of Oracle do. We also covered many optional file types such as password files, change tracking files, Data Pump files, and more. In the next chapter, we are ready to look at the Oracle memory structures.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.47.25