{"id":1023,"date":"2013-07-24T10:30:35","date_gmt":"2013-07-24T08:30:35","guid":{"rendered":"http:\/\/blogdev.alwaysdata.com\/2013\/07\/24\/retour-sur-lincident-mysql1-du-17-juillet-2013\/"},"modified":"2018-02-01T16:30:42","modified_gmt":"2018-02-01T15:30:42","slug":"retour-sur-lincident-mysql1-du-17-juillet-2013","status":"publish","type":"post","link":"https:\/\/blog.alwaysdata.com\/fr\/2013\/07\/24\/retour-sur-lincident-mysql1-du-17-juillet-2013\/","title":{"rendered":"Retour sur l\u2019incident mysql1 du 17 juillet 2013"},"content":{"rendered":"<p>Le mercredi 17 juillet 2013 \u00e0&nbsp;0h02 (UTC+2), une corruption de syst\u00e8me de fichiers s\u2019est produite sur le serveur mysql1. Toutes les bases de donn\u00e9es h\u00e9berg\u00e9es sur ce serveur ont \u00e9t\u00e9 indisponibles durant la nuit, et une faible proportion d\u2019entre elles ont \u00e9t\u00e9 victimes de corruption de donn\u00e9es.<\/p>\n<p>Ce billet revient en d\u00e9tails sur cet incident&nbsp;: ce qu\u2019il s\u2019est pass\u00e9 et les enseignements que nous en tirons. Nous avons essay\u00e9 d\u2019utiliser des termes compr\u00e9hensibles par tous, tout en gardant autant de d\u00e9tails techniques que possible.<\/p>\n<p>Vous pouvez \u00e9galement relire le <a href=\"http:\/\/status.alwaysdata.com\/operation\/116\/detail\/\">compte-rendu<\/a> en direct de l\u2019incident.<\/p>\n<h2>Ce qu\u2019il s\u2019est&nbsp;pass\u00e9<\/h2>\n<h3>Utilisation de bcache<\/h3>\n<p>Commen\u00e7ons par pr\u00e9ciser que le mat\u00e9riel du serveur mysql1 a&nbsp;<a href=\"http:\/\/status.alwaysdata.com\/operation\/114\/detail\/\">\u00e9t\u00e9 chang\u00e9<\/a> le 7&nbsp;juillet&nbsp;afin de l\u2019\u00e9quiper \u00e0&nbsp;la fois de disques SSD et de disques m\u00e9caniques. Le serveur \u00e9tait auparavant uniquement pourvu des disques SSD, mais l\u2019augmentation croissante de l\u2019espace disque a&nbsp;justifi\u00e9 cette \u00e9volution.<\/p>\n<p><a href=\"https:\/\/github.com\/torvalds\/linux\/blob\/master\/Documentation\/bcache.txt\">bcache<\/a> est une technologie int\u00e9gr\u00e9e r\u00e9cemment \u00e0&nbsp;Linux et qui permet de combiner des disques SSD et m\u00e9caniques afin d\u2019obtenir un espace disque important et des performances proches de celles d\u2019un SSD. Nous reviendrons en d\u00e9tails sur le choix de cette technologie dans la seconde partie du billet.<\/p>\n<h3>D\u00e9faillance d\u2019un disque<\/h3>\n<p>Le 16 juillet \u00e0&nbsp;3h29, un des disques du serveur a&nbsp;connu un probl\u00e8me mat\u00e9riel. Le disque a&nbsp;automatiquement \u00e9t\u00e9 \u00e9ject\u00e9 du RAID1, et le serveur a&nbsp;continu\u00e9 \u00e0&nbsp;fonctionner normalement sur le second disque\u200a\u2014\u200ac\u2019est le principe m\u00eame du RAID. Ce genre de probl\u00e8me n\u2019est pas rare. Deux possibilit\u00e9s&nbsp;:<\/p>\n<ul>\n<li>soit le disque est d\u00e9finitivement hors service, auquel cas il faudra le remplacer&nbsp;;<\/li>\n<li>soit le disque a&nbsp;connu un probl\u00e8me temporaire, et il suffit de le \u00ab&nbsp;red\u00e9marrer&nbsp;\u00bb pour qu\u2019il fonctionne \u00e0&nbsp;nouveau normalement.<\/li>\n<\/ul>\n<p>Notre \u00e9quipe a&nbsp;pris connaissance de l\u2019incident le matin\u200a\u2014\u200aaucune astreinte n\u2019a \u00e9t\u00e9 d\u00e9clench\u00e9e, puisque cela n\u2019a aucun impact sur le bon fonctionnement du serveur. Nous avons d\u00e9cid\u00e9 de programmer une intervention pour le soir m\u00eame (c\u2019est une op\u00e9ration qui n\u00e9cessite de mettre le serveur hors service pendant quelques minutes, nous pr\u00e9f\u00e9rons donc le faire \u00e0&nbsp;des heures creuses).<\/p>\n<h3>Red\u00e9marrage du serveur<\/h3>\n<p>\u00c0 23h52, nous red\u00e9marrons le serveur mysql1. Nous constatons que le disque qui \u00e9tait sorti du RAID fonctionne \u00e0&nbsp;nouveau normalement. Mais imm\u00e9diatement, nous observons une corruption du syst\u00e8me de fichiers (XFS) sur lequel les bases de donn\u00e9es sont stock\u00e9es. Apr\u00e8s une investigation rapide, nous comprenons ce qu\u2019il vient de se passer.<\/p>\n<p>Les bases de donn\u00e9es sont stock\u00e9es sur un pseudo-disque bcache, combinaison virtuelle de nos disques m\u00e9caniques et de nos SSD. Lorsque Linux d\u00e9marre, bcache scanne l\u2019ensemble des disques physiques \u00e0&nbsp;la recherche d\u2019une signature. Cette signature, lorsqu\u2019elle est d\u00e9tect\u00e9e, signifie que ce disque fait partie d\u2019un pseudo-disque bcache. bcache combine ensuite les disques trouv\u00e9s et cr\u00e9e le pseudo-disque. Ces signatures sont install\u00e9es une fois pour toutes \u00e0&nbsp;l\u2019installation du syst\u00e8me.<\/p>\n<p>Nos deux disques m\u00e9caniques \u00e9taient en RAID1, ce qui veut dire que les deux disques \u00e9taient strictement identiques et synchronis\u00e9s. C\u2019est, bien entendu, le principe du RAID1&nbsp;: si un disque tombe en panne, l\u2019autre prend la rel\u00e8ve puisqu\u2019il est sa copie conforme. Dans le cas de mysql1, \u00e0&nbsp;23h52, nous avions donc&nbsp;:<\/p>\n<ul>\n<li>le disque d\u00e9faillant qui \u00e9tait rest\u00e9 dans son \u00e9tat de 3h29 (avec des donn\u00e9es \u00ab&nbsp;p\u00e9rim\u00e9es&nbsp;\u00bb)&nbsp;;<\/li>\n<li>le second disque qui contenait les \u00ab&nbsp;vraies&nbsp;\u00bb donn\u00e9es, \u00e0&nbsp;savoir les plus r\u00e9centes.<\/li>\n<\/ul>\n<p>Les deux disques avaient donc, du point de vue de bcache, des signatures identiques. Au red\u00e9marrage du serveur, bcache a&nbsp;donc assembl\u00e9 les SSD avec le disque d\u00e9faillant (le premier trouv\u00e9) plut\u00f4t que le second disque, \u00e0&nbsp;jour. Or les SSD contenaient des donn\u00e9es r\u00e9centes. Nous avions donc un pseudo-disque qui \u00e9tait la combinaison de certaines donn\u00e9es de 23h52 (SSD) et de donn\u00e9es de 3h29 (disque d\u00e9faillant).<\/p>\n<p>\u00c9videmment, ce pseudo-disque ne contenait alors pas des donn\u00e9es coh\u00e9rentes, d\u2019o\u00f9 la corruption de fichiers. Nous avons imm\u00e9diatement d\u00e9mont\u00e9 le syst\u00e8me de fichiers pour recombiner les SSD avec le second disque, avec les donn\u00e9es \u00e0&nbsp;jour. Mais c\u2019\u00e9tait trop tard&nbsp;: le simple fait d\u2019avoir pr\u00e9alablement mont\u00e9 le pseudo-disque bcache avec le disque d\u00e9faillant a&nbsp;entrain\u00e9 des \u00e9critures sur les SSD. Les donn\u00e9es des SSD n\u2019\u00e9taient alors plus coh\u00e9rentes avec le second disque.<\/p>\n<h3>Restauration des donn\u00e9es<\/h3>\n<p>Malgr\u00e9 les corruptions du syst\u00e8me de fichiers, une tr\u00e8s grande proportion des donn\u00e9es restait lisible. Nous avons donc pris la d\u00e9cision de restaurer autant que possible les donn\u00e9es \u00e0&nbsp;jour, plut\u00f4t que de restaurer les sauvegardes de la veille pour tout le&nbsp;monde.<\/p>\n<p>La premi\u00e8re \u00e9tape a&nbsp;\u00e9t\u00e9 de copier l\u2019ensemble des donn\u00e9es (300 Go) sur un serveur temporaire. Par s\u00e9curit\u00e9, nous avons copi\u00e9 une seconde fois les donn\u00e9es, sur un second serveur temporaire. Les donn\u00e9es du premier serveur ont \u00e9t\u00e9 utilis\u00e9es pour d\u00e9marrer MySQL (accessible uniquement en interne) et essayer de r\u00e9cup\u00e9rer le maximum de bases possible, ce qui a&nbsp;entrain\u00e9 des modifications sur les fichiers. Les donn\u00e9es du second serveur n\u2019\u00e9taient l\u00e0 que pour nous permettre de recommencer le processus, si besoin.<\/p>\n<p>La restauration des donn\u00e9es (qui consistait essentiellement \u00e0&nbsp;ex\u00e9cuter \u201cmysqldump\u201d sur chaque base) a&nbsp;pris du temps&nbsp;: la corruption a&nbsp;entra\u00een\u00e9 de nombreux plantages de MySQL, ralentissant l\u2019op\u00e9ration. Une fois que nous avions un dump SQL pour la grande majorit\u00e9 des bases (96 %), nous avons pu d\u00e9marrer la restauration finale sur mysql1 (reformat\u00e9 entre temps). Les 4 % de bases corrompues ont ensuite \u00e9t\u00e9 restaur\u00e9es depuis les sauvegardes de la veille.<\/p>\n<p>Dans certains rares cas, les donn\u00e9es r\u00e9cup\u00e9r\u00e9es que nous pensions saines \u00e9taient finalement en partie corrompues. Les clients concern\u00e9s ont pu nous contacter pour que nous restaurions alors une sauvegarde.<\/p>\n<h2>Diminuer les risques \u00e0&nbsp;l\u2019avenir<\/h2>\n<p>Commen\u00e7ons d\u2019embl\u00e9e par dire que la perte de donn\u00e9es est un risque qu\u2019il est impossible de r\u00e9duire \u00e0&nbsp;z\u00e9ro. Les causes peuvent \u00eatre multiples&nbsp;: bug, erreur humaine, probl\u00e8me mat\u00e9riel, accident majeur, etc. C\u2019est la raison pour laquelle les sauvegardes existent. Cela ne veut toutefois pas dire qu\u2019on ne peut pas r\u00e9duire davantage les risques.<\/p>\n<h3>Utilisation de technologies jeunes<\/h3>\n<p>L\u2019incident a&nbsp;pour origine un bug dans bcache. Il est donc l\u00e9gitime de se demander si l\u2019utilisation de bcache, une technologie relativement jeune, \u00e9tait judicieux.<\/p>\n<p>En r\u00e8gle g\u00e9n\u00e9rale, plus une technologie est jeune, plus le risque qu\u2019elle pr\u00e9sente des dysfonctionnements (mineurs ou majeurs) est \u00e9lev\u00e9. Il faut donc juger si les avantages qu\u2019apportent la technologie justifient la prise de risque. Naturellement, ce jugement \u00e9volue au fil du temps&nbsp;: plus la technologie m\u00fbrit, plus les risques diminuent.<\/p>\n<p>En ce qui concerne bcache, les avantages sont importants&nbsp;: permettre d\u2019augmenter consid\u00e9rablement les performances sans sacrifier l\u2019espace disque. Rappelons que contrairement \u00e0&nbsp;la majorit\u00e9 des h\u00e9bergeurs, nous n\u2019imposons aucune limite sur la taille des bases de donn\u00e9es.<\/p>\n<p>Nous suivons l\u2019\u00e9volution des technologies hybrides SSD\/disque m\u00e9canique depuis d\u00e9j\u00e0 longtemps. Il en existe de nombreuses, au-del\u00e0 de <a href=\"https:\/\/github.com\/torvalds\/linux\/blob\/master\/Documentation\/bcache.txt\">bcache<\/a>&nbsp;:&nbsp;<a href=\"https:\/\/github.com\/torvalds\/linux\/blob\/master\/Documentation\/device-mapper\/cache.txt\">dm-cache<\/a>,&nbsp;<a href=\"http:\/\/www.stec-inc.com\/enhanceio\/\">EnhanceIO<\/a>,&nbsp;<a href=\"https:\/\/github.com\/facebook\/flashcache\/\">FlashCache<\/a>,&nbsp;<a href=\"http:\/\/www.lsi.com\/channel\/products\/storagesw\/Pages\/MegaRAIDCacheCadeSoftware2-0.aspx\">CacheCade<\/a>,&nbsp;<a href=\"http:\/\/sourceforge.net\/projects\/tier\/\">btier<\/a> pour n\u2019en citer qu\u2019une partie. En d\u00e9but d\u2019ann\u00e9e, nous avons test\u00e9 et compar\u00e9 \u00ab&nbsp;en laboratoire&nbsp;\u00bb plusieurs de ces solutions. Au terme de ces tests, nous avons d\u00e9cid\u00e9 d\u2019utiliser bcache sur un serveur de pseudo-production&nbsp;: http11, sur lequel nous avons migr\u00e9 une poign\u00e9e de clients volontaires. Pendant 4&nbsp;mois, ce serveur a&nbsp;tourn\u00e9 avec bcache sans pr\u00e9senter le moindre probl\u00e8me, tout en tenant ses promesses de performances accrues.<\/p>\n<p>Pr\u00e9cisons que bcache, d\u00e9velopp\u00e9 par un ing\u00e9nieur de Google, existe depuis 2010, et est consid\u00e9r\u00e9 comme stable par son auteur depuis 2011\u200a\u2014\u200adate de la derni\u00e8re d\u00e9couverte d\u2019un bug pouvant provoquer des corruptions de donn\u00e9es. Utilis\u00e9 en production par de nombreuses personnes et organisations depuis, il a&nbsp;\u00e9t\u00e9 int\u00e9gr\u00e9 \u00e0&nbsp;Linux en 2013 au terme d\u2019une longue et s\u00e9v\u00e8re revue de code par plusieurs d\u00e9veloppeurs seniors de&nbsp;Linux.<\/p>\n<p>Notre d\u00e9cision d\u2019utiliser bcache en production est parfaitement assum\u00e9e et nous n\u2019estimons pas qu\u2019il s\u2019agisse d\u2019une faute. Le bug, que nous avons depuis&nbsp;<a href=\"http:\/\/thread.gmane.org\/gmane.linux.kernel.bcache.devel\/1842\">remont\u00e9 aux d\u00e9veloppeurs<\/a>, a&nbsp;\u00e9t\u00e9 corrig\u00e9 moins de 2h apr\u00e8s, un dimanche soir. Une telle r\u00e9activit\u00e9 n\u2019est qu\u2019un atout suppl\u00e9mentaire pour bcache.<\/p>\n<h3>Am\u00e9liorer la fiabilit\u00e9 de notre mat\u00e9riel<\/h3>\n<p>Deux \u00e9l\u00e9ments mat\u00e9riels ont, indirectement, conduit au&nbsp;bug&nbsp;:<\/p>\n<ul>\n<li>le fait que le disque ait rencontr\u00e9 un probl\u00e8me temporaire qui a&nbsp;provoqu\u00e9 son \u00e9jection du&nbsp;RAID&nbsp;;<\/li>\n<li>le fait que nos ch\u00e2ssis ne soient pas \u00e9quip\u00e9s de hot swap, nous obligeant \u00e0&nbsp;red\u00e9marrer le serveur pour relancer le disque (ou \u00e0&nbsp;d\u00e9brancher un serveur pour remplacer un disque).<\/li>\n<\/ul>\n<p>Nous allons remplacer l\u2019ensemble de nos serveurs au cours des prochains mois. Parmi leurs avantages, ils seront encore plus fiables qu\u2019actuellement. Nous aurons l\u2019occasion de revenir en d\u00e9tails sur cette migration dans quelques semaines.<\/p>\n<h3>Ajouter une option de redondance<\/h3>\n<p>Plusieurs clients souhaiteraient que nous proposions une option de redondance master\/slave qui permettrait de pallier certains types de pannes, dont l\u2019incident que nous avons eu. Cette option a&nbsp;n\u00e9cessairement un co\u00fbt non n\u00e9gligeable.<\/p>\n<p>Dites-nous dans les commentaires si vous seriez int\u00e9ress\u00e9 par une telle option, qui augmenterait le prix d\u2019un pack d\u2019environ 50&nbsp;%.<\/p>\n<h2>En conclusion<\/h2>\n<p>Environ 300 bases de donn\u00e9es MySQL ont \u00e9t\u00e9 corrompues et ont d\u00fb \u00eatre restaur\u00e9es depuis les sauvegardes de la veille, ce qui repr\u00e9sente moins de 4 % des bases stock\u00e9es sur mysql1, et moins de 1,5 % de l\u2019ensemble des bases MySQL. Chaque client concern\u00e9 a&nbsp;\u00e9t\u00e9 contact\u00e9 par mail, et nous leur r\u00e9it\u00e9rons nos excuses.<\/p>\n<p>Nous pr\u00e9parons de gros changements internes destin\u00e9s \u00e0&nbsp;am\u00e9liorer encore davantage notre fiabilit\u00e9, d\u00e9j\u00e0 tr\u00e8s \u00e9lev\u00e9e. Vous en saurez plus tr\u00e8s bient\u00f4t.<\/p>\n<p>N\u2019h\u00e9sitez pas \u00e0&nbsp;nous faire vos retours et suggestions en commentaires. Nous sommes toujours preneurs. Nous remercions au passage tous ceux qui nous ont apport\u00e9 leur soutien durant cet incident, c\u2019est toujours appr\u00e9ci\u00e9.<\/p>\n<p>Nous souhaitons enfin d\u2019excellentes vacances \u00e0&nbsp;tous ceux qui s\u2019appr\u00eatent \u00e0&nbsp;en prendre\u200a\u2014\u200aet bon courage \u00e0&nbsp;ceux qui en reviennent&nbsp;:)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Le mercredi 17 juillet 2013 \u00e0&nbsp;0h02 (UTC+2), une corruption de syst\u00e8me de fichiers s\u2019est produite sur le serveur mysql1. Toutes les bases de donn\u00e9es h\u00e9berg\u00e9es \u2026 <a class=\"read-more\" href=\"https:\/\/blog.alwaysdata.com\/fr\/2013\/07\/24\/retour-sur-lincident-mysql1-du-17-juillet-2013\/\">Keep reading<\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"wp_typography_post_enhancements_disabled":false,"footnotes":""},"categories":[1],"tags":[159,181,148],"class_list":["post-1023","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-bcache-fr","tag-mysql-fr","tag-panne-fr"],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/posts\/1023","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/comments?post=1023"}],"version-history":[{"count":0,"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/posts\/1023\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/media?parent=1023"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/categories?post=1023"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.alwaysdata.com\/fr\/wp-json\/wp\/v2\/tags?post=1023"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}