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

> Explore master-slave database replication in masterslave.func.php automatically sync users, route master DB access, and migrate data with three operational modes.

- Repository: [Nemo Ma/phpdts](https://github.com/amarillonmc/phpdts)
- Tags: how-to-guide
- Published: 2026-02-24

---

**The [`masterslave.func.php`](https://github.com/amarillonmc/phpdts/blob/main/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`](https://github.com/amarillonmc/phpdts/blob/main/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`](https://github.com/amarillonmc/phpdts/blob/main/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`](https://github.com/amarillonmc/phpdts/blob/main/config.inc.php) and instantiates a new `dbstuff` object using the `$master_dbhost`, `$master_dbuser`, `$master_dbpw`, `$master_dbname`, and `$master_tablepre` variables.

```php
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:

```php
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:

```php
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`](https://github.com/amarillonmc/phpdts/blob/main/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`](https://github.com/amarillonmc/phpdts/blob/main/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.