Repository navigation
Expand file tree
/
Copy path01-read-write-splitting.php
More file actions
148 lines (114 loc) · 4.63 KB
/
Copy path01-read-write-splitting.php
File metadata and controls
148 lines (114 loc) · 4.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<?php
/**
* Basic Read/Write Splitting Setup Example
*
* This example demonstrates how to set up and use read/write connection splitting
* to distribute database load across master and replica servers.
*/
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/../helpers.php';
use tommyknocker\pdodb\PdoDb;
use tommyknocker\pdodb\connection\loadbalancer\RoundRobinLoadBalancer;
$driverEnv = getenv('PDODB_DRIVER') ?: 'mysql';
$config = getExampleConfig();
$driver = $config['driver'] ?? $driverEnv;
// For SQLite, use a temporary file instead of :memory: for read/write splitting
if ($driver === 'sqlite') {
$config['path'] = sys_get_temp_dir() . '/pdodb_rw_test_' . uniqid() . '.db';
}
echo "=== Read/Write Splitting - Basic Setup ===\n\n";
// ========================================
// 1. Basic Setup with RoundRobin Load Balancer
// ========================================
echo "1. Setting up read/write splitting\n";
// Create initial database instance with write connection
$db = createPdoDbWithErrorHandling($driver, $config);
// Enable read/write splitting with round-robin load balancer
$db->enableReadWriteSplitting(new RoundRobinLoadBalancer());
// Add write connection (master) - using the default connection
$writeConfig = $config;
$writeConfig['driver'] = $driver;
$writeConfig['type'] = 'write';
$db->addConnection('write', $writeConfig);
// For demo purposes, use the same database but mark as read replicas
// In production, these would be actual replica servers
$readConfig1 = $config;
$readConfig1['driver'] = $driver;
$readConfig1['type'] = 'read';
$db->addConnection('read-1', $readConfig1);
$readConfig2 = $config;
$readConfig2['driver'] = $driver;
$readConfig2['type'] = 'read';
$db->addConnection('read-2', $readConfig2);
echo "✓ Configured 1 write master and 2 read replicas\n\n";
// ========================================
// 2. Create Test Table
// ========================================
echo "2. Creating test table\n";
// Create test table using fluent API (cross-dialect)
$schema = $db->schema();
$schema->dropTableIfExists('users_rw');
$schema->createTable('users_rw', [
'id' => $schema->primaryKey(),
'name' => $schema->string(255)->notNull(),
'email' => $schema->string(255)->notNull(),
'status' => $schema->string(50)->defaultValue('active'),
'created_at' => $schema->timestamp()->defaultExpression('CURRENT_TIMESTAMP'),
]);
echo "✓ Table created\n\n";
// ========================================
// 3. Automatic Read/Write Routing
// ========================================
echo "3. Testing automatic routing\n";
// INSERT goes to write master automatically
$userId = $db->find()
->table('users_rw')
->insert([
'name' => 'John Doe',
'email' => 'john@example.com',
]);
echo "✓ INSERT (routed to master): User ID = $userId\n";
// SELECT goes to read replica automatically
$users = $db->find()
->from('users_rw')
->get();
echo "✓ SELECT (routed to replica): Found " . count($users) . " users\n";
// UPDATE goes to write master automatically
$affected = $db->find()
->table('users_rw')
->where('id', $userId)
->update(['status' => 'inactive']);
echo "✓ UPDATE (routed to master): Affected $affected rows\n\n";
// ========================================
// 4. Force Write Mode for SELECTs
// ========================================
echo "4. Testing forceWrite() for SELECT queries\n";
// Sometimes you need to read from master (e.g., after a write)
$user = $db->find()
->from('users_rw')
->forceWrite() // Force this SELECT to use master
->where('id', $userId)
->getOne();
echo "✓ SELECT with forceWrite() (routed to master): User = " . $user['name'] . "\n\n";
// ========================================
// 5. Connection Router Info
// ========================================
echo "5. Connection router information\n";
$router = $db->getConnectionRouter();
echo "Write connections: " . count($router->getWriteConnections()) . "\n";
echo "Read connections: " . count($router->getReadConnections()) . "\n";
echo "Sticky writes enabled: " . ($router->isStickyWritesEnabled() ? 'Yes' : 'No') . "\n";
echo "Force write mode: " . ($router->isForceWriteMode() ? 'Yes' : 'No') . "\n\n";
// ========================================
// 6. Cleanup
// ========================================
echo "6. Cleanup\n";
$schema->dropTableIfExists('users_rw');
echo "✓ Test table dropped\n";
// Clean up SQLite temp file
if ($driver === 'sqlite' && isset($config['path']) && file_exists($config['path'])) {
unlink($config['path']);
echo "✓ Temporary SQLite file removed\n";
}
echo "\n=== Example completed successfully ===\n";