国外设计欣赏网站 - 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
1 D. o2 }% `7 F, x* g' J35 ]4 s" h3 t% F# o9 y3 g
$db_url['default'] = 'mysql://username:password@localhost/databasename';! @" i+ o: U1 V+ G3 E: J
$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
/ ^9 Q5 \- ]% I3 O, b* c) c  O514 z0 s2 I8 I0 P5 o: ], v
52
* Q* n! F; r$ \53- I7 d2 {& I6 t. g3 \& K
54
/ r/ `$ Y/ I" ~6 w; }" F55# P0 C: h$ \4 k6 R9 Z3 g! c. \$ E
56
, I, |: Z% y: t- d  j9 X57$ C0 w# r) X7 A) \" d, D3 b
58( V% T; s! A$ A; v1 y* V5 v7 D$ ]
59
: S/ s' q2 d- n! Z) ~60
( I2 D3 y! K" {7 S61
2 ~# W5 Z) `' [" D+ E2 e62* P% I0 y' K0 O' B, K) @. t
63
% j3 B# Q) T  N0 K3 ]64
2 M6 T/ G+ u2 C. l  d) H% W/ i9 Y/ T65
9 f  Z6 m! V1 Y668 ~) P/ n7 N* Y# S( k4 r
67! a' r8 @) t; t6 k4 E% {3 w. L$ F
68/ ?( b) a6 F5 g0 {
69
, @1 W! r4 g) r" t6 H702 K' r8 ^. f* ~7 U
71
( V; G7 \: f) c: e: C72
+ I9 t/ ?$ n/ c7 k4 F( i: r3 f3 o73
- V3 B) J, W9 K9 ?6 H74
! c1 O8 G, T( V9 {$ D75; N1 U( W% C& f: b2 x
76
. u- T# g3 U/ S77
, h4 x8 |- F6 l' e! B5 @# i$ L78
3 ^8 V2 \; k3 |79; p# [) J% T6 k; j' O8 a. _
80
. X  q0 z! p; o3 c- }9 F81
: k+ k  G" M- ?# u1 T82
% H- L1 e3 I. L$ G83
0 k5 a& K6 e9 d* Q. Q( @6 g841 {! }& `8 A( F; z8 Z1 K- g
852 J/ g9 N! K* Y8 c, F4 f
86" K" [7 |# {: o  y5 S
87
5 d' C/ e) t; l! \* U% I884 e. L7 ~' v. I& e( m
890 p' P% i, h) |, T) p5 O& {! V
909 q/ c- J9 d2 I, m9 g! ^
911 C7 H7 T) ~2 a
926 {* y+ g3 l4 n9 a
935 o. T7 Q" @5 Y2 F5 r
94  {$ M* t! b( J3 H( N- l( A5 H7 v
95
2 b! _$ f* z' z) A# _$ G963 _, \$ P; e: I0 y- x: \
97
' m) ?# n) i1 H6 n98
' [9 o! g' d: M- X99' Y% n. B$ P  x! ?$ t
function db_query($query) {
1 y2 g. b* Q6 Y( O& r  $args = func_get_args();
0 G& g; ?8 ~1 h9 s3 A  array_shift($args);+ C! t' \- Y8 y0 M
  $query = db_prefix_tables($query);
2 Y: K9 s& ^- a2 E# E# `  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax) F: b+ ?$ [8 w
    $args = $args[0];! `+ Z: e. v$ F3 |$ s
  }0 h0 ^# V" N& v+ V* y$ i7 ?% B
  _db_query_callback($args, TRUE);
! A  J* ?4 m( O; f4 l+ r) s, V: }4 ?  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);9 w4 o( L2 K4 a& h5 o1 X
 + o* q8 u1 }+ i& e4 ~8 s% \3 u
  /*1 l' S" L' w9 w  Q# C* ~5 Z5 j
   * Integrating multiple read/write databases8 e5 ?% r% @" E
   */& t# u" j: a" j5 F3 W
  if(!db_lock_master() && strpos(strtolower($query), "select") === 0 && strpos(strtolower($query), "last_insert_id") === FALSE){
0 e8 B4 t/ J( n: [- Z2 X    $commits   = array('alter', 'insert', 'update', 'delete', 'flush', 'lock','create');
# j0 G: S( Y: f. [. w$ F- n- v    $is_commit = false;! i4 o* I) e2 E- W) U, Z' }+ I
    foreach($commits as $type) {* n( i9 B- Q' L2 p" {/ 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 commits7 R0 `+ |9 h0 }% |" t
        $is_commit = true;
6 a! R, f1 |# _1 R( [      }# n$ ^* ], H  F
    }
: W7 G6 A' c8 K$ s $ a9 y$ Q3 T$ i% r% t
    if($is_commit){
& Q6 \; L+ F$ N& s; ?% H      db_set_active('default');# n& G' @5 k& P( o6 n9 d* b
      //drupal_set_message('default');
( ^/ O- n% `. {( j' D( f; L7 Q    } else{
0 Q' b0 ]( a* }+ ?      db_set_active('readonly');3 R5 d* c+ v8 Z3 y3 a: V
      //drupal_set_message('readonly');( e" f# _1 r# u" Q
    }# _$ a% ]0 f1 E2 `5 w
  }
/ Q$ V! y6 q, @* q) ^  else {
& [# B  }% `/ @% @8 B    db_set_active('default');) N, `" a# c; ]0 |9 v1 r
  }! k2 c; D$ j" ~  t+ b
  /*
( ^  O% E, `& F8 W  `   * End read/write router$ B4 x4 Z. s% {5 w2 s+ Y" I
   */
" s0 v% \, r: n) }' g. b 
; D2 j: [$ q; Q, k! C  return _db_query($query);
- t; A( ~/ U- v( g3 w}) t) O" ~/ n9 v5 ~+ }
 # N, R2 s) a4 O0 L1 ]' H$ V/ m
function db_lock_master($lock = null) {& E  v# u; c: ~9 v4 m& y
  static $lock_master = false;
$ B+ J9 H6 z' `8 j! ?  y  if (is_null($lock)) {! V+ G; s1 A- T4 B2 u! x
    return $lock_master;' @% Q) k1 Y+ @+ r
  }
& E9 A+ m# ]  f: K. b, [) e  else {9 C# T( E: A  V! [* t
    $lock_master = $lock;1 ?- t- M8 O. Q# h/ i! Q$ t
    return $lock_master;
3 I0 x" M3 ^5 Z6 i  }1 K# @2 v# j7 l0 H( D
}

最后,该代码只能支持一个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 22:00 , Processed in 0.577693 second(s), 154 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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