国外设计欣赏网站 - DOOOOR.com

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,微信登陆

搜索

[Drupal优化/SEO/环境] 在Drupal的数据库层应用MySQL Master/Slave

[复制链接]
发表于 4-20-2012 21:42 | 显示全部楼层 |阅读模式

众所周知,MySQL的master/slave模式对于提高数据库访问层的性能是非常有效的,本文就在Drupal中如何应用mysql当master/slave做一下简单介绍。


默认情况下Drupal6并不支持master/slave结构,即使是Drupal的Pressflow版本,也是只提供相关函数,并不能把已有的db_query定向到slave数据库,因此有必要在drupal到query机制中加入router的功能。


根据Drupal.org上面这篇文章的讨论,笔者总结了一下,并作了相应的改良,http://drupal.org/node/469274


比如sql过滤中会出现过滤掉某些字段中含有update的字段,此外由于主从数据库的延迟问题,我们需要一个锁定到master数据库的机制,所以添加了一个函数用于锁定主数据库。


首先,修改settings.php,添加default和readonly数据库的设置。


25 o+ V$ H; V1 [& A7 \: \' R
39 Y* E* a! o9 U+ m* P
$db_url['default'] = 'mysql://username:password@localhost/databasename';* e! [* h: m9 c; n
$db_url['readonly'] = 'mysql://username:password@localhost/databasename';

其次,修改和添加如下代码在/includes/database.mysql-common.inc 中,


注意:

1. db_query是修改drupal核心。

2. db_lock_master是保持db一直锁定在master数据库上。(不同步的情况下使用,有时我们不能保证主从完全同步,就需要一直在master上操作,比如Drupal的核心函数user_save/node_save,在保存之后立即load一个对象,这种情况主从没有同步导致莫名其妙的数据bug,笔者以前在项目中经常遇到,大家多注意)。


50
! |' o& Q+ s5 m8 j+ e8 r. C514 R, C: W: ]4 X$ w
52
, U& G7 c9 j0 d5 D53
& @+ o% z' Z5 r5 S* h) m: d54
$ T  M: h3 x( n4 H- H6 G) R, C55' Y: ~  O' I" @1 Z* R2 `0 x
56' `; o7 H4 @  ^
57" q; Z" f7 P, |) O0 p% p1 A
58
1 r9 v8 }$ {4 z0 ?' g- y8 Q6 O59
4 Z3 X. a* _8 Z4 f, F* i60  K$ a" X8 G4 Q8 W0 f% B
61
* s* |8 f! u, k' \1 R9 @620 C) {: n1 U1 P. R( w
63
, x9 x, n8 t/ R# S& j0 }64
: N1 P. j0 `/ I8 ~6 f& V65
/ t2 R. w/ P# u. c( Z* G7 Z, C66- L: j- u5 Q# Z* H
67
7 g7 R6 Q; _  ^' ]5 \& P; M68
1 q; s4 i( ~3 C2 O4 k/ V697 E3 R2 l6 p# K! V; v% \
703 e0 k1 G7 M$ N# ?9 K8 J# T8 y
71
. ~8 T2 }7 t. U5 j; y0 J72. S  ?0 I* `: }, _+ ^# _
732 q( Y, Z% [9 N. y
749 k- u2 S4 x& t7 k. V
75
- _2 k- F+ w7 ]0 z5 M7 U$ F; i" b764 q2 f# v4 V+ W; i2 [  \
77
. M7 m5 i6 }4 S: C1 K78! L3 w( Z, w1 U# _7 T, |4 e5 L
799 O/ B1 X% i/ l# R  P
806 y8 z1 U. s. i  i: q7 p
81
/ F; q4 E0 |) J' C; p8 ~* d" V" V829 v) p- Y( u1 e" T
83! ]( Z: ]2 y2 {3 {# f
84; z8 Z% Z& u' P7 B( g7 y: Q% ?
85* D% N- s- b% h9 d- ?
86
$ ~2 b3 d/ i( J0 K; J# K874 F" M9 ?; U* X
88
) s: e9 l7 x8 M9 ^% Q894 L9 v4 m) m  v" d
90
, t0 R& {; ?/ ^3 O91
. Z# V  I/ o5 j. G& Q92
# U/ t* _8 O9 P$ \! j93
3 A& l8 \, W6 D; p7 p# |$ G( F94  i8 i; f6 l( s# H1 l
95
$ m, T& T3 a6 |! ^, u6 p1 k96% a( Z* N; L+ M$ w* h/ s
97
" I! P+ }) ^3 W; N: m98
% ?0 y0 M  [: {* e  e; X99
  V! D, @5 Q' e% S
function db_query($query) {; W1 s: S+ V2 q2 C. b) J% T
  $args = func_get_args();4 A- ^5 j! j5 b3 R9 @
  array_shift($args);
/ v) l2 W, D3 M, K6 Q6 H8 G  $query = db_prefix_tables($query);  e; R" }" G( t% {+ P
  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax( z& V5 ]6 u: H' M% t" M
    $args = $args[0];7 g( c; f% g# N( v0 f: v1 S5 r( V
  }! J5 l, g. V( Q
  _db_query_callback($args, TRUE);# S2 N9 h+ q2 k
  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);& B9 c0 w! i- [8 k2 `7 `( H
 9 x3 w0 m! l  f
  /*
# Q5 u% C8 l) Z; W* C6 I   * Integrating multiple read/write databases! g. G  B; Q# t. c5 K& _( s5 J
   */4 G" i6 _: x3 L$ \% v, D' U
  if(!db_lock_master() && strpos(strtolower($query), "select") === 0 && strpos(strtolower($query), "last_insert_id") === FALSE){8 k+ R0 ?; Y, Y$ v
    $commits   = array('alter', 'insert', 'update', 'delete', 'flush', 'lock','create');0 i$ E  X9 T6 J7 B- K, D! _
    $is_commit = false;
: C! q: t; H$ \& G. P9 D, \    foreach($commits as $type) {8 ]+ j7 b9 ]: h4 G& _( w2 s/ Q
      if((strpos(strtolower($query), "$type "))){//[insert|update|create] xxxx, need a space, otherwise, some field which is like 'user_updated' will be filter as commits3 I% B1 @. o/ o) o# ^3 o
        $is_commit = true;
3 w* f$ p7 {% t3 {: R1 i* _      }& r$ M0 o, c& B- w1 W5 A
    }
* O% ^7 W4 J5 [. v3 h 
9 W; N+ c' A1 d+ E7 j7 s, U    if($is_commit){# ~8 C8 M- y( R. q2 C
      db_set_active('default');
* m0 |( Q9 y  [6 \  {# t      //drupal_set_message('default');. [3 U2 E2 e/ s  d
    } else{
& H; c( y8 P8 ]. W; J7 N      db_set_active('readonly');
% y) E( |' X6 {& j- q  [      //drupal_set_message('readonly');" |5 @1 W7 J0 ]  t- F8 t9 c5 t
    }6 N) ?4 a# ?! Y' n! j4 f" B7 L
  }8 A3 _! D7 L! M& u) u
  else {
4 M. k: ~$ J) b2 N    db_set_active('default');2 F& B  r  t5 I+ k& r. F+ E
  }% r2 o) e. \6 z" J' O/ L) A* I3 t
  /*
8 C  p6 `# q! l, Y' j- X   * End read/write router
, s/ D0 U& H  L6 K  n& W. i7 O  Y( H   */9 l( N! x/ n2 g5 w# Q7 Q1 c8 m: ~
 
5 d0 z8 B' M, R8 ]  B+ I7 B  return _db_query($query);
' B5 F/ D! O4 O# _5 E) `# V: \}
- J- x, |1 T& [: t 4 F; H1 G+ t; }5 J# D
function db_lock_master($lock = null) {% T! I7 e2 J5 E* n, e# C
  static $lock_master = false;
2 h# C% E: g- ]) \4 c: E  U  if (is_null($lock)) {
' p( t+ M& e0 O    return $lock_master;# m+ |4 |& s9 x2 ^( V
  }
5 Y& ^4 [$ b" X6 g+ f- [$ l0 r- C- s) O  else {
4 c! b7 A4 G' r/ K. k" L' T    $lock_master = $lock;
' f5 C" ^* b: n+ H3 }" t    return $lock_master;
+ P- h; p5 w- N) n, W  p: U  }. Y% R/ t* s/ k
}

最后,该代码只能支持一个slave数据库,如果我们有多个slave db,那么有两个办法。

1. 修改上面到php代码,在应用slave db的代码中,再用一个函数分配slave数据库。

2. 用haproxy做一个mysql db代理。参考这篇文章 http://www.oschina.net/question/17_4131


参考文章

Using multiple slave MySQL databases as ‘read only’ DBs

How does Drupal.org split MySQL read/write queries to a master/slave




声明: 本站所有文章欢迎转载,所有文章未说明,均属于原创,转载均请注明出处。 

本文有效链接: http://www.drupal001.com/2011/09/drupal-mysql-master-slave/ 

版权所有: Drupal与高性能网站架构 http://www.drupal001.com

|2011-2026-版权声明|平台(网站)公约|手机版|手机版|DOOOOR 设计网 ( 吉ICP备2022003869号 )

GMT+8, 11-12-2025 17:06 , Processed in 0.320839 second(s), 75 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表