国外设计欣赏网站 - 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
( H: Q& g+ B0 ~$ F; g3
, V; d0 _$ Q" |6 P! h
$db_url['default'] = 'mysql://username:password@localhost/databasename';% O. D8 O8 {4 t/ u
$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,笔者以前在项目中经常遇到,大家多注意)。

507 u# v2 L  n( L; K
51' M# X! O5 a3 I: Z% \6 Q/ H9 T
52/ L5 _9 Q$ ^# Q
53
+ s3 x& A& |+ y0 `" b& s: |8 O5 [54. V, {  J5 J; b# D  B4 N
552 l" \" d1 j% A( e# [9 g* _, v
56
$ V1 Z" {3 I# g. ~57
5 `& P. \7 y; a58
  U' |  M2 o6 ~1 C7 e5 B9 E599 A9 H/ l2 s9 i" s% Q1 X# }/ B
60& {0 T+ h8 v  Q7 O9 ~
61
( H$ S  p* W0 v, H# I% u0 i62; v9 r/ ~8 i6 K" o$ H* c
635 t) H5 h# b; O
649 G$ P0 y# A3 i" M3 [- d
656 [. W9 Z" \. N+ I
66
0 \8 o7 ~, ?8 `, \67
1 _; s5 |4 U- J! S68
- w. Q5 e0 f5 f' B& X' l: t, J69
2 v7 ?2 W# y: c" H) C) g) R7 E70
3 o0 i( Z- n2 L1 u: a& u. y7 A71
3 T& e3 K2 p* J4 w; X& _72' Q% u1 u. n; l# Z  x8 P; ~
732 V0 V! m/ a4 T" X4 W
74
% v$ z+ }2 \+ i$ ~; i75
' ^% _* V6 i: L) B( U76
% n% ^+ L: ~1 m$ U2 w5 \) B77
4 r) o5 V$ E# w  g3 \( Z  e78
) g5 J1 T- Q2 ~: y- |3 |79  f, b+ S/ F0 t% D
805 K) q1 v: I, J7 m0 y; D2 r
81
; y9 M8 \! H  ~% C5 f( f82
+ o, W( }: x) }5 p+ \83+ i1 N. F; j# U
84
* C; E  Q9 I4 {! _% v' }. y  e85
. Z1 R- J) @9 ?6 t86& w  y* p5 q4 R8 K- g2 e8 Z* e* w
87
& [6 e9 l1 y4 V, V4 ]3 y88
" m" p' N7 j+ V% k; ~' P894 d& y$ c( G5 G
90
7 a8 F% h$ C4 Q91* G6 p9 o9 i9 A* R2 c( G
924 y: t- Q3 H: a8 p
93, M, S/ H& |0 K" r; s8 |
947 P7 ?+ ~! @( d
95% `4 o3 ], g' ~0 k/ P% U1 ~
96
  H+ e4 x# h" S% c# H+ q/ S97: e8 o% r$ E; A1 g
983 v4 y, ?0 A9 t) P. e
993 z( G3 O# {2 S& R
function db_query($query) {/ d( o- V: E$ G
  $args = func_get_args();2 Q3 c$ u8 z/ S- k0 M$ m
  array_shift($args);
) c9 r6 i' f9 o5 v  $query = db_prefix_tables($query);5 E* A1 T! ]& z. e
  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
7 ?, a# G& _8 v2 a& W    $args = $args[0];, `% @. E# _. W1 e, w3 b; `# O
  }& ^% X! l! s" {+ p$ [
  _db_query_callback($args, TRUE);5 M* r" e  v* R# u7 D) x& W
  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);3 c: a5 n! Y) V  S; s$ b; K- w0 H
 
% T+ Z+ T( h. _# d& b3 |/ N  /*0 G) I9 A7 s8 {1 Y3 `, C9 p  h
   * Integrating multiple read/write databases
2 s+ {( O& R1 w% l0 |) m   */, K+ E5 X% {/ O1 q2 @" h
  if(!db_lock_master() && strpos(strtolower($query), "select") === 0 && strpos(strtolower($query), "last_insert_id") === FALSE){
: N; Q% q+ M' t% V- r9 U2 t8 b+ E- t( J    $commits   = array('alter', 'insert', 'update', 'delete', 'flush', 'lock','create');
/ `' F+ s) p/ r8 U; X) \    $is_commit = false;
) R: u# {( L4 n  \0 m6 ?    foreach($commits as $type) {  O2 l$ t: B6 {/ f/ j, x: b, x
      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
! h% I5 L6 F% W, e- ~        $is_commit = true;3 D/ c: W+ Q8 K- m
      }/ G5 b2 \/ e3 }5 d
    }* P; D/ H8 T" l! u
 
1 O, u5 x' Y6 U( {* v! i) Q    if($is_commit){0 [: \  H- S/ v0 [  x1 y& ]! ?6 B
      db_set_active('default');
4 C. `. q. N9 \3 t# j( K      //drupal_set_message('default');0 j+ \8 n% V( l6 h" ?( Z
    } else{1 s& r6 n3 w/ z4 g5 x
      db_set_active('readonly');5 i; C$ B& M8 W2 N/ i8 Q% v
      //drupal_set_message('readonly');% [& ]* N) \* v: U# k
    }
9 @6 X7 p$ U2 ?9 a( {. A7 P  }( Q( w4 P# g/ P  R! |
  else {- [1 y' s7 W& V- I! ?5 l  W) B
    db_set_active('default');
0 G* Y% l: u# g8 a" j5 j' Q" U  }
5 m" R+ Q  R3 p  /*6 A( q9 D& E4 D# s7 b
   * End read/write router
2 h, E8 {( w- m4 `4 Y4 L   */" C- m" ]) N, Y6 j, o$ t
 ( C4 g9 ]5 g) q
  return _db_query($query);$ A' ?7 }! ^# f: h: j& T
}4 w1 {1 }4 Z6 d; k
 . L& X6 P; b9 B% f# T+ l, @% p* S0 v
function db_lock_master($lock = null) {7 J8 A1 X* }0 p
  static $lock_master = false;
2 `4 ?" h( f- P! D& |  if (is_null($lock)) {
9 A. ~( p- o7 _6 p9 _    return $lock_master;! }8 h7 _- v: Z6 n7 G
  }
8 m7 B% u2 Q7 [) O6 h  else {  E: f6 I, A& T; i: P
    $lock_master = $lock;
9 [, h( K, d6 d' x    return $lock_master;
# e4 E4 w* s" R0 l: X  }/ C! D; w2 n+ N$ v
}

最后,该代码只能支持一个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, 2-19-2025 14:05 , Processed in 0.392290 second(s), 152 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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