Block volume sizing on OCI is two independent decisions: capacity and performance. A 500 GB volume at the default Balanced tier delivers 3000 IOPS. The same volume at Higher Performance delivers 37,500 IOPS. If you deploy a database volume at the default tier and find performance disappointing, this is why. The performance tier is not automatic. You choose it explicitly, and it affects your cost.
Performance Tiers
Four tiers controlled by vpus_per_gb. Lower Cost (0) = 2 IOPS/GB for cold data. Balanced (10) = 60 IOPS/GB for general workloads. Higher Performance (20) = 75 IOPS/GB for databases. Ultra High Performance (30-120) = up to 225 IOPS/GB for demanding OLTP. IOPS = vpus_per_gb times GB, so a 500 GB Higher Performance volume delivers 37,500 IOPS.
Step 1: Database Volumes at Correct Tiers
resource "oci_core_volume" "oracle_db_data" {
compartment_id = var.compartment_id
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
display_name = "oracle-db-data"
size_in_gbs = 500
vpus_per_gb = 20
is_auto_tune_enabled = false
defined_tags = { "Operations.Environment" = "production", "Operations.ManagedBy" = "terraform" }
}
resource "oci_core_volume" "oracle_db_redo" {
compartment_id = var.compartment_id
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
display_name = "oracle-db-redo"
size_in_gbs = 100
vpus_per_gb = 30
is_auto_tune_enabled = false
}
resource "oci_core_volume" "oracle_db_archive" {
compartment_id = var.compartment_id
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
display_name = "oracle-db-archive"
size_in_gbs = 1000
vpus_per_gb = 10
}
Step 2: Volume Attachments
resource "oci_core_volume_attachment" "db_data" {
attachment_type = "paravirtualized"
instance_id = oci_core_instance.db_server.id
volume_id = oci_core_volume.oracle_db_data.id
is_pv_encryption_in_transit_enabled = true
is_read_only = false
}
resource "oci_core_volume_attachment" "db_redo" {
attachment_type = "iscsi"
instance_id = oci_core_instance.db_server.id
volume_id = oci_core_volume.oracle_db_redo.id
use_chap = true
is_multipath = true
encryption_in_transit_type = "BM_ENCRYPTION_IN_TRANSIT"
}
Step 3: Backup Policy
resource "oci_core_volume_backup_policy" "database_policy" {
compartment_id = var.compartment_id
display_name = "database-volume-backup-policy"
schedules {
backup_type = "INCREMENTAL"
period = "ONE_HOUR"
retention_seconds = 86400
time_zone = "UTC"
}
schedules {
backup_type = "INCREMENTAL"
period = "ONE_DAY"
hour_of_day = 2
retention_seconds = 604800
time_zone = "UTC"
}
schedules {
backup_type = "FULL"
period = "ONE_WEEK"
day_of_week = "SUNDAY"
hour_of_day = 1
retention_seconds = 2592000
time_zone = "UTC"
}
}
resource "oci_core_volume_backup_policy_assignment" "db_data" {
asset_id = oci_core_volume.oracle_db_data.id
policy_id = oci_core_volume_backup_policy.database_policy.id
}
resource "oci_core_volume_backup_policy_assignment" "db_redo" {
asset_id = oci_core_volume.oracle_db_redo.id
policy_id = oci_core_volume_backup_policy.database_policy.id
}
Step 4: Volume Group for Consistent Snapshots
A Volume Group backs up all volumes simultaneously in a crash-consistent snapshot, ensuring all three database volumes are captured at the same point in time and the backup is restorable without RMAN reconstruction.
resource "oci_core_volume_group" "oracle_db" {
compartment_id = var.compartment_id
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
display_name = "oracle-database-volume-group"
source_details {
type = "volumeIds"
volume_ids = [
oci_core_volume.oracle_db_data.id,
oci_core_volume.oracle_db_redo.id,
oci_core_volume.oracle_db_archive.id
]
}
}
Step 5: Performance Alarms
resource "oci_monitoring_alarm" "volume_throttled" {
compartment_id = var.compartment_id
display_name = "oracle-db-data-volume-throttled"
is_enabled = true
metric_compartment_id = var.compartment_id
namespace = "oci_blockstore"
query = "VolumeThrottledIOs[5m]{volumeId = '${oci_core_volume.oracle_db_data.id}'}.sum() > 100"
severity = "WARNING"
pending_duration = "PT5M"
destinations = [var.ops_notification_topic_id]
body = "Oracle DB data volume IOPS are being throttled. Consider upgrading the VPUs per GB setting."
}
resource "oci_monitoring_alarm" "redo_latency" {
compartment_id = var.compartment_id
display_name = "oracle-redo-write-latency"
is_enabled = true
metric_compartment_id = var.compartment_id
namespace = "oci_blockstore"
query = "VolumeWriteLatency[5m]{volumeId = '${oci_core_volume.oracle_db_redo.id}'}.mean() > 1"
severity = "CRITICAL"
pending_duration = "PT5M"
destinations = [var.ops_notification_topic_id]
body = "Oracle redo log volume write latency above 1ms. High redo write latency directly increases transaction commit time."
}
Operational Notes
If you need more IOPS without moving to Ultra High Performance, increasing volume size at the same tier delivers proportionally more IOPS at the same per-GB price. A 200 GB redo log at Higher Performance delivers 15,000 IOPS versus 7,500 IOPS at 100 GB, doubling throughput by doubling size.
Ultra High Performance requires multipath iSCSI, not the standard paravirtualized attachment. Without multipath, a single iSCSI connection becomes the bottleneck before the volume reaches its rated IOPS. Set is_multipath = true on the volume attachment and configure OS-level multipath on Oracle Linux before placing the volume into service.
Regards,
Osama
#OCI #OracleCloud #BlockVolume #Storage #Terraform #IaC #TechBlog #Oracle #DatabaseEngineering #PlatformEngineering #OracleCloudInfrastructure #VolumeBackup #IOPS #StoragePerformance #OracleDatabase #DisasterRecovery #VolumeGroups #CloudInfrastructure #HighPerformance #CloudStorage
Leave a comment