Skip to content

Database Schema

Complete reference for the Admin Audit Trail database schema.

Overview

Admin Audit Trail stores all log entries in a single database table: admin_audit_trail.

Key characteristics: - Single table design for simplicity - Indexed for performance - Supports both numeric and character references - Stores timestamps as Unix timestamps - Text field for descriptions (supports HTML)

Table Structure

admin_audit_trail

Table name: admin_audit_trail

Description: Logged events by the admin_audit_trail module

Storage engine: InnoDB (default for Drupal)

Character set: utf8mb4 (supports full Unicode)

Schema Definition

$schema['admin_audit_trail'] = [
  'description' => 'Logged events by the admin_audit_trail module.',
  'fields' => [
    'lid' => [
      'description' => 'Log id.',
      'type' => 'serial',
      'not null' => TRUE,
    ],
    'type' => [
      'description' => 'Event handler type.',
      'type' => 'varchar',
      'length' => '50',
      'not null' => TRUE,
    ],
    'operation' => [
      'description' => 'The operation performed.',
      'type' => 'varchar',
      'length' => '50',
      'not null' => TRUE,
    ],
    'path' => [
      'type' => 'varchar',
      'length' => '255',
      'not null' => TRUE,
      'default' => '',
      'description' => 'Current path.',
    ],
    'ref_numeric' => [
      'description' => 'A numeric value that can be used to reference an object.',
      'type' => 'int',
      'not null' => FALSE,
    ],
    'ref_char' => [
      'description' => 'A character value that can be used to reference an object.',
      'type' => 'varchar',
      'length' => '255',
      'not null' => FALSE,
    ],
    'description' => [
      'description' => 'Description of the event, in HTML.',
      'type' => 'text',
      'size' => 'medium',
      'not null' => TRUE,
    ],
    'uid' => [
      'description' => 'User id that triggered this event (0 = anonymous user).',
      'type' => 'int',
      'not null' => TRUE,
    ],
    'ip' => [
      'description' => 'IP address of the visitor that triggered this event.',
      'type' => 'varchar',
      'length' => '255',
      'not null' => FALSE,
    ],
    'created' => [
      'description' => 'The event timestamp.',
      'type' => 'int',
      'not null' => TRUE,
    ],
  ],
  'primary key' => ['lid'],
  'indexes' => [
    'created' => ['created'],
    'user' => ['uid', 'ip'],
    'ip' => ['ip'],
    'join' => ['type', 'operation', 'ref_numeric', 'ref_char'],
  ],
];

Field Definitions

lid (Primary Key)

Type: Serial (Auto-increment integer) NULL: NOT NULL Description: Unique log entry identifier

Characteristics: - Auto-incremented on insert - Primary key for the table - Uniquely identifies each log entry - Never reused even after deletion

Example values: 1, 2, 3, 4, 5...

SQL Type: INT AUTO_INCREMENT


type

Type: VARCHAR(50) NULL: NOT NULL Description: Event handler type (usually the entity type)

Purpose: Categorizes the log entry by entity or event type

Common values: - node - Content entities - user - User accounts - taxonomy_term - Taxonomy terms - media - Media entities - file - File entities - menu_link_content - Menu links - comment - Comments - workflow - Workflow transitions - custom_form - Custom form submissions

Indexed: Yes (as part of join composite index)

Max length: 50 characters

Example SQL:

SELECT DISTINCT type FROM admin_audit_trail;


operation

Type: VARCHAR(50) NULL: NOT NULL Description: The operation/action performed

Purpose: Describes what action was taken

Common values: - insert - Entity created - update - Entity updated - delete - Entity deleted - login - User logged in - logout - User logged out - login_failed - Failed login attempt - password_reset - Password reset requested - state_change - Workflow state transition - role_add - Role added to user - role_remove - Role removed from user

Indexed: Yes (as part of join composite index)

Max length: 50 characters

Example SQL:

SELECT operation, COUNT(*) as count
FROM admin_audit_trail
GROUP BY operation
ORDER BY count DESC;


path

Type: VARCHAR(255) NULL: NOT NULL Default: '' (empty string) Description: Current path where the event occurred

Purpose: Records the URL path where the action was performed

Example values: - /node/123/edit - /user/5/edit - /admin/structure/menu/manage/main/add - /taxonomy/term/10/edit

Max length: 255 characters

Use cases: - Determine where actions were performed - Identify problematic pages - Track administrative interface usage


ref_numeric

Type: INT NULL: NULL (optional) Description: Numeric reference value (typically entity ID)

Purpose: Links the log entry to a specific entity by ID

Common uses: - Node ID (nid) - User ID (uid) - Term ID (tid) - Media ID (mid) - Any numeric entity identifier

Indexed: Yes (as part of join composite index)

Example values: 123, 456, 789

SQL Type: INT(11) (signed integer)

Example queries:

-- Find all logs for node ID 123
SELECT * FROM admin_audit_trail
WHERE type = 'node' AND ref_numeric = 123
ORDER BY created DESC;

-- Find most frequently modified entities
SELECT ref_numeric, COUNT(*) as changes
FROM admin_audit_trail
WHERE type = 'node' AND operation = 'update'
GROUP BY ref_numeric
ORDER BY changes DESC
LIMIT 10;


ref_char

Type: VARCHAR(255) NULL: NULL (optional) Description: Character reference value

Purpose: Provides additional context or alternative reference

Common uses: - Entity bundle name (e.g., 'article', 'page') - Machine names (e.g., 'main-menu') - UUIDs - String identifiers - Custom categorization

Indexed: Yes (as part of join composite index)

Max length: 255 characters

Example values: - article - page - main - dept_5 - product_electronics

Example queries:

-- Count logs by bundle
SELECT ref_char as bundle, COUNT(*) as count
FROM admin_audit_trail
WHERE type = 'node'
GROUP BY ref_char
ORDER BY count DESC;


description

Type: TEXT (MEDIUMTEXT) NULL: NOT NULL Description: Human-readable description of the event

Purpose: Provides detailed, human-readable information about what happened

Characteristics: - Supports HTML content - Medium text size (16MB max) - Should be translatable (use t() function) - May contain variable substitutions

Max size: 16,777,215 characters (16MB)

Example values:

Created article "How to Install Drupal"
Updated user john.doe - Changed email to john@example.com
Deleted taxonomy term "Obsolete Category"
User admin logged in successfully
Failed login attempt for user: admin

Best practices: - Use t() for translation support - Include key details (entity label, changed fields) - Be concise but informative - Avoid sensitive data (passwords, API keys)


uid

Type: INT NULL: NOT NULL Description: User ID that triggered the event

Purpose: Identifies which user performed the action

Special values: - 0 - Anonymous user - 1 - Admin/root user - >1 - Regular users

Indexed: Yes (as part of user composite index)

Foreign key: Links to users.uid (not enforced at database level)

Auto-filled: Yes (current user if not provided)

Example queries:

-- Find all actions by user ID 3
SELECT * FROM admin_audit_trail
WHERE uid = 3
ORDER BY created DESC;

-- Count actions per user
SELECT u.name, COUNT(*) as actions
FROM admin_audit_trail a
LEFT JOIN users_field_data u ON a.uid = u.uid
GROUP BY a.uid, u.name
ORDER BY actions DESC
LIMIT 10;

-- Find anonymous user actions
SELECT * FROM admin_audit_trail
WHERE uid = 0;


ip

Type: VARCHAR(255) NULL: NULL (optional) Description: IP address of the visitor

Purpose: Records the client IP address for security tracking

Supports: - IPv4 addresses (e.g., 192.168.1.1) - IPv6 addresses (e.g., 2001:0db8:85a3:0000:0000:8a2e:0370:7334) - Proxy headers (X-Forwarded-For)

Indexed: Yes (both standalone and as part of user composite index)

Max length: 255 characters

Auto-filled: Yes (from request)

Privacy note: May be considered PII under GDPR/privacy laws

Example queries:

-- Find actions from specific IP
SELECT * FROM admin_audit_trail
WHERE ip = '192.168.1.50'
ORDER BY created DESC;

-- Find users with multiple IPs (possible security concern)
SELECT uid, COUNT(DISTINCT ip) as ip_count
FROM admin_audit_trail
GROUP BY uid
HAVING ip_count > 5
ORDER BY ip_count DESC;

-- Find unusual IP patterns
SELECT ip, COUNT(*) as attempts
FROM admin_audit_trail
WHERE operation = 'login_failed'
GROUP BY ip
HAVING attempts > 10
ORDER BY attempts DESC;


created

Type: INT NULL: NOT NULL Description: Unix timestamp when the event occurred

Purpose: Records when the action was performed

Format: Unix timestamp (seconds since 1970-01-01 00:00:00 UTC)

Indexed: Yes (standalone index)

Auto-filled: Yes (current time if not provided)

Example values: 1705324800 (2024-01-15 12:00:00 UTC)

Example queries:

-- Recent logs (last 24 hours)
SELECT * FROM admin_audit_trail
WHERE created > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 24 HOUR))
ORDER BY created DESC;

-- Logs from specific date
SELECT * FROM admin_audit_trail
WHERE created BETWEEN UNIX_TIMESTAMP('2024-01-01') AND UNIX_TIMESTAMP('2024-01-31 23:59:59')
ORDER BY created DESC;

-- Logs per day (last 30 days)
SELECT DATE(FROM_UNIXTIME(created)) as date, COUNT(*) as count
FROM admin_audit_trail
WHERE created > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))
GROUP BY date
ORDER BY date DESC;

-- Convert to human-readable
SELECT lid, FROM_UNIXTIME(created) as datetime, description
FROM admin_audit_trail
ORDER BY created DESC
LIMIT 10;

Indexes

Primary Key: lid

Type: Primary Key Fields: lid

Purpose: Unique identifier for each log entry

Characteristics: - Automatically indexed - Ensures uniqueness - Used for direct lookups


Index: created

Type: Single-column index Fields: created

Purpose: Optimize date-based queries

Benefits: - Fast filtering by date ranges - Efficient ORDER BY created - Quick recent log retrieval

Optimized queries:

WHERE created > X
WHERE created BETWEEN X AND Y
ORDER BY created DESC


Index: user

Type: Composite index Fields: uid, ip

Purpose: Optimize user-based and IP-based queries

Benefits: - Fast user activity lookups - Efficient IP-based filtering - Combined user+IP queries

Optimized queries:

WHERE uid = X
WHERE ip = 'X.X.X.X'
WHERE uid = X AND ip = 'X.X.X.X'


Index: ip

Type: Single-column index Fields: ip

Purpose: Optimize IP address lookups

Benefits: - Security monitoring - Brute force detection - Geographic analysis

Optimized queries:

WHERE ip = 'X.X.X.X'
GROUP BY ip


Index: join

Type: Composite index Fields: type, operation, ref_numeric, ref_char

Purpose: Optimize filtered queries and joins

Benefits: - Fast type+operation filtering - Entity reference lookups - Complex filtering queries

Optimized queries:

WHERE type = 'node' AND operation = 'delete'
WHERE type = 'node' AND ref_numeric = 123
WHERE type = 'node' AND operation = 'update' AND ref_char = 'article'

Example Queries

Basic Queries

Get all logs:

SELECT * FROM admin_audit_trail
ORDER BY created DESC
LIMIT 100;

Count total logs:

SELECT COUNT(*) FROM admin_audit_trail;

Table size:

SELECT
  table_name,
  table_rows,
  ROUND(((data_length + index_length) / 1024 / 1024), 2) AS 'Size (MB)'
FROM information_schema.TABLES
WHERE table_name = 'admin_audit_trail';

Advanced Queries

Logs with user information:

SELECT
  a.lid,
  a.type,
  a.operation,
  a.description,
  u.name as username,
  u.mail as email,
  FROM_UNIXTIME(a.created) as datetime,
  a.ip
FROM admin_audit_trail a
LEFT JOIN users_field_data u ON a.uid = u.uid
ORDER BY a.created DESC
LIMIT 50;

Daily activity summary:

SELECT
  DATE(FROM_UNIXTIME(created)) as date,
  COUNT(*) as total_events,
  COUNT(DISTINCT uid) as unique_users,
  COUNT(DISTINCT ip) as unique_ips
FROM admin_audit_trail
WHERE created > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))
GROUP BY date
ORDER BY date DESC;

Most active users:

SELECT
  u.name,
  COUNT(*) as actions,
  MIN(FROM_UNIXTIME(a.created)) as first_action,
  MAX(FROM_UNIXTIME(a.created)) as last_action
FROM admin_audit_trail a
LEFT JOIN users_field_data u ON a.uid = u.uid
GROUP BY a.uid, u.name
ORDER BY actions DESC
LIMIT 20;

Maintenance

Cleanup Old Logs

-- Delete logs older than 90 days
DELETE FROM admin_audit_trail
WHERE created < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 90 DAY));

Optimize Table

OPTIMIZE TABLE admin_audit_trail;

Analyze Table

ANALYZE TABLE admin_audit_trail;

Next Steps