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

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,微信登陆

搜索

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

[复制链接]
发表于 2-7-2012 03:11 | 显示全部楼层 |阅读模式

在数据库的架构方面,我们来讨论到MySQL的主从架构,即Master/Slave如何在Drupal中应用。

众所周知,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数据库的设置。

26 s5 @  `$ T. w5 Q* B2 f; r4 u
3: O% ^! ~. s+ u
$db_url['default'] = 'mysql://username:password@localhost/databasename';8 S+ N! t* r7 R1 h
$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
  f9 V6 I: A2 E2 ~/ u51
5 a( L2 a) m4 l7 T) z52# K$ u/ v" \/ h, N
538 L; v: b' l6 f  G- v
54
. W( P: \) o6 [2 k2 o4 _55
& H- r$ f. {( ]( A) ~( P; j569 ~. I" S% ]. j% M* m- C
577 J5 U" a; j/ m7 I. r+ E; e
58# z. m. Q2 ^: V$ X  d
59& f3 t) G% a+ N. t# U  a
60
' D* W+ s! Y! D* P8 F' X7 {618 h; C) E- T' ]% e3 p9 }
62# h! }$ n( k+ m. q+ \+ A
63( Y) M# r( M( z2 v+ S% H4 U
64* }, G+ |% o& ]6 J
65
: B: C$ `8 e! a1 W" ]. u0 E! R66' L- U# Z8 J4 }& V/ a1 H
67
: ~  t4 v9 |$ r) u3 F68
+ f& A. y/ S- K" C5 s69
4 Q1 w; y& Z4 s, \6 K5 T2 w70
1 T3 A0 O9 }3 \9 @# s3 D71
: x/ k% P0 G. `" V! l! l72/ L2 |6 v1 g3 w' [! d! t/ s
73
/ Z7 p* {8 y! A& f$ U' ^9 d74' {; I' Q7 t0 Z! Y+ Q$ S
756 j, D$ z+ j8 G- p. [; ^
768 a% A% i* M1 X0 q4 H7 W: p  ]
77' f: h1 P% @: L+ o+ Q$ B
78! }5 F& j) L% B. p9 S
79
# d* R2 O8 R1 c; k80
, e  g. M" L. i* L811 z( ]6 R+ e2 O# v; q
82
+ @& s# f( r7 _" l7 U; }+ I83
0 E$ U* H2 b  k5 ~; |/ P' T84
- d5 v# b8 e- I$ C9 S: }85
# F- P' W) S+ Z' {' M86, e. L. M- y: V1 f/ f$ W4 g/ [4 G
87
& V& Q; _/ P! i; Y' A88
6 U) A  [  s% x89: ~0 Z5 e, E  m
90# l9 @3 W, |5 Y9 G% Z# }, n0 n
91
2 H* Q3 @' E/ R; e! g- l92
& |- }, N" y) C7 _, {& M: u2 D  y93
, S/ i/ q" r, r1 U94  }. R- J% k5 x0 C& F' ~9 z0 W( F) H
953 d0 t1 C- C7 l8 f: ^8 p/ O
96. U2 W" K+ H# r9 K7 J
97: q  ~- h1 [+ G: d- k
98
4 t: t  G2 z( _9 w# }# |3 R3 E7 V1 f99" a* w4 M. p6 o6 ?/ X2 n
function db_query($query) {
( n# M- ~6 x1 P* a1 i  $args = func_get_args();
, B! }3 O; c' o5 N4 c1 K  array_shift($args);
2 F" A6 z2 z' m2 \5 e  $query = db_prefix_tables($query);
0 {5 f3 V: C8 k$ @$ p  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax' m! U% v7 N3 @" N: x
    $args = $args[0];4 t, h6 K8 e! X7 D8 N2 t6 H9 n
  }! w: c9 D  {' j6 k$ c5 K1 l8 J
  _db_query_callback($args, TRUE);, ]0 z: g' _6 a. m3 R; a
  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);3 T  r- X% C; L6 O9 w+ X
 
$ A0 ^0 M# ?7 K8 ~8 D  /*
6 ^3 G- ]2 |1 T4 j# e3 v8 H! {0 M. T   * Integrating multiple read/write databases4 L  m9 H- S5 @+ Z
   */( Z1 q/ j) z6 c2 p3 z$ ]
  if(!db_lock_master() && strpos(strtolower($query), "select") === 0 && strpos(strtolower($query), "last_insert_id") === FALSE){7 Q' w4 S& E3 z$ b4 Z0 M; ]
    $commits   = array('alter', 'insert', 'update', 'delete', 'flush', 'lock','create');* s) z5 T4 u; h7 T% Z5 ]( l
    $is_commit = false;1 X- p3 p5 d% c' m1 j' \; I& Q
    foreach($commits as $type) {
+ u: k0 g; Y6 p0 K' O3 \+ ?      if((strpos(strtolower($query), "$type "))){//[insert|update|create] xxxx, need a space, otherwise, some field which is like 'user_updated' will be filter as commits- {, Q. P  Z, J4 _
        $is_commit = true;
6 J- g- M0 u+ a9 d! N. h- [      }
7 M. p  `; B6 q# g4 z. ^    }
9 w1 H  h0 k4 H' H4 w$ \3 l1 \6 \ 
" O% c% a+ ^7 v3 T    if($is_commit){
7 i9 [3 m0 r2 \7 n  h& o- ^      db_set_active('default');  K' t$ q( I# }7 y7 V) ]: L1 f
      //drupal_set_message('default');
) b. a4 ]3 E" e6 A9 r  z! _3 j0 Y9 B    } else{' L7 l# Z" u; b0 ]& U1 b
      db_set_active('readonly');+ b0 U$ e4 b' o9 c: v3 L: D! o: L  h5 _
      //drupal_set_message('readonly');
- X7 U; ^: k$ I$ e    }* m$ U9 c- W. Q8 g8 }+ Q7 N/ {
  }
6 r; Y$ }0 s2 S  else {
6 r- O3 |7 u# S# t; x3 T    db_set_active('default');+ y- G$ r0 Y( s" a9 W
  }
4 F$ z+ b7 N/ ^2 ?( ^% B  /*+ e) G: }- l5 r0 T' ^3 o
   * End read/write router
7 p4 Z, A: K- Y2 U& y   */2 \6 A0 \% G, c+ p* o' [+ w
 
9 u, f* w9 W- W  return _db_query($query);
9 N: [; T) s. u5 h' c- S4 U}
. A! F3 `2 c  ? 
# a6 S' Q6 B, X7 A& G* qfunction db_lock_master($lock = null) {3 W  a* `" V  l1 c: w0 c4 f
  static $lock_master = false;- x- h1 X+ V2 F. f9 y4 f# [: s, X
  if (is_null($lock)) {1 X3 ?* g& R2 f$ N
    return $lock_master;
0 l& }/ i/ J# [. W# g9 R- X+ Q  }
3 Q! Z6 `5 }2 J4 O" @  else {
# ~5 |) b4 l' Q    $lock_master = $lock;
  U6 X& C  n" n( H9 \' c2 f    return $lock_master;
; S! N: V& v! r7 f2 F2 W  }, o# p/ }7 v1 W6 q8 A5 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, 11-11-2025 21:42 , Processed in 0.313044 second(s), 66 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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