国外设计欣赏网站 - 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
: O1 T! C; S) I3
8 x$ g$ G) A/ X* y9 [# s
$db_url['default'] = 'mysql://username:password@localhost/databasename';' h3 B- `0 F5 Y
$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
7 B8 x: I3 ~1 O- R, s. f+ e  T' L515 x. [* \6 V# s% N
521 Y0 b+ G& j5 \, F8 M/ b! X
53
) n% f0 B9 {: i6 |" c  Y54
, Q! _, x- i9 k; p4 C$ E( B55
9 G. B' ?. B6 }6 ~4 k56. h8 n" v6 G; |$ F: _
57( Q3 y0 H8 h+ N
58& m+ Q" S4 d5 e' ^4 A' H
59
! S: |/ m$ G3 A( D' v60
2 Q' j& n4 u/ M) ?8 S" C6 z61/ l) _" Y8 K; i9 Z0 ~2 }
62" W$ S& [6 v9 o4 L; s
631 G  S: H) M6 h( g5 v( q
64
. N3 j0 m/ `5 v( \5 P65
  j1 @/ o, [9 t3 j6 W( |66
( B- I3 S: W0 d$ s* Z: b673 g& V  d4 g3 U1 \- \7 o
68" B( T. ?- c$ Z* x  g7 j
697 j8 F+ Y- q! k% K3 s4 Z
70
) H) v3 p2 |3 e7 o) u, ~9 |71
1 m" O- B, p5 R& b72
3 H1 X: l, ^- {0 O) t! V) A73
- @: X  d, P* k* l74
, T  |$ Z( f$ x% V75
6 x; L/ A& C6 N# ~$ M/ a% x5 i/ ]76
, i) {  S( l2 h770 U* t/ {1 G1 C0 O* F! K
78
* _% Z# v8 ^3 y& [& f& l. a79& ~6 w/ \. M" `& H* m  @1 l5 M' v
800 X' E' r1 P( d- c6 ]; w, ~2 T
81
3 _, Z( o( k" `- ^82& K) H, i3 A+ o% p
836 j- u% v9 w; E, Y) ]0 Y: ?! w& D: o& |
84( S- o2 n: j& {: v
85
* ~* z" ^/ ]0 ~/ ~1 c# u) i) m86, m3 _" `7 o2 E0 V' E+ X7 U4 ?, l
87
7 C/ F+ P  W& m$ s2 B2 M88
2 L6 U. w$ b& K) H4 C$ Q' m% K89
& c8 t5 G' Z8 B8 i6 Q; A0 R90# m% i0 W% R% z9 W7 Q
91
- u( Z9 z0 s" g! _  _9 R5 T5 \92* I( |0 ]. m2 w; c
93
9 [0 B" ?/ ]9 O% G94
; }7 }* d) p( P" Y) v954 C, W# @6 ?" g. [4 r6 S, P
969 ~4 c; z4 r, y; W; \
97
4 e: D" u+ Y& e4 q2 [. s1 k) h98
4 Y8 j0 p, A* D1 {. @; ^99
' N! c! D7 n% I8 v5 v! ?  E& b+ @+ u# t
function db_query($query) {! Q2 F# X3 R1 X* B
  $args = func_get_args();# O6 A; z+ b7 {$ R" j# F
  array_shift($args);$ ]5 b; t# e9 m, v
  $query = db_prefix_tables($query);: l7 X8 W# E+ K5 N/ I' y
  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
+ E4 c: ]+ ?& ^/ l    $args = $args[0];. E$ B) M1 S+ D/ ~
  }
8 x% Y/ l: q; M$ h! |, W  _db_query_callback($args, TRUE);
1 k( ]2 p3 Y; \1 I" D! @% _) x; ~8 F  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);% a1 I9 d# l3 M+ D& [8 V. v
 
% x% h+ d2 y1 Y5 W+ ]  /*5 Z3 X+ P- W1 n! f" |3 Z) V
   * Integrating multiple read/write databases
. j3 }& A: B4 H   */
) _( {6 K" Y& ^4 {) Q: A4 c  if(!db_lock_master() && strpos(strtolower($query), "select") === 0 && strpos(strtolower($query), "last_insert_id") === FALSE){
* S2 {+ k6 y( ~/ x3 w+ s    $commits   = array('alter', 'insert', 'update', 'delete', 'flush', 'lock','create');. P8 q; ]$ e6 s# @% L4 `
    $is_commit = false;
! G$ T! z0 l/ h    foreach($commits as $type) {
, d# P9 {( e* @; ?; b3 T# {1 N      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
& z2 g8 y4 t; I8 A# F( u( ~        $is_commit = true;
5 a! @9 t; P2 v0 G' G- m      }
- |; B. F& Z+ t1 ~/ L" E" {" n5 w    }
4 s/ R8 q. r& D( s' ?* i8 p 
) g/ l+ z  I* i. t    if($is_commit){( H: c' N; q$ T1 n
      db_set_active('default');* W, m- A8 `8 S4 K, l  V3 w( ~. x
      //drupal_set_message('default');
, b  r. e  `8 ]8 I0 T    } else{
4 E! T* M$ A0 @) m" V2 M3 p3 B      db_set_active('readonly');0 F1 B6 U7 h; h
      //drupal_set_message('readonly');4 y( N' q3 a  u1 s" v9 I7 @7 a' n( N
    }
8 X, s2 V0 i' ?- \  }
* m: T* q4 A" B' F  else {
% f: {2 [8 N" d& H& K! l- T    db_set_active('default');8 U! D& V% |3 u8 }& x, I
  }
/ s: u6 K8 C9 t9 E  j$ ?; K  /*
8 E8 F" F) B* ]" q1 t. W   * End read/write router! G# Q7 W+ o9 ~2 b+ w8 j* G
   */# H# Y- _3 p, s# ?: X2 w6 C6 \
 : K7 D) Z7 j) f* x8 R: ~
  return _db_query($query);6 j: B3 o8 C& \
}) o/ W' [5 n# w+ S2 W& u
 ) S5 D" X" K' P( }+ _  @) l
function db_lock_master($lock = null) {
2 `0 a: l8 |% C1 S( e0 @+ N; w  static $lock_master = false;
8 |0 E2 Q" v; H1 E& J  U  if (is_null($lock)) {
% Y' p1 L4 g* h; K. f3 H    return $lock_master;
9 ~. j. z; _9 |. a1 h* S; K  }
1 l4 W- B+ `2 \5 _2 {" h+ f  else {
" B! N* K- r# a9 m    $lock_master = $lock;2 n' P' |+ t+ X% {
    return $lock_master;/ }  `) K- \. [1 a" F7 {
  }9 @! Z1 X4 V$ i) ^0 K" ?! J& B
}

最后,该代码只能支持一个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, 12-19-2025 18:41 , Processed in 0.269581 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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