Tutoriel sur la mise en place d'un serveur MySQL multiple-instances

ska_rOOt

Ce tutoriel a pour objectif de vous aider à configurer MySQL avec plusieurs instances. Ainsi vous pourrez obtenir sur la même machine plusieurs serveurs pouvant être attribués à des administrateurs différents (un peu comme les hébergeurs). Bien que cela ne soit pas obligatoire mais préconisé, les répertoires de stockage des fichiers de base sont distincts. On ne consomme pas plus de ressources qu'avec un seul serveur. Cette manipulation a été testée sur Fedora Core 4, Apache 2, MySQL 4.1.10.

Pour réagir à ce tutoriel, un espace de dialogue vous est proposé sur le forum : Commentez

- Titre : Tutoriel sur la mise en place d'un serveur MySQL multiple-instances

- Auteur : ska_rOOt

- Parution : 28 septembre 2005

- Mise à jour : 22 mars 2016

- Licence :

Sommaire

- I. Prérequis

- II. Information sur mysqld_multi

- III. Préparation

- IV. Fichier de configuration

- V. Première utilisation

- VI. phpMyAdmin

- VII. Démarrage automatique au boot

- VIII. Conclusion et remerciements

I - Prérequis

Éléments requis pour la réalisation de ce tutoriel :

- un système d'exploitation Linux ;

- un serveur HTTP ;

- un serveur MySQL 4.1.x.

II - Information sur mysqld_multi

mysqld_multi est un programme livré avec MySQL. Il sert à gérer plusieurs serveurs utilisant différents sockets Unix et ports TCP/IP sur la même machine.

Pour fonctionner, le programme lit un fichier de configuration dans lequel sont référencés les différents groupes (serveurs de base de données) ainsi que le moyen d'y accéder.

Ce programme se substitue au démon mysqld pour démarrer un, plusieurs, ou tous les serveurs. On peut, comme mysqld, configurer le système pour que le service se lance au démarrage de la machine. Cette manipulation est expliquée à la fin du tutoriel.

III - Préparation

Ce tutoriel n'étant ni destiné à vous faire découvrir le monde Unix, ni faire de vous un administrateur Web, nous partirons du fait que l'on a déjà installé Linux ainsi qu'un serveur HTTP.

Pour l'exemple, et vu que les tests ont été réalisés sur ce type de système, les commandes et les chemins des répertoires utilisés sont ceux d'une distribution Fedora Core 4 installée par défaut pour une station de travail. Je ne détaillerai ici ni la configuration de Fedora, ni celle d'Apache, ni celle de MySQL.

Toutefois, le service mysqld n'étant pas démarré par défaut, vous pouvez l'activer après vous être logué en tant que super-utilisateur (root) et en tapant :

1. # /etc/init.d/mysqld start

Ce qui aura pour effet, par l'intermédiaire du sous-programme mysql_install_db, d'instaurer une première base de données nommée « mysql » contenant les privilèges nécessaires à une première utilisation ainsi qu'à la suite de ce tutoriel.

Si, comme prévu, le service mysqld fonctionne, il est maintenant temps de l'arrêter. Pour vérifier s'il est actif :

1. # ps aux | grep mysqld

vous donnera ceci :

vérification process

Pour arrêter le service mysqld :

1. # /etc/init.d/mysqld stop

Nous allons à présent créer les différents répertoires qui serviront aux serveurs à stocker leurs fichiers. Il est important d'en avoir un par serveur, cela afin d'éviter des erreurs irrécupérables.

Mettons-nous comme objectif de créer deux serveurs (vous pourrez en créer autant que vous voulez). Une fois reconnu comme utilisateur root, tapez :

1. # mkdir /var/lib/mysql1 /var/lib/mysql2

Sur Fedora Core 4, avec installation de MySQL natif, le système crée un utilisateur et un groupe nommés « mysql ». Il nous faut maintenant donner à cet utilisateur le droit de travailler avec ces répertoires :

1. # chown -R mysql:mysql /var/lib/mysql1 /var/lib/mysql2

Le programme mysqld_install_db est utilisé pour initialiser un serveur proprement avec un répertoire de stockage des fichiers de base. Mais comme nous en avons la possibilité, étant donné qu'il s'agit de la même version de moteur, dupliquons simplement le répertoire contenant les privilèges primaires de la base mysql installée par défaut (dans ma configuration, /var/lib/mysql/mysql) dans les répertoires respectifs des nouveaux serveurs.

Si vous n'êtes pas sûr de la localisation du répertoire, ouvrez le fichier my.cnf (/etc/my.cnf) et cherchez la variable datadir qui devrait contenir le chemin d'accès recherché.

1. # cp -Rp /var/lib/mysql/mysql /var/lib/mysql1/

2. # cp -Rp /var/lib/mysql/mysql /var/lib/mysql2/

IV - Fichier de configuration

Le fichier de configuration de mysqld se trouve (suivant les distributions) dans /etc/ et se nomme my.cnf

On pourrait utiliser ce fichier pour la configuration de mysqld_multi, mais par sécurité (afin de laisser la possibilité d'un éventuel retour), nous allons en créer un autre.

Comme dit précédemment, nous avons comme objectif dans ce tutoriel d'installer deux serveurs distincts, mais rien ne vous empêche d'en créer autant que vous voulez, il suffira d'adapter les répertoires nécessaires et les paramètres de groupes ([mysqldX] dans le fichier de configuration, X représentant l'identifiant du serveur) pour chacun d'entre eux.

Avant de remplir le fichier de configuration, il convient de vérifier que les répertoires suivants existent. Si ce n'est pas le cas, veuillez adapter les chemins à votre configuration système.

- Répertoire de lancement du programme (par défaut : /usr/bin).

- Répertoire de stockage des données et des sockets (par défaut : /var/lib/mysql).

- Répertoire de stockage des logs (par défaut : /var/log).

- Répertoire de stockage des processus (par défaut : /var/run/mysqld).

- Répertoire d'installation du serveur (par défaut : /var/lib).

Entrons dans le vif du sujet, ouvrez votre éditeur de texte préféré et créez le fichier /etc/multi_my.cnf (ou le nom de votre choix) comme indiqué ci-dessous :

1. # configuration principale de mysqld_multi

2. # l'utilisateur multi_user est necessaire pour que

3. # le programme puisse arreter les moteurs.

4. [mysqld_multi]

5. mysqld = /usr/bin/mysqld_safe

6. mysqladmin = /usr/bin/mysqladmin

7. user = multi_user

8. password = mypass

10. # configuration d'un premier serveur

11. [mysqld1]

12. # repertoire de stockage des fichiers de base

13. datadir=/var/lib/mysql1

14. # chemin du socket (imperativement different pour chaque serveur)

15. socket=/var/lib/mysql1/mysql.sock1

16. # port (imperativement different pour chaque serveur)

17. port=3306

18. # pour compatibilite avec anciens serveurs

19. old_passwords=1

20. # chemin des fichiers de log

21. err-log=/var/log/mysqld1.log

22. # chemin des processus

23. pid-file=/var/run/mysqld/mysqld.pid1

24. # utilisateur proprietaire du processus

25. user = mysql

27. # configuration d'un second serveur

28. [mysqld2]

29. datadir=/var/lib/mysql2

30. socket=/var/lib/mysql2/mysql.sock2

31. port=3307

32. old_passwords=1

33. err-log=/var/log/mysqld2.log

34. pid-file=/var/run/mysqld/mysqld.pid2

35. user = mysql

37. # configuration serveur maître

38. [mysql.server]

39. user=mysql

40. basedir=/var/lib

Enregistrez votre fichier, c'est fini pour la configuration mysqld_multi.

V - Première utilisation

Passons aux choses sérieuses, nous allons mettre en route mysqld_multi.

Par défaut, le programme utilise (comme mysqld) le fichier de configuration my.cnf. Nous devons donc lui dire qu'il faut utiliser notre fichier fraîchement créé. Pour ce faire, nous nous servirons du paramètre --config-file (pour plus d'information -> man mysqld_multi)

Syntaxe d'utilisation :

1. mysqld_multi [options] {start|stop|report} [GNR[,GNR]...]

mysqld_multi prend comme paramètre : start, stop ou report suivi des identifiants de serveurs à démarrer. Pour rappel, ils sont repérés par le numéro placé derrière chaque intitulé [mysqldX] dans la configuration. Mais on peut aussi mettre un panel de serveurs (exemple 2-6 démarrera les serveurs 2 à 6) ou ne rien mettre, auquel cas il démarrera tous les serveurs présents dans le fichier de configuration.

Nous démarrerons les serveurs 1 et 2 (pour l'exemple)

1. # /usr/bin/mysqld_multi --config-file=/etc/multi_my.cnf start 1,2

Une des nombreuses particularités du système Linux est de pouvoir vérifier en temps réel le contenu d'un fichier log. Ceci est réalisé à l'aide de la commande « tail ».

Ouvrons deux terminaux, et lançons dans chacun d'entre eux une commande tail :

1. # tail -f /var/log/mysqld1.log

2. # tail -f /var/log/mysqld2.log

Si tout va bien, on doit voir ceci :

mysql1.log

mysql2.log

Il faut à présent créer les droits dans les bases MySQL pour que l'utilisateur du programme mysqld_multi (multi_user dans notre fichier de configuration) puisse fermer les instances à son gré.

1. # mysql -u root -S /var/lib/mysql1/mysql.sock1 -p -e "GRANT SHUTDOWN ON *.* TO multi_user@localhost IDENTIFIED BY 'mypass'"

2. # mysql -u root -S /var/lib/mysql2/mysql.sock2 -p -e "GRANT SHUTDOWN ON *.* TO multi_user@localhost IDENTIFIED BY 'mypass'"

Vous pouvez maintenant fermer n'importe quelle instance de serveur en tapant la commande suivante (par exemple pour arrêter le serveur 1) :

1. # mysqld_multi --config-file=/etc/multi_my.cnf stop 1

Vérifiez dans le terminal surveillant le fichier log :

mysqld_close

VI - phpMyAdmin

Afin d'offrir aux administrateurs la possibilité de gérer agréablement leur(s) serveur(s), nous installerons également phpMyAdmin, une interface réalisée en PHP qui permet de gérer toutes les actions courantes (privilèges, projections, insertions, paramétrages, etc.) sur MySQL à travers un visuel convivial.

Vous trouverez les sources de ce programme à cette adresse :

http://www.phpmyadmin.net/home_page/

La version disponible à l'heure ou j'écris cet article est : phpMyAdmin-2.6.4-pl1.tar.bz2

Téléchargez l'archive bzip2 dans le répertoire de votre choix (exemple : /home/toto/). Placez-vous dans le répertoire web d'Apache (par défaut : /var/www/html) et décompressez l'archive.

1. # cd /var/www/html

2. # bzip2 -d /home/toto/phpMyAdmin-2.6.4-pl1.tar.bz2

3. # tar -xvvf /home/toto/phpMyAdmin-2.6.4-pl1.tar

Nous allons créer deux répertoires phpMyAdmin nommés sqladmin1 et sqladmin2 :

1. # mv phpMyAdmin-2.6.4-pl1 sqladmin1

2. # cp -Rp sqladmin1 sqladmin2

Modifions le fichier sqladmin1/config.inc.php ainsi :

1. $cfg['PmaAbsoluteUri']              = 'http://domaine_serveur_http/sqladmin1/';

2. $cfg['Servers'][$i]['port']         = '3306';

3. $cfg['Servers'][$i]['socket']       = '/var/lib/mysql1/mysql.sock1';

4. $cfg['Servers'][$i]['connect_type'] = 'socket';

5. $cfg['Servers'][$i]['auth_type']    = 'http';

Modifions le fichier sqladmin2/config.inc.php à présent :

1. $cfg['PmaAbsoluteUri']              = 'http://domaine_serveur_http/sqladmin2/';

2. $cfg['Servers'][$i]['port']         = '3307';

3. $cfg['Servers'][$i]['socket']       = '/var/lib/mysql2/mysql.sock2';

4. $cfg['Servers'][$i]['connect_type'] = 'socket';

5. $cfg['Servers'][$i]['auth_type']    = 'http';

Vous pouvez maintenant vous connecter à phpMyAdmin à l'adresse suivante :

serveur 1 = http://localhost/sqladmin1/ ( root sans mot de passe )

serveur 2 = http://localhost/sqladmin2/ ( root sans mot de passe )

Profitez de l'interface pour créer un nouvel utilisateur avec mot de passe et tous les privilèges (GRANT ALL PRIVILEGES). Puis (je dirais : surtout) supprimez l'utilisateur root.

Faites attention à ne pas supprimer l'utilisateur multi_user ! Cela n'a pas de graves conséquences, mais vous ne pourriez plus arrêter l'instance de ce serveur avec la commande mysqld_multi.

Une fois les modifications de privilèges réalisées, modifiez les deux fichiers config.inc.php afin qu'ils correspondent avec le nom d'utilisateur ayant tous les privilèges.

1. $cfg['Servers'][$i]['user']         = 'utilisateur_admin';

Modifiez les droits sur les répertoires sqladmin pour empêcher tout accès direct aux fichiers. Seul l'utilisateur d'Apache doit pouvoir y avoir accès (dans ma config : apache) :

1. # chown -R apache:apache /var/www/html/sqladmin1/ /var/www/html/sqladmin2/

2. # chmod -R go-wrx /var/www/html/sqladmin1/ /var/www/html/sqladmin2/

Puis créez un fichier .htaccess dans chaque répertoire « sqladmin » :

1. <Files config.inc.php>

2. Deny from all

3. </Files>

C'est fini pour phpMyAdmin et sa sécurité, vous pouvez dormir tranquille…

VII - Démarrage automatique au boot

Il ne reste plus qu'à créer un script pour automatiser le lancement des serveurs voulus au démarrage de la machine. Ouvrez à nouveau votre éditeur de texte et copiez/collez le script ci-dessous. Enregistrez-le sous /etc/init.d/multi_mysqld.

N'oubliez pas d'ajouter les références de serveurs à démarrer derrière la commande mysqld_multi si vous ne voulez en démarrer qu'une partie.

1. #!/bin/bash

2. #

3. # multi_mysqld       Ce script permet de demarrer ou d'arreter

4. #                    le programme MySQL (mysqld_multi).

5. #

6. # chkconfig: - 64 36

7. # description:    MySQL database servers.

8. # processname: mysqld_multi

9. # config: /etc/multi_my.cnf

10. # Source function library.

11. . /etc/rc.d/init.d/functions

12. # Source networking configuration.

13. . /etc/sysconfig/network

14. # Nom du programme

15. prog="MySQL multi-serveurs"

16. # Chemin du fichier de configuration

17. conf="/etc/multi_my.cnf"

18. # Chemin du fichier de log

19. err_m="/var/log/multi_mysqld.log"

20. # deco

21. sep="*--------------------------------*"

23. test_var()

24. {

26. variable="$1"

27. type_rech="$2"

28. msg=""

30. if [ $type_rech = "x" ];then

31. msg="exécutable"

32. else

33. msg="lisible"

34. fi

36. # extraction des donnees

37. awk 'BEGIN{FS="="}($1 ~ /^'$variable'/){print $2;}' "$conf" | sed 's/[ \t]*//' 2>/dev/null > /tmp/.tmpfic

39. # test d'existence des fichiers en lecture et repertoires

40. retour=`awk 'function TestDir(Rep)

41. {

42. Cmd = "test -'$type_rech' " Rep ";echo $?"

43. Cmd|getline Result

44. close(Cmd)

45. if (Result==1) return 0

46. if (Result==0) return 1

47. print Result

48. }

49. {

50. if (TestDir($1)) printf "%-40s %s\n","'$variable'="$1,"OK"

51. else printf "%-40s %s %s\n","'$variable'="$1,"non trouvé ou non","'$msg'"

52. }' /tmp/.tmpfic 2>/dev/null`

53. echo "$retour"

54. }

56. # fonction qui verifie l'existence d'une variable de configuration

57. get_mysql_option()

58. {

60. result=`sed -n "s/^[ \t]*$2[ \t]*=[ \t]*//p" "$1" 2>/dev/null | tail -n 1`

61. if [ -z "$result" ]; then

62. # non trouve retourne KO

63. result="KO"

64. else

65. # retire les quotes et commentaires

66. dequoted=`echo "$result" | sed "s/^'\([^']*\)'.*$/\1/"`

67. if [ x"$dequoted" != x"$result" ]; then

68. result="$dequoted"

69. else

70. dequoted=`echo "$result" | sed 's/^"\([^"]*\)".*$/\1/'`

71. if [ x"$dequoted" != x"$result" ]; then

72. result="$dequoted"

73. else

74. result=`echo "$result" | sed 's/^\([^ \t#]*\).*$/\1/'`

75. fi

76. fi

77. fi

78. }

80. # teste des variables de configuration

81. get_mysql_option $conf datadir

82. datadir="$result"

83. get_mysql_option $conf socket

84. socketfile="$result"

85. get_mysql_option $conf err-log

86. errlogfile="$result"

87. get_mysql_option $conf pid-file

88. mypidfile="$result"

90. # fonction qui etablit le message d'erreur

91. get_params_ok()

92. {

93. retour=""

94. if [ ! -r "$1" ]; then

95. retour="Fichier de configuration introuvable : $1"

96. return -1

97. fi

98. if [ "$2" = "KO" ]; then

99. retour="Aucun paramètre datadir trouvé !"

100. return -1

101. fi

102. if [ "$3" = "KO" ]; then

103. retour="Aucun paramètre socket trouvé !"

104. return -1

105. fi

106. if [ "$4" = "KO" ]; then

107. retour="Aucun paramètre err-log trouvé !"

108. return -1

109. fi

110. if [ "$5" = "KO" ]; then

111. retour="Aucun paramètre pid-file trouvé !"

112. return -1

113. fi

114. if [ ! -d "$2" ]; then

115. retour="Répertoire fichiers MySQL ( datadir ) introuvable !"

116. return -1

117. fi

118. }

120. # demarrage

121. start()

122. {

123. # teste si au moins un serveur peut demarrer

124. get_params_ok $conf $datadir $socketfile $errlogfile $mypidfile

126. # si test ko

127. if [ ! -z "$retour" ]; then

128. # log multi_mysqld.log

129. touch "$err_m"

130. echo `LC_ALL=fr_FR date '+%A %d %B %Y %H:%M:%S'` " : $retour">>"$err_m"

131. echo $"Démarrage $prog: "

132. action $"$retour" /bin/false

133. return -1

134. fi

136. # execution de mysqld_multi

137. /usr/bin/mysqld_multi --config-file="$conf" start >/dev/null 2>&1

138. ret=$?

139. if [ $ret -eq 0 ]; then

140. # si tout ok

141. sleep 2

142. action $"Démarrage $prog: " /bin/true

143. else

144. # si non

145. action $"Démarrage $prog: " /bin/false

146. fi

147. return $ret

148. }

150. # arret

151. stop()

152. {

153. # teste les parametres de configuration

154. get_params_ok $conf $datadir $socketfile $errlogfile $mypidfile

156. # si test ko

157. if [ ! -z "$retour" ]; then

158. # log multi_mysqld.log

159. touch "$err_m"

160. echo `LC_ALL=fr_FR date '+%A %d %B %Y %H:%M:%S'` " : $retour">>"$err_m"

161. echo $"Démarrage $prog: "

162. action $"$retour" /bin/false

163. return -1

164. fi

166. # execution de mysqld_multi

167. /usr/bin/mysqld_multi --config-file="$conf" stop >/dev/null 2>&1

168. ret=$?

169. if [ $ret -eq 0 ]; then

170. # si tout ok

171. sleep 1

172. action $"Arrêt $prog: " /bin/true

173. else

174. # si non

175. action $"Arrêt $prog: " /bin/false

176. fi

177. return $ret

178. }

180. restart()

181. {

182. stop

183. start

184. }

186. config()

187. {

188. # si fichier de configuration existe

189. if [ ! -r "$conf" ]; then

190. echo "fichier de configuration introuvable : $conf"

191. echo $sep

192. action $"Lecture fichier de configuration $prog" /bin/false

193. else

194. # affichage sans les commentaires et sans espaces ni tabulations

195. echo $sep

196. echo "| Lecture fichier configuration  |"

197. echo $sep

198. awk '! (/^ *#/ || /^$/) { print $0 }' "$conf" 2>/dev/null | sed 's/[ \t]*=[ \t]*/=/'

199. echo $sep

200. action $"Lecture fichier de configuration $prog" /bin/true

201. fi

202. }

204. config_test()

205. {

206. # si fichier de configuration existe

207. if [ ! -r "$conf" ]; then

208. echo "fichier de configuration introuvable : $conf"

209. echo $sep

210. action $"Test fichier de configuration $prog" /bin/false

211. else

213. # verification de l'existence des valeurs de chaque variable

214. echo $sep

215. echo "| Test des variables nécessaires |"

216. echo $sep

217. test_var "err-log" "r"

218. test_var "datadir" "d"

219. test_var "mysqld" "x"

220. test_var "mysqladmin" "x"

221. test_var "basedir" "d"

222. rm -f /tmp/.tmpfic 2>/dev/null

223. echo $sep

224. action $"Test du fichier de configuration $prog" /bin/true

225. fi

226. }

228. case "$1" in

229. start)

230. start

231. ;;

232. stop)

233. stop

234. ;;

235. status)

236. status mysqld

237. ;;

238. restart)

239. restart

240. ;;

241. config)

242. config

243. ;;

244. config_test)

245. config_test

246. ;;

247. *)

248. echo $"Usage: $0 {start|stop|status|restart|config|config_test}"

249. exit 1

250. esac

251. exit $?

Enregistrons-le et rendons-le exécutable.

1. # chmod +x /etc/init.d/multi_mysqld

À ce stade, vous n'avez plus besoin de passer par la commande /usr/bin/mysqld_multi pour gérer l'ensemble de vos serveurs. Par exemple, je veux démarrer tous mes serveurs :

1. # /etc/init.d/multi_mysqld start

démarrage

Le script permet aussi de réaliser deux autres tâches intéressantes, le paramètre « config » affichera le contenu du fichier de configuration épuré, le paramètre « config_test » affichera le résultat du test d'existence des valeurs de variables déclarées.

J'ai trouvé pratique de pouvoir vérifier l'intégrité du fichier de configuration avant de lancer le démon, notamment lors de la création d'une nouvelle instance.

1. # /etc/init.d/multi_mysqld config_test

Et voici le résultat du test d'intégrité de notre fichier de configuration :

test de la configuration

Il ne nous reste plus qu'à configurer le system V :

1. # chkconfig --add multi_mysqld

2. # chkconfig --level 345 multi_mysqld on

3. # chkconfig --level 345 mysqld off

C'est terminé. Bravo ! Vous avez maintenant deux instances de MySQL sur votre machine dès son démarrage !

VIII - Conclusion et remerciements

Nous tenons à remercier Maximilian pour la relecture technique, ced pour sa relecture orthographique et Malick SECK pour la mise au gabarit.