国外设计欣赏网站 - 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
$ e7 O/ Z$ ?2 m9 c* F3
$ T- `" u6 U' Q- @
$db_url['default'] = 'mysql://username:password@localhost/databasename';
# T; d4 {8 L) E$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
* _0 q. E) K8 T% y: P# z51% a" @% _! B$ S$ o* d8 {+ f
52
+ m# L8 X# I0 c" N8 e1 T53
- ]2 ~+ [9 w* J* h54
, x% B9 g+ g( D7 V; I2 N- G, o" \" p55' d8 Z2 ~: q2 O7 b$ _% M
56/ d' ~9 y" o$ X. k# n( S" n
57
6 F4 ^% c0 g( o# r58$ T$ m+ a& }" s* e, r
59
, r* n/ ^' L/ x$ c& a60* w$ R  [' \0 s3 d8 R
61
* W# M0 |  w+ i" P. @7 L. z, Z62
" [% w5 {  j( c0 M* A# ^63$ L. C# r) c8 P! @6 b# Y
64  i3 ~1 v* u: f! K0 ~+ }5 z( J
65
+ q; k0 j2 w. w2 V" w( ~( ~66
, d4 T9 u( ?( i0 [) ^+ {67
1 B. h4 O5 B( g68- c& i: l4 f' z: x5 y
69) b5 ^2 k# K1 O0 a% I* ?; h
70
) f/ L5 Z2 G( R9 n71
5 m, ~  F/ f) |. R# c, n72
! i' q3 M, n: l" z9 V' o% r# t73  R' `6 g8 S/ z  H6 ~$ y% n; y
744 P6 V! q: {/ E2 R8 A9 J
75
5 J# ?% `) ^2 U* J4 ]+ e764 o- M7 S( L- w; S" |# p' J
772 x* d8 Q" k8 P
782 i; k% }% z9 E9 u0 P9 t6 V9 a
79$ E, |; o% z, Z3 R, z( f% @
80
0 M/ v$ E2 T( @( o7 n$ T2 s812 I; [& u) G" M. `- z) x
82
3 b7 S. l$ ~! y% r- R, B6 ?4 c% _; L835 L$ A! L: T; k( l* P2 z5 q
84/ `1 b, N' M1 R2 o/ E& {. N  G( B; u
85
; {) R9 Z+ Y8 g86  h# O' H$ w9 E6 m. r; x2 `7 ]
87
+ N1 E$ `/ o1 O88
; e3 o7 W" q9 R2 m, [# y( D89
) }  D% B) _; {/ @. R* p/ P3 V90. V1 O/ A, C- x8 j& Y
91
( j& d/ o* G. f92" J5 f# b, L8 E3 i' O
93/ {7 |# {# Y; J/ }8 k( h
941 M9 F* o  e+ T# C2 A
95
( t1 Z: k. T# _96
4 ^1 O7 _3 X) K" p% {/ }% o978 ~& B& Q) r8 Z2 @- R
984 z: H+ F4 Y" i# Q
991 T& K6 B: T! i( s' m# A5 \
function db_query($query) {
& f. H$ E0 n. {& i) v  $args = func_get_args();$ w4 _; W# `+ s5 Q; \6 _
  array_shift($args);! z$ {( N/ W# M
  $query = db_prefix_tables($query);; f" k5 `+ Y8 Z
  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
4 R6 X  ]! j2 Y+ s# _* ]5 _    $args = $args[0];
" d) ~" }# v2 O; B) `) u9 y  }
; r- p& T+ `2 s6 R- L  _db_query_callback($args, TRUE);
7 B2 X. e% e# l+ ^  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
& r0 D6 @$ ~" A' a4 H+ w. X! X 
$ n4 v$ S/ P& x! p% m) Z# z  /*# O/ }7 [( m4 _5 A  Y
   * Integrating multiple read/write databases
& [! ~1 b( r% R/ l   */1 p/ A9 k0 F. U% N
  if(!db_lock_master() && strpos(strtolower($query), "select") === 0 && strpos(strtolower($query), "last_insert_id") === FALSE){6 \. \, y3 P! H2 S
    $commits   = array('alter', 'insert', 'update', 'delete', 'flush', 'lock','create');4 z! I  n9 n3 m3 \; i! M5 Q
    $is_commit = false;1 m  A: q# g) {+ v, c* N& ^
    foreach($commits as $type) {
4 `9 t( r: w8 V( ^  H5 o      if((strpos(strtolower($query), "$type "))){//[insert|update|create] xxxx, need a space, otherwise, some field which is like 'user_updated' will be filter as commits2 p" D% A: ]' h/ \; t
        $is_commit = true;
5 F% x* S, Q5 n) E6 j9 G4 `      }
$ C# Q0 R& l8 C6 m( {, n4 Z" s    }. G( `$ m% K8 D( T( n' o
 
5 L1 g, T$ B/ E0 s    if($is_commit){4 X1 E# A4 |* `6 S8 q3 v7 F4 \
      db_set_active('default');% Y' [' g5 H: t% P9 ]$ D
      //drupal_set_message('default');
) M) u7 ~  |% b2 ~) ~0 M; V8 h4 S    } else{
/ k3 J1 |, D9 i, V8 }2 l      db_set_active('readonly');0 n, \: }# k. N/ t" `* \0 i
      //drupal_set_message('readonly');
; `6 m, y; e4 T+ I* G2 s  y: K- p8 m6 U    }
. @4 v2 M% t2 T  }% @/ `" y7 H3 y' g, J( T3 w* w
  else {# u  e2 [6 s: j$ W8 f
    db_set_active('default');5 x3 }. H7 n. q
  }
3 _/ i, c/ }- @& `* @1 j1 G  /*& f! s, _5 d  B# U, P2 r) R
   * End read/write router
" d5 G  e5 b/ C6 Y1 e   */1 ]* X9 p0 X0 M6 a1 z2 e' r' ]
 
1 r9 P% a2 W' @1 q  return _db_query($query);
& s: e. x6 }- s5 {1 A}
' ?5 J; k: K: C $ z9 ~: q% \8 B/ ~1 N
function db_lock_master($lock = null) {
) ~- k( B! G9 {# t: D3 M9 S; o  static $lock_master = false;
7 R& y6 ]; b; ~3 S! G  if (is_null($lock)) {4 K4 ~% f9 h9 F; u( B
    return $lock_master;
* w# x3 y! M% v' A2 z6 W: c, k  }1 w- O& h( J! T  R
  else {" B1 a3 J+ @: H9 Z- e( `( L9 A+ i
    $lock_master = $lock;
" X+ K9 A7 K( t: U% u1 d  h1 u    return $lock_master;
. J* @  {2 f/ S' y( {" `' }& b, Z  }
, q: h8 @; [: O: T& d; F' o# }6 e}

最后,该代码只能支持一个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, 6-18-2025 16:10 , Processed in 1.021299 second(s), 152 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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