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

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,微信登陆

搜索

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

[复制链接]
发表于 4-20-2012 21:42 | 显示全部楼层 |阅读模式

众所周知,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
& |- [) l" a# p4 x/ e2 H3& Z6 o: B/ N+ q* Q4 b$ B: y; A
$db_url['default'] = 'mysql://username:password@localhost/databasename';
& t3 ~- E+ V  f$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
- r. U3 H; |. P; Q$ F) ~. P  {3 J  ]51
% w2 c* i$ V- _2 Q  e1 k3 M1 f* [52; {# a% W  Z. ]  T6 W5 Y
53# e' V' A  S/ K! h3 C, d
54# G1 r; T  @( s1 I4 Y% H0 K
55) K1 a  u! G  A) X/ ?4 ?4 q
56
6 U% ^. j$ H7 |& p7 b) N575 }; D) e- B" P2 s0 O$ f+ f& v
58
; h1 Q/ f/ \- B# j59
- G0 W- N% C2 U% I/ c! B60
+ D& U* Y( Q7 h4 n61
( |1 e6 _7 [9 @( e' M) O: P- `62
( E( K! d; u7 c. n63
& H5 |, V+ S+ z" f& |; t* J3 Z, w64
- x) `- Y6 h$ W% F65
& A* x7 I/ L2 b  D# w4 l66) t2 p" Q$ W! D) e
67
$ A4 u8 C5 M9 a) X68
5 E( _( k7 l4 P69. d9 H' V5 G+ z1 z  F3 }
70
( T- `' Z7 o# W" |, s% B71
  r4 N  u* n+ U& U724 `+ Y8 _  S6 @( H
732 C0 q! x1 G! a7 M1 E2 y
74
8 e" M+ }: j% }/ |6 z8 b3 X; j. l75( d7 V" z- P- j( q" c
76
+ @+ t+ V/ @7 g: R77& b3 D# u5 @, \  ]. l
78  Y. |9 [" n$ D" F2 y
79. h+ o" r: `/ r
80
- n" t- U& ?( u* E4 W% Q81* G+ H/ o  _& x$ ?! Z. Q
828 s, t, O6 f( j2 ]
83) d* t! ~* q: z5 c
84) m" K! z. Z% @! k+ Y+ A
85
& j1 b: d: s* |. }3 p862 [: i' l: j; L9 x3 A, u6 I
87/ `& f5 W1 _8 v! g7 ?# M4 p
88! i( D; |6 _0 X) g5 V7 r) a
89
2 K, h: j) `; V) [3 z  x. S90# W3 X8 y3 C7 P7 a+ c" L
91
4 L, A% c3 x2 O% \$ P! _928 j& D8 d7 G; u  U) t
93
. m. i* Q, B) z: B; m+ i& m3 E944 ^: S) O% j  u% B8 }# u3 |( I# i
95  q$ H7 M: T9 \  x1 e0 [% P' [8 n
96
. C( f8 R5 d4 S# N% V. r( {97
4 q% t& f5 W4 z$ g- @. l98
$ _+ Z- i6 j# }: ]3 s% C; a4 K, p7 ~) q99- b5 n  |! T) D! ?+ e
function db_query($query) {1 o4 V, @4 M5 d0 H! _4 G
  $args = func_get_args();, K: d# |/ f5 g3 v  }2 d
  array_shift($args);
  Z% z# a, i+ w- r7 j/ L0 W" [1 j  $query = db_prefix_tables($query);
; W9 A4 u7 ~0 @' l  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
/ r# f& S; e. L  p& ~' X5 G    $args = $args[0];3 z- ^. t8 v9 F: T  D4 j
  }
- R/ z" ~3 S# p  _db_query_callback($args, TRUE);
5 i  |$ J3 r3 j* K  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
% F5 G* ]4 X. z. e 5 k; u/ X8 S8 C2 a+ Y, t  h* Z: w
  /*$ J7 l  d0 n" G" ]: M
   * Integrating multiple read/write databases6 V, u- ^  Q/ |& u2 n
   */7 {6 v) [, e6 a( C
  if(!db_lock_master() && strpos(strtolower($query), "select") === 0 && strpos(strtolower($query), "last_insert_id") === FALSE){  i5 ^# t, D' V( h
    $commits   = array('alter', 'insert', 'update', 'delete', 'flush', 'lock','create');
+ ^( m) g( }3 e! r    $is_commit = false;1 |4 \5 X( x: F& K6 b6 |
    foreach($commits as $type) {
- X0 K+ p* Q$ ]" x  e2 U6 `      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
5 v# A" l$ u# j0 D1 Q, |        $is_commit = true;
5 Z; n1 U5 q8 Y4 k      }* G9 Y3 ]/ H, n2 T( i- a
    }- @4 F/ r: K! S' Q! t- ^
 
( j# @( c0 t- h. @" f5 x    if($is_commit){
& E! Q+ Q0 H5 B9 g      db_set_active('default');
& V$ w% @0 g6 n" V( a  ^* p- R      //drupal_set_message('default');
1 X5 ^' C7 q& \9 t    } else{
* e, V# A7 L' ?0 N      db_set_active('readonly');
) I/ X# F. _5 R$ s0 [6 I$ y! c7 \      //drupal_set_message('readonly');
: C3 a8 f2 ?6 @7 ~5 N) u    }
% p+ d# {5 Q' @6 Q  }
" Q  D& d% y4 y- u" e$ c- a6 E) o+ t  else {/ `4 y1 w8 Q' T/ G1 {
    db_set_active('default');: s* m- A/ M: j  R* P, N
  }) `: ?* }9 E$ ~* P  N/ e
  /*
( u+ m) _) @% K+ q7 ^   * End read/write router; b% J  d3 d" ?4 [7 r; ?  ]
   */& R2 U. [$ j4 N) o- l# ^
 2 g7 A$ d( f1 z. M; [/ r: i
  return _db_query($query);
: r/ u* V4 J3 K2 A% ^% G}* j9 g# g+ W$ n
 
; Y' P( f+ H1 Z1 s) Qfunction db_lock_master($lock = null) {& e5 r9 b$ p/ Y2 C( J/ U, @' t
  static $lock_master = false;- B) A. F$ X: d3 F) C+ i
  if (is_null($lock)) {
( ]+ ~, ~6 E9 k2 g: z0 l    return $lock_master;  B) ~( \: q, b9 _  Q; Q9 K
  }$ b' S- h" [* G& {4 y
  else {8 i6 @% e' U0 s, P7 \( ~
    $lock_master = $lock;5 `" O! y# E' `
    return $lock_master;6 s9 V8 f3 l) G0 z( Y* _, g
  }3 X: x: z4 |/ a# y: J; i; x: b' S
}

最后,该代码只能支持一个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, 5-1-2025 20:29 , Processed in 0.332928 second(s), 232 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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