Aviation Technology · · 7 min · Jun 6, 2026
Tutorial 22

Preparing AlmaLinux 9 and Oracle 26ai for APEX

Kernel, limits, and database parameters for a stable APEX host

This tutorial tunes the foundation. Before APEX or ORDS exist, the operating system and the database itself need settings that match the hardware and the workload. Skip this and the APEX install can fail outright, or the server will run but drag under load. We do two things here: tune AlmaLinux 9 at the kernel and limits level (Phase 1), then tune the Oracle 26ai database parameters (Phase 2).

This is the second stop in the series, right after the architecture overview. It assumes a fresh AlmaLinux 9 server with Oracle Database 26ai already installed and a container database named ORCLCDB in place. Installing the database engine itself is a separate task; on RHEL-family distributions like AlmaLinux 9 the usual path is to add the Oracle Linux 9 yum repository, install the preinstall RPM, then the Enterprise Edition RPM. The setup guide's "Further reading" points to the official documentation for that step.

Hostnames, IPs, and paths shown here are placeholders. Substitute your own. The memory numbers in Phase 2 are derived from an 8 GB server - if your RAM differs, scale them.

Phase 1 - OS tuning

Oracle Database leans on specific kernel settings to run correctly and efficiently. They control how much shared memory Oracle may allocate for its SGA, how many file descriptors a process may open, how async I/O behaves, and how aggressively the kernel reclaims and swaps memory. Get them wrong and either the install refuses to proceed or performance suffers badly. Everything in this phase is permanent across reboots.

Kernel parameters

These go in /etc/sysctl.d/97-oracle.conf. A few are worth calling out. kernel.shmmax is the largest shared memory segment Oracle can allocate - set to 6 GB on this 8 GB server. fs.aio-max-nr caps async I/O requests, which Oracle relies on for direct I/O. vm.swappiness = 10 tells the kernel to avoid swapping, keeping the Oracle SGA resident in RAM rather than paged out to disk.

# Shared memory
kernel.shmmax = 6442450944
kernel.shmall = 1572864
kernel.shmmni = 4096
kernel.sem    = 250 32000 100 128

# Async I/O
fs.aio-max-nr  = 1048576
fs.file-max    = 6815744

# Network buffers
net.core.rmem_max = 4194304
net.core.wmem_max = 4194304
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 65536 4194304

# VM - reduce swapping, keep Oracle in RAM
vm.swappiness             = 10
vm.dirty_background_ratio = 3
vm.dirty_ratio            = 15

sysctl -p /etc/sysctl.d/97-oracle.conf

The final sysctl -p line loads the file so the settings take effect without a reboot. kernel.shmmax at 6442450944 is exactly 6 GB in bytes - this is one of the values to revisit if your server is not an 8 GB box.

User limits

The Oracle account also needs raised resource limits. These go in /etc/security/limits.d/99-oracle.conf. nofile sets how many files the oracle user may open at once - Oracle juggles datafiles, redo logs, and trace files simultaneously, and the Linux default is far too low. memlock = unlimited lets Oracle lock SGA pages into RAM so they can never be swapped out.

oracle  soft  nofile    65536
oracle  hard  nofile    65536
oracle  soft  nproc     16384
oracle  hard  nproc     16384
oracle  soft  stack     10240
oracle  hard  stack     32768
oracle  soft  memlock   unlimited
oracle  hard  memlock   unlimited

Disable Transparent Huge Pages

Transparent Huge Pages (THP) is a Linux memory feature that, on a database host, does more harm than good: as the kernel tries to defragment memory into large pages, Oracle sees latency spikes. Oracle's standing recommendation is to disable it explicitly.

echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

These two commands turn THP off for the running system. To make the change survive reboots, you would also set it through the bootloader or a boot-time service - the guide shows the runtime commands.

Phase 2 - Database parameter tuning

A fresh Oracle install is deliberately conservative. It does not know how much memory your server has, so it allocates little. We tell it. The two big pools are the SGA (System Global Area, the shared cache all sessions use) and the PGA (Program Global Area, per-session working memory). On this 8 GB server the split is roughly 4.5 GB to the SGA, 1.5 GB to the PGA, leaving about 2 GB for the OS and everything else.

Two clauses appear throughout. SCOPE=SPFILE writes the change to the server parameter file so it survives a restart but does not apply until then. SCOPE=BOTH applies the change immediately and saves it to the SPFILE. The memory parameters here are SPFILE-only because they take effect when the database is restarted after this phase.

Memory parameters

Connect as sysdba to the CDB and apply the memory settings.

ALTER SYSTEM SET sga_max_size          = 4608M SCOPE=SPFILE;
ALTER SYSTEM SET sga_target            = 4608M SCOPE=SPFILE;
ALTER SYSTEM SET db_cache_size         = 2048M SCOPE=SPFILE;
ALTER SYSTEM SET shared_pool_size      = 1280M SCOPE=SPFILE;
ALTER SYSTEM SET large_pool_size       = 256M  SCOPE=SPFILE;
ALTER SYSTEM SET java_pool_size        = 256M  SCOPE=SPFILE;
ALTER SYSTEM SET streams_pool_size     = 128M  SCOPE=SPFILE;
ALTER SYSTEM SET pga_aggregate_target  = 1536M SCOPE=SPFILE;
ALTER SYSTEM SET pga_aggregate_limit   = 3072M SCOPE=SPFILE;
ALTER SYSTEM SET workarea_size_policy  = AUTO  SCOPE=SPFILE;

Every one of these is sized for 8 GB of RAM. sga_max_size and sga_target at 4608M (4.5 GB), pga_aggregate_target at 1536M (1.5 GB) - if you are on different hardware, these are the numbers to rescale. Keep the same proportions and leave headroom for the OS.

Processes, cursors, and I/O

The next group sizes how many sessions the database supports and how it does I/O. processes and sessions cap concurrency. filesystemio_options = SETALL enables both direct I/O and async I/O. Note that open_cursors, fast_start_mttr_target, and optimizer_adaptive_statistics use SCOPE=BOTH, so they apply at once.

ALTER SYSTEM SET processes               = 500    SCOPE=SPFILE;
ALTER SYSTEM SET sessions                = 555    SCOPE=SPFILE;
ALTER SYSTEM SET open_cursors            = 1000   SCOPE=BOTH;
ALTER SYSTEM SET session_cached_cursors  = 100    SCOPE=SPFILE;
ALTER SYSTEM SET filesystemio_options    = SETALL SCOPE=SPFILE;
ALTER SYSTEM SET log_buffer              = 33554432 SCOPE=SPFILE;
ALTER SYSTEM SET fast_start_mttr_target  = 60    SCOPE=BOTH;
ALTER SYSTEM SET optimizer_adaptive_statistics = TRUE SCOPE=BOTH;

Resize the redo logs - 200 MB to 500 MB

The database ships with three 200 MB redo log groups. Small redo logs switch often, and every log switch triggers a checkpoint and a burst of I/O. An APEX workload is full of small, frequent transactions, so those switches add up. Moving to four 500 MB groups cuts the switch and checkpoint frequency and smooths out write performance.

You cannot shrink a log group in place, so the technique is to add the new larger groups, force the old ones to become inactive with a couple of log switches and a checkpoint, then drop them.

-- Add 4 new groups at 500MB
ALTER DATABASE ADD LOGFILE GROUP 4 '/opt/oracle/oradata/ORCLCDB/redo04.log' SIZE 500M;
ALTER DATABASE ADD LOGFILE GROUP 5 '/opt/oracle/oradata/ORCLCDB/redo05.log' SIZE 500M;
ALTER DATABASE ADD LOGFILE GROUP 6 '/opt/oracle/oradata/ORCLCDB/redo06.log' SIZE 500M;
ALTER DATABASE ADD LOGFILE GROUP 7 '/opt/oracle/oradata/ORCLCDB/redo07.log' SIZE 500M;

-- Switch logs to make old groups inactive, then drop them
ALTER SYSTEM SWITCH LOGFILE;
ALTER SYSTEM CHECKPOINT;
ALTER DATABASE DROP LOGFILE GROUP 1;
ALTER DATABASE DROP LOGFILE GROUP 2;
ALTER DATABASE DROP LOGFILE GROUP 3;
A group must be inactive before you can drop it. If a DROP LOGFILE GROUP complains that the group is active or current, issue another ALTER SYSTEM SWITCH LOGFILE; and checkpoint, then retry. The datafile paths under /opt/oracle/oradata/ORCLCDB/ assume the placeholder Oracle base - adjust them to your own layout.

With the memory and process parameters set to SPFILE, restart the database so they take effect. The redo changes above are already live.

What you have now: an AlmaLinux 9 host tuned for Oracle - kernel parameters, raised limits, THP disabled - and an Oracle 26ai database sized for 8 GB of RAM with larger redo logs. The foundation is stable. Next, in Tutorial 02, we carve out a dedicated pluggable database, APEX_PDB, with its own tablespaces and install the APEX 26.1 engine into it.