How Master-Slave Database Replication Works in masterslave.func.php

The masterslave.func.php file implements a configuration-driven master-slave database replication system for PHPDTS that enables automatic user synchronization, direct master database routing, and bidirectional data migration through three distinct operational modes controlled by the $slave_level variable.

PHPDTS (PHP Desktop Game System) relies on include/masterslave.func.php to maintain consistency across distributed game servers. This lightweight implementation allows individual servers to operate as slaves that pull user data from a master, bypass local databases entirely, or push local accounts back to remote masters via reverse migration.

Understanding the Three Slave Level Modes

The replication behavior is governed by the $slave_level integer defined in config.inc.php. This value determines how the current server instance interacts with the master database.

$slave_level Behavior
2 Slave Mode: Automatically pull and synchronize user data from the master when should_auto_sync() returns true.
3 Direct Master Mode: Bypass the local database and route all queries to the master when should_use_master_db() returns true.
-1 Reverse Migration Mode: Push local user data back to a remote master when is_reverse_migration_mode() is active.

Connecting to the Master Database

Before any synchronization occurs, the system establishes a dedicated connection to the master server. The connect_master_db() function (lines 16-31) reads credentials from config.inc.php and instantiates a new dbstuff object using the $master_dbhost, $master_dbuser, $master_dbpw, $master_dbname, and $master_tablepre variables.

function connect_master_db() {
    // Creates a new dbstuff instance using master credentials
    // Source: lines 16-31
}

This connection is used for all cross-server operations, ensuring the slave can query the ${master_tablepre}users table and related master data.

Pulling User Data from Master (Slave Mode)

When operating as a slave ($slave_level = 2), the system uses sync_user_from_master($username, $password, $target_username) (lines 61-138) to pull user accounts from the master database. This function performs a complete workflow:

  1. Connect to the master using connect_master_db().
  2. Validate credentials via check_user_in_master() (lines 38-55), which queries ${master_tablepre}users.
  3. Check existing mappings using get_user_sync_info() to prevent duplicate synchronization.
  4. Update or create the local user record:
    • If the local target exists: Update fields like credits and nick (lines 88-108).
    • If the local target does not exist: Insert a new record with full user data (lines 114-131).
  5. Persist the mapping in the user_sync table via set_user_sync_info() (lines 144-185).

The user_sync table, created lazily by create_sync_table_if_not_exists() (lines 190-212) in the gamedata/cache/ directory, stores the relationship between target_username (local) and master_username (remote) along with synchronization timestamps.

Reverse Migration (Slave to Master)

When $slave_level is set to -1, the server enters reverse migration mode, pushing local data upstream to a remote master. The reverse_migrate_user() function handles this bidirectional flow:

  1. Validate remote credentials on the target master.
  2. Update or insert the remote user record.
  3. Optionally migrate character data via reverse_migrate_game_data() (lines 151-207), which copies entries from the local players table to the remote master.
  4. Log the operation in the reverse_migration table using set_reverse_migration_info().

The reverse migration table is created on-demand by create_reverse_migration_table_if_not_exists() (lines 671-682).

Tracking Synchronization State

The system maintains two auxiliary tables to track cross-server relationships:

  • user_sync: Maps local usernames to master usernames and records the last synchronization timestamp.
  • reverse_migration: Stores mappings for data pushed from local servers back to remote masters.

Helper functions get_user_sync_status() and get_reverse_migration_status() provide metadata retrieval for monitoring replication health.

Practical Implementation Examples

Example 1: Automatic User Synchronization on Slave Server

When $slave_level = 2, implement automatic account mirroring after login:

require_once 'include/masterslave.func.php';

$username = 'player01';
$password = 'p@ssw0rd';

// Only executes sync if $slave_level == 2
if (should_auto_sync()) {
    $result = sync_user_from_master($username, $password);
    
    if ($result['success']) {
        echo "Synchronized: {$result['message']}";
    } else {
        echo "Sync failed: {$result['message']}";
    }
}

This call either updates the existing local account with master data or creates a new local record, preserving the mapping in user_sync.

Example 2: Pushing Local Data to Remote Master

For server migrations or consolidation using reverse migration mode:

require_once 'include/masterslave.func.php';

// Configure reverse migration in config.inc.php
// $slave_level = -1;

$localUser = 'localHero';
$remoteUser = 'remoteHero';
$remotePass = 'rem0tePass';

$push = reverse_migrate_user($localUser, $remoteUser, $remotePass);

if ($push['success']) {
    echo "Migrated: {$push['message']}";
    // Optionally migrate game character data
    reverse_migrate_game_data($localUser, $remoteUser);
} else {
    echo "Migration failed: {$push['message']}";
}

This validates the remote credentials, updates the master database, and logs the operation in reverse_migration.

Summary

  • masterslave.func.php provides lightweight master-slave replication for PHPDTS through three modes controlled by $slave_level.
  • Slave mode (2) pulls user data from master to local using sync_user_from_master(), maintaining mappings in the user_sync table.
  • Direct mode (3) routes queries directly to the master database, bypassing local storage via should_use_master_db().
  • Reverse mode (-1) pushes local data to remote masters using reverse_migrate_user() and tracks operations in reverse_migration.
  • Configuration resides in config.inc.php, defining master credentials and operational mode.

Frequently Asked Questions

How does PHPDTS determine whether to use the local or master database?

The system checks the $slave_level configuration variable. When set to 3, should_use_master_db() returns true and the application routes queries to the master connection returned by connect_master_db(). When set to 2, the server operates as a slave and pulls data locally while maintaining the master connection for synchronization.

What happens if a user already exists locally when syncing from master?

The sync_user_from_master() function detects existing accounts and performs an update rather than an insert. It preserves the local user ID while overwriting fields like credits, nick, and other profile data with values from the master record, then updates the user_sync mapping table to reflect the relationship.

Can character game data be migrated separately from user accounts?

Yes. While sync_user_from_master() handles account credentials and profile data, the reverse_migrate_game_data() function specifically migrates character data from the players table. This allows administrators to migrate active game sessions independently of user account information during reverse migration operations.

Where are the synchronization mappings stored?

The system creates two tables lazily: user_sync tracks master-to-slave relationships (created by create_sync_table_if_not_exists() at lines 190-212), while reverse_migration tracks slave-to-master push operations (created by create_reverse_migration_table_if_not_exists() at lines 671-682). Both tables typically reside in the gamedata/cache/ directory and store username mappings with timestamps.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →