Database Administration and Operations Questions
Day-to-day operation of database systems: configuration and tuning, patching and upgrades, automation and scripting, standards and best practices, and capacity/growth management. Covers the responsibilities of keeping databases reliable, secure, and maintainable in production. The operational-ownership surface for DBA and platform roles.
Plan a migration from MySQL to PostgreSQL for a business-critical service. Cover schema translation (types, auto-increment vs sequences, constraints), data migration at scale (initial copy + CDC), keeping systems in sync during cutover, validation checks, and a rollback procedure to minimize downtime and risk.
Sample Answer
Requirements & constraints:
- Zero/near-zero downtime, data integrity, support large dataset (terabytes), transactional consistency for business-critical service, reversible rollback, security/compliance.
High-level plan:
- Prepare target Postgres schema (translation + indexing).
- Initial bulk copy (snapshot) with parallel loaders.
- Continuous replication (CDC) from MySQL to Postgres until cutover.
- Controlled cutover with brief write freeze or dual-write, validation, switch traffic.
- Rollback plan & post-cutover monitoring.
Schema translation (MySQL → Postgres):
- Types: VARCHAR/TEXT → same; TINYINT → SMALLINT/BOOLEAN if used as flag; ENUM → TEXT or CREATE TYPE enum; DATETIME → TIMESTAMP WITHOUT TIME ZONE (or WITH TZ if needed); UNSIGNED integers → larger signed type (e.g., INT UNSIGNED → BIGINT) because Postgres lacks unsigned.
- Auto-increment: MySQL AUTO_INCREMENT → Postgres SERIAL/IDENTITY or explicit SEQUENCE. Prefer GENERATED AS IDENTITY for standards compliance. If preserving IDs, create sequence and set nextval to max(id)+1.
- Constraints: Translate CHECKs, NOT NULL, UNIQUE, FOREIGN KEYS. MySQL implicit index differences: recreate functional and partial indexes in Postgres (support expressions).
- Collation/charset: ensure UTF-8 and appropriate collation; map MySQL collations to Postgres equivalents.
- Stored procedures/triggers: rewrite in PL/pgSQL; or keep logic in application layer if easier.
Data migration at scale:
- Initial copy: take a consistent snapshot using mysqldump --single-transaction for InnoDB or use Percona Xtrabackup. Export schema-mapped data into CSV/Parquet and use COPY for parallel bulk loads into Postgres. Split by sharding key (e.g., id ranges) for parallelism.
- CDC: Deploy Debezium (Kafka) or Maxwell to capture binlog events and translate to Postgres via Kafka Connect or a custom consumer that applies idempotent upserts into Postgres. Ensure ordering per PK partition.
- Ensure transaction boundaries: use Debezium's transaction metadata or implement transactional apply logic to avoid partially-applied transactions.
Keeping systems in sync & cutover:
- Run CDC continuously until cutover; monitor lag metrics.
- During final cutover window: option A (near-zero downtime): enable dual-write in application (writes to both DBs) for a short period and read from Postgres after validation. Option B (simpler): short write freeze—deny writes for a controlled window, wait for CDC to apply all events, then switch reads to Postgres and re-enable writes.
- Use feature flag / canary traffic to route small % of reads to Postgres first.
Validation checks:
- Row counts per table, checksum per range (e.g., mysqldump --where ranges + pg_dump and compare checksums, or use pt-table-checksum style logic adapted for Postgres).
- Spot-check critical queries and compare results.
- Compare aggregate metrics (counts, sums) and referential integrity.
- Verify sequences: max(id) < nextval, no collisions.
- Application smoke tests (end-to-end flows), latency and error monitoring.
Rollback procedure:
- If dual-write: roll back by switching reads back to MySQL and stop writing to Postgres; keep Postgres as replica for debugging.
- If write freeze: keep MySQL writes queued/stashed; on failure, re-enable MySQL writes and discard Postgres changes (or replay selectively). Ensure no irreversible schema-only changes made.
- Keep binlogs and transaction offsets to resume/rollback precisely.
- Test rollback in a rehearsal environment before production.
Operational best practices:
- Automate migration scripts, CI tests, and rehearsals in staging with production-sized data if possible.
- Monitor: CDC lag, replication failures, application errors, query performance regressions.
- Communicate window to stakeholders, provide runbook with step-by-step commands and escalation contacts.
This approach minimizes downtime, preserves integrity, and gives clear rollback options while handling schema and operational differences between MySQL and PostgreSQL.
Describe how you would automate a PostgreSQL backup and restore verification in CI. Include which backups to take (logical dumps vs base backup + WAL), how to restore into an isolated environment, what post-restore validations to run (row counts, checksums, smoke tests), and approaches to avoid exposing production-sensitive data during tests.
Sample Answer
Situation: I’d automate backup + restore verification as a CI job that runs nightly and on every major schema change so we continuously validate our disaster-recovery pipeline.
Approach overview:
- Backups: produce both logical dumps for schema/row-level verification and physical base backups + WAL segments for full recovery testing.
- Logical: pg_dump --format=directory for targeted tables and fast restores.
- Physical: pg_basebackup (or wal-g/wal-e) to capture a consistent filesystem image plus continuous WAL shipping.
- CI pipeline steps:
- Trigger: scheduled or post-deploy. Create artifacts: pg_dump dir + upload, and trigger physical base backup + push WALs to object storage.
- Restore job spins up isolated environment (ephemeral k8s namespace or ephemeral VM/container) with same PG version/config.
- Restore physical base backup, restore/replay WALs to a target point-in-time, or restore pg_dump into a clean cluster for logical checks.
- Run post-restore validations.
- Tear down environment and report.
Example commands (simplified):
# logical dump
pg_dump -Fd -f /tmp/dumpdir mydb
# base backup
pg_basebackup -D /tmp/base -Fp -Xs -P -h primary
# push WALs via wal-g/wal-e (configured separately)
Restore into isolated env:
- Use Kubernetes StatefulSet or docker-compose to start a Postgres pod with empty data dir, then copy base backup and WALs in, set recovery.conf / standby.signal, and start Postgres. For pg_dump restores, initialize a new DB and pg_restore --jobs to parallelize.
- Ensure network isolation and RBAC so CI runners can’t access production.
Post-restore validations:
- Structural: compare schema versions and critical migrations (SELECT version FROM schema_migrations).
- Row-level checks: run deterministic row-counts for key tables and compare to saved counts (from pre-backup metadata).
- Checksums: validate page-level checksums if enabled (pg_checksums/pg_verify_checksums) and run sample content checksums:
- Pre-backup: store sha256 hashes of deterministic primary-key ordered concatenated columns for N sampled rows per table.
- Post-restore: recompute and compare.
- Functional/smoke tests: run a small suite of application-level tests against the restored DB (read-only API flows, key queries, indexing performance).
- WAL replay correctness: verify last WAL LSN equals expected LSN and run consistency queries (SELECT pg_last_wal_replay_lsn()).
- Timing/latency: measure restore time and WAL replay duration for SLA monitoring.
Avoid exposing production-sensitive data:
- Prefer masked/copied subsets:
- Use deterministic anonymization pipeline on dump before upload (hash PII, redact fields, replace emails with placeholder domains).
- Create a “subset export” that selects only necessary tables/rows (LIMIT, WHERE created_at > X).
- Encryption and access controls: encrypt backups in transit and at rest; store keys in CI secrets manager; restrict CI job permissions.
- Synthetic data: where feasible, generate realistic synthetic datasets for non-PII checks.
- Logging & audit: prevent sensitive data from being echoed in CI logs; mask outputs.
Why this works:
- Combining logical and physical backups tests both schema/row-level integrity and full disaster recovery including WAL replay.
- Isolated ephemeral restores avoid production exposure and ensure reproducible environments.
- Deterministic hashes, row counts, and smoke tests provide fast, automatable assertions; deeper checks run less frequently.
- Masking/subsetting and strict access controls balance realism with security.
Metrics & alerts:
- Failures should bubble up to on-call and create an incident if restores exceed RTO/RPO thresholds or validations fail. Store historical restore times and validation successes for reliability tracking.
Explain the difference between row-level triggers and statement-level triggers in SQL databases. Give two practical use cases for triggers and discuss potential pitfalls (performance impact, hidden side effects, order of execution, and recursion).
Sample Answer
Row-level vs statement-level triggers:
- Row-level triggers fire once for each row affected by the triggering statement. Example: an UPDATE that changes 100 rows will invoke a row trigger 100 times; you can reference OLD and NEW per-row values.
- Statement-level triggers fire once per SQL statement regardless of how many rows are affected. They run after/before the statement as a whole and typically cannot access per-row OLD/NEW values (some DBs provide transition tables instead).
Two practical use cases:
- Audit trail (row-level): capture who changed each row and store OLD/NEW to an audit table. Row-level ensures you record each changed row with its prior state.
- Denormalized counters or derived summaries (statement-level): update a summary table or invalidate cache once after a bulk insert/delete to avoid repeated work per row.
Potential pitfalls:
- Performance impact: row-level triggers can be very expensive on bulk operations (O(rows) extra work). Statement triggers are lighter but still add latency.
- Hidden side effects: triggers run implicitly — business logic hidden in the DB can surprise app developers and complicate debugging.
- Order of execution: when multiple triggers exist (or multiple triggers for BEFORE/AFTER), ordering may be undefined or DB-specific; relying on implicit order is fragile.
- Recursion and cascading: triggers that modify the same table can cause recursive invocation or cascade chains. Many DBs allow/disallow recursion or provide depth limits; uncontrolled recursion can cause loops or heavy resource use.
Best practices: document triggers, keep them small, prefer statement-level for bulk-safe work, use explicit stored procedures for complex logic, and include metrics/tests to detect performance regressions.
You must alter a 1TB orders table to change a column type and add an index without significant downtime. Describe an online schema migration approach using a shadow table, triggers or logical replication, backfill strategy, cutover steps, validation to ensure consistency, and an explicit rollback plan.
Sample Answer
Requirements & constraints:
- 1TB orders table; change column type and add index with minimal downtime and strong consistency.
- Target: zero/near-zero writes blocking, reads unaffected, ability to rollback quickly.
High-level approach: shadow table + dual-writes (via triggers or app-level) + backfill + validation + quick cutover and rollback.
Steps:
- Create shadow table
- Create orders_shadow with new column type and the new index. Keep same schema otherwise, plus metadata columns (source_txid, migrated_at).
- Set up dual-write for new changes
Option A — DB trigger:
- Add AFTER INSERT/AFTER UPDATE/AFTER DELETE triggers on orders that apply the same change to orders_shadow. Triggers must be idempotent and handle type conversion errors (log to separate table).
Option B — Application-level dual-write: - Modify write path to write to both tables behind a feature flag; safer for some DBs.
Option C — Logical replication:
- Use logical replication (Debezium/pg_logical) to stream existing and new changes into shadow table; simplifies initial sync + ongoing changes.
- Backfill existing rows
- Perform large-data backfill in small batched transactions (e.g., 10k–100k rows), ordered by primary key to minimize lock contention.
- Throttle and monitor replication lag; run during steady traffic; use parallel workers but limit concurrency.
- Mark progress with a checkpoint table so backfill can resume.
- Validation
- Row-count checks, checksum/hash comparisons (e.g., md5 of JSON of relevant columns) over sampled ranges and full compare in background.
- Confirm index correctness by running representative queries against both tables and comparing plans/results.
- Monitor for trigger/application errors and reconcile differences via replays from transaction log.
- Cutover
- Quiesce writes briefly (usually a few seconds) — options:
a) Flip a feature flag so application reads/writes go to orders_shadow name swapped via rename in a single atomic DDL (depends on DB).
b) If DB supports transactional rename: BEGIN; ALTER TABLE orders RENAME TO orders_old; ALTER TABLE orders_shadow RENAME TO orders; COMMIT. - Ensure no replication lag and zero pending operations in checkpoint.
- Post-cutover
- Keep orders_old for at least a retention period; run background verification for a day.
- Monitor app metrics, slow queries, and errors.
- Rollback plan
- If inconsistency or errors detected pre-cutover: stop backfill, reconcile, and fix triggers/app writes.
- If post-cutover problem: quickly rename tables back (atomic rename) to revert; or flip feature flag to point to orders_old.
- Prepare automated script to abort cutover and switch reads/writes back; test the rollback path on staging.
Operational considerations & trade-offs:
- Triggers guarantee low-latency dual-write but add CPU overhead; logical replication offloads to external consumer but increases complexity.
- Batched backfill avoids long locks; ensure foreign key and constraint behavior on shadow table matches production.
- Test entire flow on a copy of production.
This approach minimizes downtime by keeping production writes live during backfill, provides strong validation, and includes a tested, fast rollback mechanism.
Design a comprehensive database security plan for storing PII. Cover network-level controls, authentication and authorization, role-based access control, row-level security policies, encryption at rest and in transit, key management, audit logging, and key rotation policies. Explain how to validate and test these controls.
Sample Answer
Requirements & constraints:
- Protect PII (confidentiality, integrity, availability), regulatory compliance (GDPR/CCPA/HIPAA), low-latency reads for app, multi-tenant users, auditability.
High-level controls (network → app → data):
- Network-level controls
- Private DB subnet in VPC, no public IPs.
- DB behind internal load balancer/proxy (e.g., PgBouncer) and bastion for admin access.
- Security groups / NACLs: allow only app servers’ subnets and monitoring IPs on DB ports.
- Use mutual TLS for any service-to-db connections and mTLS where feasible.
- Authentication & authorization
- Centralized identity: integrate DB user auth with corporate IdP (OIDC/LDAP/AD) via IAM roles (RDS IAM, Cloud SQL IAM) or proxy that maps tokens to DB sessions.
- Short-lived credentials using federation; prohibit long-lived DB passwords for humans.
- Role-Based Access Control (RBAC)
- Define minimal roles: app_read_only, app_writer_limited, DBA_audit, Compliance_reader.
- Grant least privilege following privilege separation: app roles limited to specific schemas/stored procedures; DBAs get audit-only unless emergency.
- Row-Level Security (RLS) & data access policies
- Implement RLS (Postgres policies or equivalent) to restrict rows by tenant_id and user_id using session variables (SET LOCAL app.user_id) populated by trusted proxy.
- Use stored procedures/parameterized views for complex access rules; deny direct table access for app roles.
- Encryption
- In transit: enforce TLS 1.2+/mTLS; disable weak ciphers; HSTS for APIs.
- At rest: use disk-level encryption (cloud-managed CMEK preferred) + field-level encryption for sensitive columns (PII like SSN) using application-side encryption where DB-level encryption is insufficient.
- Key Management & rotation
- Use a KMS (AWS KMS, GCP KMS, HashiCorp Vault) with HSM-backed keys for CMEK and envelope encryption.
- Store DEKs encrypted by KMS; application retrieves DEK via short-lived KMS grant or Vault transit.
- Rotation policy: rotate DEKs quarterly or on suspected compromise; rotate KEKs (KMS keys) annually. Implement re-encryption job for rewrapping DEKs; keep key versions for decrypting old data until re-encryption completes.
- Audit logging & monitoring
- Enable immutable, tamper-evident audit logs (DB audit, cloud audit logs) shipping to centralized SIEM (Splunk/ELK) and WORM storage.
- Log: successful/failed auths, role grants, DDL, data access attempts (sensitive column access), changes to RLS/policies, key usage, admin sessions.
- Alerting: anomalous queries, access outside business hours, mass exports, privilege escalations.
Validation & testing
- Automated tests:
- Unit tests for application encryption/decryption.
- Integration tests validating RLS policies by simulating different user sessions.
- IaC tests verifying security groups, no public access.
- Penetration testing:
- Internal and third-party pentests: attempt privilege escalation, bypass RLS, man-in-the-middle TLS, DB misconfig.
- Red team & tabletop:
- Simulate compromised app server to validate lateral movement controls and key access limits.
- Chaos & fault tests:
- Rotate keys in staging to validate re-encryption, failover with rotated keys.
- Audit verification:
- Periodic review of audit logs, compare privileged actions to ticketing/approval records.
- Compliance checks:
- Automated policy-as-code (Open Policy Agent, CIS benchmarks) and scheduled compliance scans.
- Metrics & continuous monitoring:
- Track failed auths, unusual query patterns, key usage spikes; feed into SOAR runbooks.
Operational controls & processes
- Emergency access (break-glass) with multi-approver workflow, time-limited sessions and recorded activity.
- Change control: all schema/RLS changes via PRs, code review, automated tests, and staging rollout.
- Documentation & training for devs on encryption APIs, RLS usage, and least-privilege practices.
Trade-offs
- Field-level app-side encryption increases complexity (searchability, indexing) — mitigate with deterministic tokens/hashing for lookups and searchable encryption patterns where needed.
This plan delivers layered defenses, least-privilege access, auditable key lifecycle, and a validation strategy combining automated tests, pentests, and operational controls.
Unlock Full Question Bank
Get access to all 6 Database Administration and Operations interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.