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

2
3 p; M' S! \. \9 _9 Z* @. v# r3 g1 \3
/ \% d8 }$ M# M$ Q: J8 C: s
$db_url['default'] = 'mysql://username:password@localhost/databasename';
/ X& ]  k5 H* j% s# o' O) F5 S$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. o2 D* H: Y( K9 A- @
51' S' \" T; K  T4 b; W, ~7 ]
52
5 s$ l: ^/ p9 M+ ]7 j53! a( W  ^; ]" S& P
54
+ q, E: e) R% n- \55+ B' Q' ~- l* N  d& x7 Z# k
56
0 p7 \7 t6 l8 N8 V, Q57  K  s2 s$ u, @0 z* N- x1 ]
58( ]# m7 c9 U) w8 y) P/ y1 ~
59
5 W6 ]8 G% h8 t5 j/ L& D60
) ~/ K8 |+ O4 v( I5 b) g61, N4 t8 m# z& f) C5 \' G: q3 o
62+ y6 k9 X! }, p/ k! E5 G* y
639 |3 l6 c. g9 _, K5 R# M/ E
64% O# {" I) a/ O( U" |5 ?" ^8 S* ^) s
65
6 k& E" a& u% U% x( y66
9 c5 S4 J3 n3 t9 q67
. m% ~8 H2 I! M- Z9 s, |" @68
8 \& j8 N& l/ ?; k69  C! N4 }7 f9 `5 V' ~
70
4 H1 h+ Z0 z; Z. ?# `71! f2 q' k. s- M- r, ]
72% D8 I9 X6 o3 s. L/ k
73( H2 f% h( h/ `# C! D. D
74" R) B+ A: g6 b  m- T" n
75
" Y% b% M4 l; j5 T# E76
2 V! a- c1 K7 d1 c1 V# L77; ]" Z" _( q) V9 h7 k
78
; Q  l8 ]' ?: E/ X5 w( X799 h% z4 G6 z. k7 h; z: c
80
& o  @8 E( J5 _+ D# x81
# P  ^& s! x  [7 |- f& m2 _8 K2 }824 V+ h; U; d; O$ L% L. n0 L% `
83. Z* u4 J; ]7 v1 y# ^+ x" @7 E
84; d' L% U3 f; Q
85  S1 u5 k: E8 Z+ Q6 Q/ e
86
; D8 T% c( }$ `; _8 B/ A; X1 z87! g3 }1 o; {. A6 w7 J/ K
88
$ a8 M$ n3 p' p! h* I$ |. W89
7 t. q/ |/ q" Y% S& c$ V/ W# ?9 T90
0 @6 L9 Q7 q0 J3 a( `  I91% C/ w6 q" c" \& b1 t$ r
92
, @; Z0 e3 j: Y0 C  R% M, N5 t93
! |! ]9 S5 {; x& P- }94
& i8 C0 ^) P+ v; h. O. m: A0 k  p95
6 @# _. Q; l5 \( G  S96
( t" g: u! A% i) p+ O1 d97% c9 i" ?& N. L# a) L
983 {9 g- E6 v! y
99
, i! d  ^! w; y2 A* R) c, G
function db_query($query) {
% v  w0 Z7 {: h% U  $args = func_get_args();
4 r, A+ m. C. O$ `4 b- r1 |  array_shift($args);
! x6 ?  P; d$ B7 ]5 F; v  $query = db_prefix_tables($query);
) E/ L9 I, z0 j& a% `; u  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
. ~& m. M, k2 u- U) ?    $args = $args[0];
3 Q( H( L) v2 a5 j  }2 u& z, s0 K! a' l
  _db_query_callback($args, TRUE);: g- X/ E% x7 z0 r- N+ [9 F# `" p
  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);5 h7 a: V7 o4 t
 / U* B( W+ G5 y' X
  /** b+ s& f+ H' v3 ]
   * Integrating multiple read/write databases# J  _& [# T% B( B6 U" v% ^
   */: i% p: V  E* z" i& }
  if(!db_lock_master() && strpos(strtolower($query), "select") === 0 && strpos(strtolower($query), "last_insert_id") === FALSE){
0 r' B% l! W+ S/ z4 a1 z    $commits   = array('alter', 'insert', 'update', 'delete', 'flush', 'lock','create');, n1 l* J, ~4 F2 V0 l
    $is_commit = false;
! M. z- o* q2 D, i8 @    foreach($commits as $type) {7 ^% i7 a2 U" E$ a2 V0 \4 l1 h
      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
' V+ J2 q: o9 t" j  N        $is_commit = true;
; r* n# }3 X3 o      }
+ D+ _' j: u& ~& u2 a; L: d; p    }
1 B' c+ c7 }# W1 c4 z 
3 [. f$ b3 E0 @    if($is_commit){
. z: Y/ S" Q) G9 ]7 f. x+ X      db_set_active('default');
& q( w9 J+ t) X" K      //drupal_set_message('default');4 a+ B! u5 N. b
    } else{
+ H7 n; |4 i5 t* v# _1 d      db_set_active('readonly');
% c: a" ]" P0 a      //drupal_set_message('readonly');+ R6 g3 @8 b) A3 \2 x+ B
    }; X3 V5 z! e" i8 @
  }
7 ]* O. U2 B5 K. ~  e9 U  else {
4 i- e& c7 D1 m: s- z$ q# o    db_set_active('default');
& Z. j( d6 ^7 S3 m) u  }
$ o3 b2 L, q. \  /*
; n1 N1 F( T3 {3 [0 [9 T. I   * End read/write router) K8 H) v% c2 E/ H: J1 W& h1 ^
   */
( i2 L* L$ J$ ` : a+ m; l5 a: P
  return _db_query($query);
, J2 T& Y& [' u  [$ L}6 t& D8 N8 X% q5 b1 N
 
2 E2 W) C( r$ j3 O, D) Y/ s1 yfunction db_lock_master($lock = null) {6 J% f* x! B. ~! a; D. u, p: z. R$ T
  static $lock_master = false;
% _7 h' R6 ~! O' U  if (is_null($lock)) {" o+ U* z* b. Y$ j( [
    return $lock_master;
6 E1 X5 k' c4 E! ]$ H( J! h  }
" ^2 Q4 V" b2 C6 X! T5 {/ w  else {
" ]( K( r- t0 u    $lock_master = $lock;
2 k4 i" T0 _# ]% n8 c5 d4 ?- L: V" X    return $lock_master;2 V3 N# c/ s% _3 Z
  }
0 _8 e6 F' b+ F; x/ Q8 f/ Q% _}

最后,该代码只能支持一个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-19-2025 14:13 , Processed in 0.792035 second(s), 152 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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