]>
Commit | Line | Data |
---|---|---|
a2a898e8 ER |
1 | Replication patch from |
2 | http://cvs.drupal.org/viewcvs/drupal/contributions/sandbox/crackerjm/replication/ | |
3 | ||
4 | --- /dev/null 2005-02-16 21:06:48.000000000 +0200 | |
5 | +++ ./README.replication 2005-08-15 16:08:52.000000000 +0300 | |
6 | @@ -0,0 +1,34 @@ | |
7 | + | |
8 | +This README.txt and patch are for Mysql Replication. This assumes that you have | |
9 | +a master replication server and slave server(s) up and running already. If | |
10 | +you don't, then there is no purpose for reading this. If you need help for | |
11 | +replication, please read this link. | |
12 | + http://dev.mysql.com/doc/mysql/en/Replication.html | |
13 | + | |
14 | +NOTE: This is meant for drupal 4.6.0 | |
15 | + | |
16 | +Now, in includes/conf.php you have a line that looks simalar to this | |
17 | + $db_url = "mysql://username:password@localhost/database"; | |
18 | +Comment at the line so that it looks like this | |
19 | + //$db_url = "mysql://username:password@localhost/database"; | |
20 | + | |
21 | +Add the following lines below it to look like this: | |
22 | + $db_url = array(); | |
23 | + $db_url['default'] = "mysql://username:password@localhost/database"; | |
24 | + $db_url['slave1'] = "mysql://username:password@host/database"; | |
25 | + //$db_url['slave2'] = "mysql://username:password@host/database"; | |
26 | + | |
27 | +The 'default' is your MASTER server, the slaves are just that. make | |
28 | +sure that you have added the appropriate users to the servers so that | |
29 | +if you are using round robin DNS or something to that effect, that | |
30 | +way you don't end up with permission denied. | |
31 | + | |
32 | +patch your code with replication.patch and there ya go | |
33 | + | |
34 | +*********** | |
35 | +NEW: This revision of code supports the dead slave servers! | |
36 | + caveat though, if ALL of your slaves are dead, then you will | |
37 | + end up in a infinitely recursive loop searching for slave servers. | |
38 | + Hopefully in the next revision of this, I will try to come up with | |
39 | + a way to stop this recursion without the use of flags. | |
40 | +*********** | |
41 | diff -urN drupal-4.6.0/includes/database.inc drupal-test/includes/database.inc | |
42 | --- drupal-4.6.0/includes/database.inc 2005-04-08 09:24:10.000000000 -0500 | |
43 | +++ drupal-test/includes/database.inc 2005-05-29 09:30:18.710563836 -0500 | |
44 | @@ -119,11 +119,98 @@ | |
45 | die('Unsupported database type'); | |
46 | } | |
47 | ||
48 | - $db_conns[$name] = db_connect($connect_url); | |
49 | - | |
50 | + if($name == 'default') { | |
51 | + // die on failure | |
52 | + $db_conns[$name] = db_connect($connect_url, true); | |
53 | + } | |
54 | + else { | |
55 | + $db_conns[$name] = db_connect($connect_url); | |
56 | + } | |
57 | + | |
58 | } | |
59 | // Set the active connection. | |
60 | - $active_db = $db_conns[$name]; | |
61 | + if($name != 'default' && $db_conns[$name] === false){ | |
62 | + print "Bad slave, killing $name\n"; | |
63 | + db_find_slave(true); // kill bad slave | |
64 | + db_set_active(db_find_slave()); | |
65 | + } | |
66 | + else { | |
67 | + $active_db = $db_conns[$name]; | |
68 | + } | |
69 | +} | |
70 | + | |
71 | +function _is_commit($query) { | |
72 | + $commits = array('insert', 'alter', 'update', 'delete', 'flush', 'lock'); | |
73 | + foreach($commits as $type) { | |
74 | + if(preg_match("/^$type/i", $query)) { | |
75 | + return true; | |
76 | + } | |
77 | + } | |
78 | + return false; | |
79 | +} | |
80 | + | |
81 | +function db_find_slave($killslave = false) { | |
82 | + global $db_url; | |
83 | + static $slave ; | |
84 | + | |
85 | + if(!_replication_ready()) | |
86 | + return 'default'; | |
87 | + | |
88 | + if(!is_array($slave)){ | |
89 | + $slave = array(); | |
90 | + // initialize a local copy | |
91 | + foreach($db_url as $key=>$value) { | |
92 | + if(stristr($key, 'slave')) { | |
93 | + $slave[] = $key; | |
94 | + } | |
95 | + } | |
96 | + /** | |
97 | + * Since this is the first iteration of the loop, we reset the array to | |
98 | + * ensure we return the first element. | |
99 | + */ | |
100 | + return reset($slave); | |
101 | + } | |
102 | + | |
103 | + if(empty($slave)) { | |
104 | + return 'default'; | |
105 | + } | |
106 | + | |
107 | + // Failed to connect, remove from the list | |
108 | + if($killslave){ | |
109 | + array_shift($slave); | |
110 | + } | |
111 | + | |
112 | + $url = next($slave); | |
113 | + | |
114 | + if($url === false){ | |
115 | + // walked past of the end of the array, start over at first element | |
116 | + $url = reset($slave); | |
117 | + } | |
118 | + | |
119 | + return $url; | |
120 | +} | |
121 | + | |
122 | +function _replication_ready() { | |
123 | + global $db_url; | |
124 | + static $ready; | |
125 | + | |
126 | + if(isset($ready)) { | |
127 | + return $ready; | |
128 | + } | |
129 | + | |
130 | + if(is_array($db_url)) { | |
131 | + foreach($db_url as $key=>$value) { | |
132 | + if(stristr($key, 'slave')) { | |
133 | + // Found at least ONE element with the word slave in it | |
134 | + // break the search to save on cycles | |
135 | + $ready = true; | |
136 | + return true; | |
137 | + } | |
138 | + } | |
139 | + } | |
140 | + | |
141 | + $ready = false; | |
142 | + return false; | |
143 | } | |
144 | ||
145 | /** | |
146 | diff -urN drupal-4.6.0/includes/database.mysql.inc drupal-test/includes/database.mysql.inc | |
147 | --- drupal-4.6.0/includes/database.mysql.inc 2005-04-14 13:50:23.000000000 -0500 | |
148 | +++ drupal-test/includes/database.mysql.inc 2005-05-29 09:28:22.490546558 -0500 | |
149 | @@ -20,7 +20,7 @@ | |
150 | * performance, however, when the overhead to connect to your database is high | |
151 | * (e.g. your database and web server live on different machines). | |
152 | */ | |
153 | -function db_connect($url) { | |
154 | +function db_connect($url, $critical = false) { | |
155 | $url = parse_url($url); | |
156 | ||
157 | // Allow for non-standard MySQL port. | |
158 | @@ -28,10 +28,16 @@ | |
159 | $url['host'] = $url['host'] .':'. $url['port']; | |
160 | } | |
161 | ||
162 | - $connection = mysql_connect($url['host'], $url['user'], $url['pass'], TRUE) or die(mysql_error()); | |
163 | - mysql_select_db(substr($url['path'], 1)) or die('unable to select database'); | |
164 | + // For replication setups, we will assume that dieing is bad | |
165 | + $connection = mysql_pconnect($url['host'], $url['user'], $url['pass'], TRUE); | |
166 | + if(!is_resource($connection) && $critical) { | |
167 | + die(mysql_error()); | |
168 | + } | |
169 | + // We die on bad slaves. These should be taken care of | |
170 | + // maybe hook this somehow or something | |
171 | + mysql_select_db(substr($url['path'], 1)) or die(mysql_error()); | |
172 | ||
173 | - return $connection; | |
174 | + return ($connection)?$connection:false; | |
175 | } | |
176 | ||
177 | /** | |
178 | @@ -40,14 +46,38 @@ | |
179 | function _db_query($query, $debug = 0) { | |
180 | global $active_db; | |
181 | global $queries; | |
182 | + global $db_url; | |
183 | ||
184 | if (variable_get('dev_query', 0)) { | |
185 | list($usec, $sec) = explode(' ', microtime()); | |
186 | $timer = (float)$usec + (float)$sec; | |
187 | } | |
188 | ||
189 | + /** | |
190 | + * If the db_url isn't an array, then we can assume that this server is not | |
191 | + * ready for a replication setup. This outer if is purely for a speed as | |
192 | + * calling PHP's builtin functions are way faster than user functions. | |
193 | + * So, if its an array and has more than one element, we shall atleast check | |
194 | + * to see if it's possibly ready for a replication enviorment. However, | |
195 | + * if no [slave#] elements are found, then we assume normal operations. | |
196 | + */ | |
197 | + if(is_array($db_url) && sizeof($db_url) > 1 && _replication_ready() ) | |
198 | + { | |
199 | + if (_is_commit($query) === true){ | |
200 | + db_set_active('default'); | |
201 | + } | |
202 | + else | |
203 | + { | |
204 | + // no checks as _replication_ready() verifies | |
205 | + // that there is atleast one slave | |
206 | + db_set_active(db_find_slave()); | |
207 | + } | |
208 | + } | |
209 | + | |
210 | + | |
211 | $result = mysql_query($query, $active_db); | |
212 | ||
213 | + | |
214 | if (variable_get('dev_query', 0)) { | |
215 | list($usec, $sec) = explode(' ', microtime()); | |
216 | $stop = (float)$usec + (float)$sec; | |
217 | @@ -67,6 +97,7 @@ | |
218 | } | |
219 | } | |
220 | ||
221 | + | |
222 | /** | |
223 | * Fetch one result row from the previous query as an object. | |
224 | * | |
225 | @@ -239,4 +270,4 @@ | |
226 | * @} End of "ingroup database". | |
227 | */ | |
228 | ||
229 | -?> | |
230 | \ No newline at end of file | |
231 | +?> | |
38ea02a6 ER |
232 | --- ./sites/default/settings.php~ 2005-08-15 16:41:07.000000000 +0300 |
233 | +++ ./sites/default/settings.php 2005-08-15 16:42:47.000000000 +0300 | |
234 | @@ -77,8 +77,15 @@ | |
235 | * Database URL format: | |
236 | * $db_url = 'mysql://username:password@localhost/database'; | |
237 | * $db_url = 'pgsql://username:password@localhost/database'; | |
238 | + * | |
239 | + * Database URL format with MySQL replication: | |
240 | + * $db_url = array(); | |
241 | + * $db_url['default'] = "mysql://username:password@localhost/database"; | |
242 | + * $db_url['slave1'] = "mysql://username:password@host/database"; | |
243 | */ | |
244 | -$db_url = 'mysql://username:password@localhost/database'; | |
245 | +$db_url = array(); | |
246 | +$db_url['default'] = 'mysql://mysql:@localhost/drupal'; | |
247 | +#$db_url['slave1'] = "mysql://mysql:@mysql-slave/drupal"; | |
248 | $db_prefix = ''; | |
249 | ||
250 | /** |