国外设计欣赏网站 - 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数据库的设置。


2
9 h( o; [" @1 c: t3 d( f! v3
$ P, r. }8 |) g: G5 P1 Y3 N; K7 p
$db_url['default'] = 'mysql://username:password@localhost/databasename';% V% p" ]7 U3 w: d5 m4 l  \  k
$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
: w. |) G5 t. s51
% Z: e( o- E+ H1 t; f52+ P3 \5 ^4 G( M) w2 i  }4 ^  ?# o
53
+ {2 ]7 M/ h; u+ K0 y54* q2 a( Z5 r% J7 M5 X3 C
55
6 E% v% W/ I# j9 [& f+ @56/ h1 f# ~- f: @: Z# U6 k
57
4 B- e+ i) L7 k% I58
  u+ v8 o% Y1 t0 J& _, y59
: ~7 X4 N) d( `; r. U60& d/ }/ R( s( q+ E! R4 l
61
2 C6 @5 a4 E# L0 A! f5 N% |6 k- H62  o7 J6 L. k1 J2 U0 r
634 [' u5 c1 R- J1 U# E- }2 ]: {
64) q3 S; q7 ^8 z4 w7 g4 Q
65; I! A+ e4 g  P7 U& X; @7 R4 O
66" J! o0 b/ M0 i2 T: L" J: M+ p
67
- S8 ]& {+ ]6 ?' t68" f' I8 F6 m0 l0 o$ T0 t: F- I
69
. K! r( n" L5 ]) l+ z; V+ M* S4 r700 d5 j( r9 v) f$ o( R
711 n  z$ o' x7 b! X
72
+ D3 r9 l5 ~2 d2 d6 u5 p( G& F731 X8 L: h! U% \+ z. P
74) k; N7 {2 Y8 D9 g: A+ A2 c7 N  L, k
75
. a$ m! M& P/ r% b, k* h2 W761 Y, q/ z8 I- J  K' q
77: U" b( X2 a' _, V
78
5 c0 q/ x" M& b  v+ O) q79. Z' n( I3 `1 j* Y" E4 x
80
% l3 L! h, K$ O+ V8 s/ P  Q81, ~' Q/ x/ u. z  @& y- Y# c/ `
82
5 B4 M* l/ ^$ _0 Z1 _83
+ F  |/ s) V' M; H, h0 t- }6 R845 x1 s5 d# _) k9 `6 \
85' ?8 Q9 A5 ]% _0 z: o4 v0 [8 t
86  m8 X3 z$ j  a/ P+ g' I3 ]- }
87
) @4 V/ e. l, o, O88
6 W7 {, d0 J  k9 R5 D89
$ u; w  i+ C0 L2 J3 o8 W) c90% }9 b: S2 D5 w! C4 a, Z( ^
91$ J+ T. ^2 G( ^
92
8 B8 N, X0 a. A! @93
4 ^$ @0 D& X0 q' e$ a3 k4 t94
9 p! x# b* h9 j: R95
! b+ L$ W7 p) B+ H& ]- H+ s  Q96: M# W4 _& f4 {' s) l
97" p8 B2 G- `+ Z
98
1 r3 Q0 U  r1 p' U99+ }; u. F/ r4 A1 P  ~3 r  Y  ]5 g
function db_query($query) {7 S1 p2 Q& Z9 Y+ e: D. J
  $args = func_get_args();
; D- x. o& N5 k4 K2 v& I  array_shift($args);
. R* _5 I" a8 [6 z) E  `+ o  $query = db_prefix_tables($query);0 O8 Y8 [# g( v5 ?* w9 h
  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
/ A' F; O1 r: i  k( N    $args = $args[0];
$ J- }5 N0 _+ Q& [* q4 g( w  }
$ g' u5 h, g* V  _db_query_callback($args, TRUE);
" \1 Q( R% x% o  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);- c, A' x8 Z. u
 
7 Z- c% K+ Z( y& }, p4 X  /*
: c$ g1 p3 r4 h5 [; [# S   * Integrating multiple read/write databases) I0 s8 J8 b4 o; t, s
   */
- c" a, ], Q+ l4 m9 S$ j& F  if(!db_lock_master() && strpos(strtolower($query), "select") === 0 && strpos(strtolower($query), "last_insert_id") === FALSE){; d! s) y% t/ W! w1 z. @3 D& ^
    $commits   = array('alter', 'insert', 'update', 'delete', 'flush', 'lock','create');
1 o+ ]/ B: W- z# T( f: o    $is_commit = false;
! r$ z! Q/ W8 x7 |2 @( z9 a  S8 d    foreach($commits as $type) {" {: C& J# \4 r* }4 G7 b% P' S
      if((strpos(strtolower($query), "$type "))){//[insert|update|create] xxxx, need a space, otherwise, some field which is like 'user_updated' will be filter as commits4 J" p- w' u! S. u* `, O
        $is_commit = true;4 s( G. d, c* T
      }
0 p+ s6 g$ Q+ K! k) Q) ^    }
$ v- I( d6 v9 d $ A2 K1 Y5 \; J' C1 P' e
    if($is_commit){
6 S) U+ h- O: v' Y: N      db_set_active('default');3 p6 G1 i! g% s2 K# b- r
      //drupal_set_message('default');
3 f. X. O4 y( x    } else{
7 c! t% M2 V! F      db_set_active('readonly');% z! C  \5 ^0 q' _. `5 @9 w' m
      //drupal_set_message('readonly');
* \+ I7 n0 ]1 O7 j* q8 S, I    }
9 g! z' w/ V( u( Q. M* s/ v3 ?  }$ p" |4 H/ N4 p# j$ \! C3 M7 A: B/ w
  else {
6 \: I9 h# }' t' m- x7 I    db_set_active('default');- n- F6 r3 e7 [# A3 E
  }
) Y2 j7 E1 u% H3 I+ {$ K; E  /*; R, p5 [( T2 b
   * End read/write router0 U! Z+ i6 w+ K3 k! X
   */
, [' M9 c& }( [/ J ' [2 I3 j8 f$ s# n3 ]! }3 u
  return _db_query($query);
3 G; o4 d. h9 O+ m}( }+ W& F+ t1 Y0 E! W# V5 Y( i5 T
 
) u9 }" A6 @# \function db_lock_master($lock = null) {
5 X) }2 x) o* ^: i& M  static $lock_master = false;. Z9 R, B) l& ?" u9 `1 m
  if (is_null($lock)) {
2 O1 e8 J) W0 @7 e* t    return $lock_master;
$ O# A# D, `1 T0 D4 `  }  p" F: U7 |& z3 Z' C% s* ]3 l1 v
  else {5 R/ w1 U+ f/ F  i# v# ?
    $lock_master = $lock;
  P5 h' i; E9 {( Y+ l: J' `5 F1 x    return $lock_master;
1 I3 ?! V6 r( q" B% G' Y+ J  }
& R& A% ]6 x1 T. W, U, ~}

最后,该代码只能支持一个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, 2-21-2025 07:58 , Processed in 0.575214 second(s), 230 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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