国外设计欣赏网站 - 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
7 ?! U( m' ^! C% s+ T; h3$ V+ S3 x! U; d: z( s; P5 t/ x' R
$db_url['default'] = 'mysql://username:password@localhost/databasename';
0 d0 I' h% T# D4 ?1 h6 x  v$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
) j1 g! {; m7 O+ r. q& }51
5 D/ {. S+ Y) B52
5 ^6 Z4 F0 W+ x/ S" p: U53  ?& U/ `, c8 M( Y
54+ s4 p4 W1 a+ i4 b: S+ W2 P
55- t: o1 l2 o" m' L6 N; V
56
4 S1 |9 M4 U6 I573 F( s  s' L4 r" F; x
58
) t# j- @% g5 ^0 u59
4 a4 R  B$ `: @9 i60% N0 `- U5 y9 `
61
5 k, V7 ~5 J7 P8 ?62( O" E* E4 y( P8 [" Q
637 v3 V- J1 C( X: w! @
64
; H. I& x' a3 v7 ~65! m7 ~( X+ a+ z  P3 r
66
# \0 G9 }$ w- l8 M67
) ]( q- K+ v' s+ G% }68
6 Z/ `* R7 `8 z3 _69
# b0 m" U) Z$ C1 ?' w70
. a0 Y, T) ]* l' k7 I! c71* h: h, z+ j: O. L- o$ L
72
9 z, ?" G! l1 v$ f73
9 C% T' v, h2 A2 g740 ?- ?) K7 Y, H3 X* d9 t; o+ _( @" J2 J
75
; K1 C0 }5 r2 Z# E' R) X76
. t4 R# J* Y' h0 ~775 Z/ s/ l9 {6 P' q, ^- ?- h. a
78
+ x  K  ^0 u3 s! J. J79
  P( x- |7 e+ l80
- j& l! ?% x! d! {+ D81! Z7 B/ P& G3 k" ~+ Y, J
82
# A) [4 {6 e* _6 L83
; A# M( K' h7 @! ?844 P$ W1 r: b, n5 U! g
85
7 r! t0 g# b6 [& P86
3 o9 _; T4 v% |/ \- e' [4 J2 k! h87
, D# {7 k1 F) t( a0 Z88
. I% v) E# F8 }  c* j/ _895 f- Z0 O9 B" \2 r3 t+ K% M
90
6 [/ M, V6 h2 g. J/ u91
  z) I4 _/ P1 u- y% t92
. t1 N) c( @3 n% ?: @5 s0 z, i% f+ L936 o- A4 B2 i$ H6 U1 J
94  J# @% g' V" N2 C
957 u6 ~& C, N2 G1 w
96: u, Z$ x  d+ P  h. G; q9 Y
977 f* |! w5 q, C: K4 e7 X" n8 L
98
. j! e# K8 z9 |) R4 B9 l5 t99
4 m' ~, J7 a2 l5 q5 ?
function db_query($query) {1 j3 ^) E' }- e% P/ d
  $args = func_get_args();$ c6 F" m. \; }7 D6 t& A
  array_shift($args);
. l& e8 Z( k' U  $query = db_prefix_tables($query);
9 R; c1 D0 g2 E7 d2 ^  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
1 B- W# i3 X+ F2 N# q4 b    $args = $args[0];
2 {8 E# U- D1 H0 l1 Q  }% j- w) [8 `1 W! e: i) s. ?
  _db_query_callback($args, TRUE);
4 x" F8 H" g, i6 V  U4 w" b  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);. ]  |$ s- V" q
 ( ^. K7 [* g, x
  /*. q1 h" U% F" _9 a8 m* S
   * Integrating multiple read/write databases2 y+ @  z7 x  P& P; r
   */9 ]: I4 C7 F8 G# H) f1 Q
  if(!db_lock_master() && strpos(strtolower($query), "select") === 0 && strpos(strtolower($query), "last_insert_id") === FALSE){
( D7 C. X0 u" m0 K* S8 A    $commits   = array('alter', 'insert', 'update', 'delete', 'flush', 'lock','create');0 [* g# O" i$ }6 E; j
    $is_commit = false;: \8 Y- k* E/ g3 e
    foreach($commits as $type) {5 n* m( k: q; I* S, Y, W- {
      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. Y: Q4 \& @/ M9 z2 u9 f( `- j8 g
        $is_commit = true;3 ?1 r6 y( P5 `0 F4 y8 D! d- c
      }3 l2 `/ N; |. g' X7 ?2 I
    }
6 B0 D* w! O) `( `, u8 M( J 
7 |4 ]& u( @& U6 h! C+ {    if($is_commit){2 c4 f5 Y4 M$ U5 W/ R
      db_set_active('default');; w7 g# c% F& @4 @  J& q7 v
      //drupal_set_message('default');) c# x% r  P5 u+ r/ Q- W' M
    } else{
2 G; U6 G  a) y3 r# ?9 Z7 J! o      db_set_active('readonly');
) ]" N% D0 `8 \. u9 `0 H" r; ?      //drupal_set_message('readonly');
3 r  V3 t3 G' j1 r2 p( E. ^    }' c- V! i- T. t* w- s/ \
  }
# |# p9 w/ ~0 U9 e  else {. q  q% Z4 P. J8 y( y  v8 o
    db_set_active('default');
% b; O5 R" _3 b/ a- c$ y  }' t) L. d0 G8 q( o( G
  /*# [1 d# R5 R; X8 n: s( d
   * End read/write router2 Z* z: c5 \+ L. Z$ Z. L5 h0 j
   */
! L9 c* g2 G& h' d4 ?6 j$ V) x # j) q3 B9 y$ C& S2 V, d
  return _db_query($query);
4 Q0 V# |- l2 M! [! M- x}
" y9 W! F0 \" |: g0 ]* U( Q $ @& l' @% Y* n7 D
function db_lock_master($lock = null) {
* K- f3 G, V6 H5 f' I  static $lock_master = false;
: x2 o9 ?) p" j# n( c  if (is_null($lock)) {
+ V+ s" I2 z' Z/ |2 y8 y# x    return $lock_master;
* c  [( {, ?* r# d$ X. \% D  }: |, ?# ]$ P/ h2 v
  else {6 @; O. h' T+ b5 w% X! u* e% d
    $lock_master = $lock;
$ l4 B7 t) F9 ^. D+ e    return $lock_master;
: F9 X8 [$ l( R  g- `& v, R! @  }$ {# w# X# P( t4 c' e' T' I
}

最后,该代码只能支持一个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, 4-28-2025 21:05 , Processed in 0.392839 second(s), 154 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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