国外设计欣赏网站 - 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
% `# ~* C' n7 x3 N: c3* p1 ]6 ^2 T4 D' L0 g* r, l8 ?6 y
$db_url['default'] = 'mysql://username:password@localhost/databasename';
/ y# p& b; H8 I$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
0 X( l3 B* q6 l, C' ?# u# o1 N51
& _! G1 [+ Z2 ]6 {52
: R% Y4 l% G1 J+ X# r" F2 ?3 W53* G' O$ |+ k7 a) D
54
" `5 a6 l2 T: q; E9 V0 R55
0 v; {/ @/ W) H& F" u, Y56
* d# u7 q3 u* u5 y% d0 D57
* \0 y2 V1 e6 P58
9 b4 P  {( j& y$ ?8 e  \; ]: M0 R59' w. m3 E# S- Q3 L
60# g5 J3 F4 C! B! p0 Q
61
0 N2 f9 B6 K( p6 B6 G2 b5 X# p629 |% G" Z4 }; s% m5 B
63
" k! Z+ \1 e3 [& l64$ p# ^2 y" u' S: L
65
( x" C# j6 t8 x9 v" U660 T* L8 `" k3 `2 X& \
671 I% F; N- {6 X" f4 c
68
& L  M% o# f# V& c# h  e. j690 h+ Z7 S, o4 [+ l7 u6 {
702 S5 P  d7 S8 f6 n" @
71- u; j7 f  q/ ~6 o# ^& d1 \2 p
72' d7 V2 h  K  X% M
73
5 E6 Y* `0 l* D8 |  U3 M7 Q/ Q$ b74
" a! E  T" I# |! C2 W75
1 m) j2 U( U8 G3 b3 J76
4 P  f) Z  L, Z! S, p77
+ B1 S! Z3 \5 d, J% H- K6 g78. Y$ S* Z3 L7 L) E' [: _
79: A: ]! J( e0 y( r
80
7 Z4 [$ o4 A; e# `" C4 n! O. E81
; P& Y  W6 f8 \5 g* }% r82
+ n  D4 R' m, z6 F% t! s* {83
8 a0 e5 K7 t: f$ w, w* s, y0 [844 F" H5 c. `+ l, ?; m1 n" W# n2 D
85
" m0 O; e" Z, d' T, C# e7 I2 i86: q# {$ U! E  W2 E& K  `) Y
87- \) h! o* f9 D) d7 |3 r
88* n; b3 A! D2 {, E+ D: S% n8 m) ?
89
: u; k" s* u2 E90
. M" P* a( U. ]0 q- _91
. v' L- a7 ~1 I# Y$ `6 N92
$ _. H0 }" d; U4 ?& u: O2 s93
7 y" }% R/ u6 M/ i3 [3 w94
% j! C5 F1 B% `2 Q4 C3 H3 T95! |: ?$ D$ m0 Y6 v
96- }7 R; {8 N2 y$ y4 X3 K
97
5 g9 O2 o! J) Z  J0 k  U& k* n98% V/ `8 j, |" @) P
99
: `1 h" n4 w( o; M, R- l( u4 V" o
function db_query($query) {
) S1 |  `5 ?% N  $args = func_get_args();: A% `1 `) X- E, P, m* F6 b
  array_shift($args);$ S% ]; e/ C+ C7 I* r
  $query = db_prefix_tables($query);' t+ i$ [* ~% J9 O# |
  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax1 o4 X, Z# ~3 D; J$ M2 C
    $args = $args[0];+ s* f5 c; t' X, {
  }
! Y2 D/ X# q$ k- V! J3 {  _db_query_callback($args, TRUE);
  y2 `! X) m' a0 v* Q3 n8 b  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);1 r' c( w, [) i) I
 6 L' R4 a  N& W" S( s9 q
  /*" q3 }! U8 X& x7 T/ w& c
   * Integrating multiple read/write databases
% F/ u* o* |8 |! H" {! m/ b   */
/ J# v6 q6 p" k# W$ ?% P) ]. L7 x  if(!db_lock_master() && strpos(strtolower($query), "select") === 0 && strpos(strtolower($query), "last_insert_id") === FALSE){
: T7 _$ c, @( _: \0 y% A    $commits   = array('alter', 'insert', 'update', 'delete', 'flush', 'lock','create');
( z$ N: r# e9 V2 r/ @    $is_commit = false;
  K2 j7 ]+ D) r& i* R# |) U& A    foreach($commits as $type) {
' E4 c  F! c# t      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- k: z2 \. r2 [! k6 u# b# k% h
        $is_commit = true;
* T/ \) H' E& G' q5 o) {% J      }
% Q% F; {# g% i! J    }
1 L- o6 v' M( k4 B& h- B % J4 X. R: A: N2 L3 c
    if($is_commit){) v4 f! Z: [; J$ q) {" e0 N
      db_set_active('default');
" j& N0 }/ d; l( [, {' ]( c+ R      //drupal_set_message('default');
, T2 I$ C2 w% F* K( a3 M$ n    } else{1 ]6 {1 `7 Q8 Z. z9 ]; v! L
      db_set_active('readonly');: I3 n: ]# u1 }5 X+ O+ i
      //drupal_set_message('readonly');
- Z+ P  ?4 E& u    }  [# f' G6 }- G: j
  }/ d& ^* f  u6 K; H5 D& Q
  else {
/ c6 v, d- t$ q) e) X2 ^    db_set_active('default');
) y3 W( |4 X; D1 [$ h7 h6 U! Q- i9 @  }+ n; T) ]/ q+ p
  /*& t' c! X& q) R" v( _; a/ n
   * End read/write router
5 B; f( ?  W' A! Y) S* B# Z   */$ _1 w+ \. W3 @4 ]" M" ?; t5 g% i! }" J
 ) Y" e3 m- C# n; O6 \1 V
  return _db_query($query);! R, B2 b/ n. Z3 w% t6 O
}, o5 n; ~  p! \# C' B* E9 F
 
& B9 n/ S: U* v  |& X; cfunction db_lock_master($lock = null) {
" n" b- p$ k0 v+ Y: O  static $lock_master = false;
; c- P& T" Y0 p1 S  if (is_null($lock)) {% b& S4 v# G; k! s
    return $lock_master;8 Q4 o, l- x+ V3 Y  q
  }
+ z& l# f6 K2 s* @  X% g  else {
% u4 P& w: g. m1 x    $lock_master = $lock;
. r, N* w* t4 B# r& U5 `    return $lock_master;
% Y( v4 ^; P" V1 e  }
; x2 _& \" _7 _& M. D/ p9 q  y}

最后,该代码只能支持一个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, 11-12-2025 07:12 , Processed in 0.196150 second(s), 75 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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