国外设计欣赏网站 - 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数据库的设置。


25 t. i0 f2 L& ]9 L1 ]
3
& v8 \0 ~# L) r. s. G2 |
$db_url['default'] = 'mysql://username:password@localhost/databasename';4 j7 m& s. N; a' s
$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# q8 h) x& Y7 o! s* K6 c
51
+ l% r% u  d8 ?  p% x; z52/ d: m3 u& p5 V7 h6 y) G
53
% i/ d9 f! V* t0 ]; ?- z6 q54
# h$ x5 L# e2 m0 |4 [8 R1 [" L3 {559 ?1 C3 Z* n7 M
56
+ K0 B, k# i: q. m+ K57
, G8 c2 X8 \% p58
$ v& n9 [& T5 _( Q( V, s3 m, s9 N8 {59
8 V4 H3 j7 ?+ {1 F- h7 }- }7 ^606 m6 y% d; K& r
61! z# r8 \; D: y4 B1 G0 M+ l
626 `( O' f" s# S' W$ ]
63
% G8 r3 R- H1 F8 L$ M+ }! {( |64
/ S: K3 a* ~6 p( ^, e4 w65- E0 l# d, y. D6 g  v% S: O6 H' g
66# r" `2 c$ x0 |+ \! Z
67
: S3 Y8 U& c' i68
8 C2 \; y: M5 j. G9 h- w69
& x+ i! K  K) R( M$ |. h70
* D6 T( l$ {/ c$ A" K' M71+ H: @) O' _+ `3 \( k
72
: u0 K1 Z) y) r, ~9 {73
. t2 T0 ]8 b# B: J2 K74+ h3 C3 I% U6 V1 m
75
3 `9 h3 b2 K1 y76
; h% Z1 L( o  ]& j: R779 `. [' z" o( L0 b' @0 @* p. ]5 \
78% h! ^0 E* m% j8 n# m' e, B
79
9 q9 _) F7 p2 y! ^: A5 r80& P+ Y- f3 l  L, ~
81
  q* t2 [4 r+ s* e; y82
9 m! }; j) s. ^! q' Z% g; O83
( Z6 {4 `8 u; W; Y9 C' w5 h84
  P1 w& ?) @; p* h# R85% ^9 i  w4 M0 Y$ X4 E) ~
86
- D/ `$ F0 m5 d) p; K5 V87! O& }- k, x, P; o! _# C# H' l+ E
88, H$ y6 I( J% o
89
. B) p- a. J/ G. E, n9 M: t900 E( C7 W" I* T0 ?6 y; B
91$ N( P4 G1 Z  D5 q* L! n2 y7 g4 x
92
3 `3 w0 v7 O& H, V! ~! A5 ^- `93
' X4 ]+ }) i- C) o" ]& ]! y947 a: i' n+ r) v$ n
95
' k3 N) P8 \8 u7 W4 m& P$ b96, p( t" e" I$ c
97
# e/ V8 A3 b5 p. o: N98
6 c6 B1 d( J- d+ S99( f% I' X4 i" \. P4 ^
function db_query($query) {3 Z1 Z, S% A4 S" F# g* Z
  $args = func_get_args();* [) u. Y( P" L$ {6 \3 e# F; ^
  array_shift($args);! D& w; s7 \* n; r3 _
  $query = db_prefix_tables($query);! ?3 L5 t0 i9 k. T! V2 @
  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
' T" p( g5 J1 V5 D& x! M5 G7 K    $args = $args[0];( g  \1 e: s6 D  {3 h& e8 t6 j
  }
7 K9 _* C9 ^8 m5 N5 g, G  _db_query_callback($args, TRUE);
# _0 t2 O; M' o/ X5 H5 i6 A2 A5 s  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);* ]) l+ X0 a  b# k
 # r4 r0 {6 e, i. {
  /*
, T- v" a# W# |% |' p4 J   * Integrating multiple read/write databases
- n1 B* o6 U5 i6 J6 |' z+ h+ R, a   */
* E/ D# h7 }7 C* _3 }  if(!db_lock_master() && strpos(strtolower($query), "select") === 0 && strpos(strtolower($query), "last_insert_id") === FALSE){  ^6 a$ ^/ C! z( Q6 U% Z
    $commits   = array('alter', 'insert', 'update', 'delete', 'flush', 'lock','create');
# w4 e0 o. a4 g" I  N7 ^    $is_commit = false;
9 U. i3 ^5 ?2 P6 W    foreach($commits as $type) {- S( j' _+ D! }, J, n5 ], I
      if((strpos(strtolower($query), "$type "))){//[insert|update|create] xxxx, need a space, otherwise, some field which is like 'user_updated' will be filter as commits8 [0 {" k, _/ k7 t
        $is_commit = true;
; U. }9 B8 G5 X6 Y5 e1 w# ^: }1 c! E      }
- Z& o3 V/ D' X% H: Y9 F. p    }
* ^3 _  Y- n$ Z& Z; @ 
/ U8 N3 ]! r6 `' z4 @3 |& o    if($is_commit){
5 p' m" _; ^  j9 ^5 e( F$ }( N      db_set_active('default');7 W7 ~, q! u! l: P3 y
      //drupal_set_message('default');
( ^& P0 f. u+ V( i    } else{
1 i" }. Z: ?1 X4 \% x, i! b6 D      db_set_active('readonly');/ A8 S. u* s& O# Z
      //drupal_set_message('readonly');# [; A) Q, M' k) L9 N- j
    }( Y( M1 _( n; H( t8 x7 `
  }/ \9 T% [' t3 u; n% p+ D; P4 b
  else {
! p- [8 z- x& `4 r( W+ f- E    db_set_active('default');  ]/ a1 Z4 I9 F+ I' V
  }0 A3 L4 S- l4 u) r  I
  /*
& J6 m, v1 f; |" i- U8 y2 Z, p: D   * End read/write router
2 c! n6 f8 f4 J% X( b* y   */& I9 z7 p6 o8 m* P1 Q; u
 9 N7 g' D& U- H5 C, |/ M
  return _db_query($query);
# b8 H9 v# v. `( U) f0 J1 d* R}
3 y$ U$ I$ Y+ d  H4 U1 m) i 
( G9 w! a2 u9 b( n. U( ~& ffunction db_lock_master($lock = null) {+ k9 X! g9 [# T: P% P" I5 _% |
  static $lock_master = false;
+ n" v% k* M) X2 D  if (is_null($lock)) {
  \# G9 J% m+ G8 v3 Q    return $lock_master;
; o, b' T' p: r0 j! T& A  }5 K9 _% i: J) O( }) V" U+ R
  else {
* d9 ]5 d. {: k$ l2 @# q0 I/ R    $lock_master = $lock;+ z" S0 g" D+ |2 s  E$ s
    return $lock_master;( ?# o) O- B% H+ O; U' b
  }9 p/ I$ l& l; X: I5 H
}

最后,该代码只能支持一个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, 6-18-2025 06:56 , Processed in 0.408158 second(s), 231 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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