{"id":5286,"date":"2016-05-12T16:39:16","date_gmt":"2016-05-12T15:39:16","guid":{"rendered":"http:\/\/blog.capdata.fr\/?p=5286"},"modified":"2019-09-13T13:12:52","modified_gmt":"2019-09-13T12:12:52","slug":"pas-de-la-tarte","status":"publish","type":"post","link":"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/","title":{"rendered":"Pas de la tarte"},"content":{"rendered":"<a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-twitter nolightbox\" data-provider=\"twitter\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Twitter\" href=\"https:\/\/twitter.com\/intent\/tweet?url=https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F5286&#038;text=Article%20sur%20le%20blog%20de%20la%20Capdata%20Tech%20Team%20%3A%20\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"twitter\" title=\"Share on Twitter\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/twitter.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-linkedin nolightbox\" data-provider=\"linkedin\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Linkedin\" href=\"https:\/\/www.linkedin.com\/shareArticle?mini=true&#038;url=https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F5286&#038;title=Pas%20de%20la%20tarte\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"linkedin\" title=\"Share on Linkedin\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/linkedin.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-mail nolightbox\" data-provider=\"mail\" rel=\"nofollow\" title=\"Share by email\" href=\"mailto:?subject=Pas%20de%20la%20tarte&#038;body=Article%20sur%20le%20blog%20de%20la%20Capdata%20Tech%20Team%20%3A%20:%20https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F5286\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"mail\" title=\"Share by email\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/mail.png\" \/><\/a><p>Non vraiment, \u00e7a va pas \u00eatre de la tarte. Et si vous vivez dans une grotte depuis le d\u00e9but de l&#8217;ann\u00e9e, vous ne savez peut \u00eatre pas encore que <a href=\"http:\/\/blogs.microsoft.com\/blog\/2016\/03\/07\/announcing-sql-server-on-linux\/#sm.00001pfer19wrpcwoqff2jscx6zct\">SQL Server doit \u00eatre port\u00e9 sur Linux<\/a>.<\/p>\n<p>D&#8217;ailleurs mister <a href=\"https:\/\/blogs.msdn.microsoft.com\/slavao\/\">Slava Oks<\/a>, le grand gourou de l&#8217;allocation m\u00e9moire dans SQLOS, <a href=\"https:\/\/www.linkedin.com\/pulse\/considering-part-revolution-dont-hesitate-apply-slava-oks?trk=prof-post\">est revenu au bercail<\/a> pour pr\u00eater main-forte \u00e0 l&#8217;\u00e9norme chantier pr\u00e8s de 10 ans apr\u00e8s avoir quitt\u00e9 la dream team du building 35. C&#8217;est un signe qui ne trompe pas.<\/p>\n<p>On a une id\u00e9e relative du <em>quand<\/em> (mi-2017), on a d\u00e9j\u00e0 beaucoup \u00e9voqu\u00e9 le <em>pourquoi<\/em>. Il est encore trop t\u00f4t pour parler du <em>comment<\/em>. Tout ce qu&#8217;on peut formuler pour l&#8217;instant ce sont des hypoth\u00e8ses. C&#8217;est ce qu&#8217;on va faire, essayer de voir o\u00f9 peuvent \u00eatre les grandes difficult\u00e9s de porter SQL Server sur linux, de notre humble point de vue d&#8217;utilisateur &#8211; disons &#8211;\u00a0<em>\u00e9clair\u00e9<\/em> du produit.<\/p>\n<p><strong><span style=\"font-size: 1.5em;\">Pourquoi \u00e7a semble compliqu\u00e9:<\/span><\/strong><\/p>\n<p>Parce que globalement le code de SQL Server a une adh\u00e9rence tr\u00e8s forte avec les primitives win32, et le sous-syst\u00e8me du m\u00eame nom (subsystem win32 = kernel32.dll + advapi32.dll + gdi32.dll + user32.dll). Ces primitives exposent \u00e0 SQL Server tout un framework pour adresser des appels au noyau par exemple :<\/p>\n<p>&#8211; Ouvrir, \u00e9crire, lire, \u00e9tendre, r\u00e9duire un\u00a0fichier&#8230;<br \/>\n&#8211; Ouvrir une socket TCP, \u00e9couter sur un port TCP.<br \/>\n&#8211; Allouer et acc\u00e9der \u00e0 des pages en m\u00e9moire.<br \/>\n&#8211; Synchroniser les acc\u00e8s \u00e0 des ressources partag\u00e9es (principalement des listes cha\u00een\u00e9es de ressources, par exemple les <em>BUFs<\/em>, mais aussi des IO r\u00e9seau ou disque&#8230;)<\/p>\n<p>La plupart de ces actions ne peuvent pas se faire au niveau utilisateur (en <a href=\"https:\/\/en.wikipedia.org\/wiki\/Protection_ring\">ring 3<\/a>), donc Windows fournit un ensemble de primitives qui sont ensuite &#8216;<em>traduites<\/em>&#8216; en quelque sorte par ntdll.dll en language noyau. C&#8217;est ainsi que <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa365747(v=vs.85).aspx\">WriteFile()<\/a> qui est expos\u00e9e par kernel32.dll est link\u00e9e \u00e0 une fonction <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/hardware\/ff567121(v=vs.85).aspx\">ZwWriteFile()<\/a> qui ne peut \u00eatre ex\u00e9cut\u00e9e qu&#8217;en mode noyau (ring 0), qui contient du code sp\u00e9cifique \u00e0 l&#8217;architecture (x64) et un appel au dispatcher parmi d&#8217;autres choses.<\/p>\n<p>On comprend vite que l&#8217;ensemble du code est intimement li\u00e9 \u00e0 l&#8217;impl\u00e9mentation du C sous win32. Typiquement il n&#8217;existe pas d&#8217;IO Completion Port\u00a0sous Linux. Pour chaque composant on va trouver un \u00e9quivalent mais qui ne fonctionne pas tout \u00e0 fait de la m\u00eame fa\u00e7on.<\/p>\n<h2>Opposition de styles ?<\/h2>\n<p>On serait tent\u00e9 d&#8217;imaginer que, m\u00eame si Linux et Windows partagent aujourd&#8217;hui la m\u00eame plateforme d&#8217;ex\u00e9cution qu&#8217;est le x86_64, ils sont tr\u00e8s diff\u00e9rents de conception. En fait ils ne sont pas si diff\u00e9rents que \u00e7a.<\/p>\n<p>Windows tel qu&#8217;on le connait aujourd&#8217;hui a \u00e9t\u00e9 con\u00e7u \u00e0 partir de 1989,\u00a0principalement par <a href=\"https:\/\/www.microsoft.com\/about\/technicalrecognition\/david-cutler.aspx\">Dave Cutler<\/a> qui sortait en 1988 d&#8217;un projet avort\u00e9 chez Digital (MICA\/Prism) et qui avait d\u00e9j\u00e0 une bonne id\u00e9e de comment devait fonctionner un operating system, dans la mesure o\u00f9 il avait d\u00e9j\u00e0 travaill\u00e9 sur VMS pendant 13 ans. Linux a vu le jour \u00e0 peu pr\u00e8s \u00e0 la m\u00eame \u00e9poque que NT, Linus Torvalds terminant la v0.02 aux alentours de 1991, donc dans le m\u00eame contexte technologique, avec le monde des PC d\u00e9j\u00e0 bien \u00e9tabli. Plus troublant encore, leurs origines respectives sont \u00e9galement align\u00e9es sur la m\u00eame p\u00e9riode, le milieu des ann\u00e9es 70 (UNIX pour Linux, et VMS pour Windows NT).<\/p>\n<p>Vu du 8i\u00e8me \u00e9tage, les services in-core des deux noyaux semblent assez similaires, par exemple :<\/p>\n<p>&#8211; Tout le code du noyau est ex\u00e9cut\u00e9 dans un seul et m\u00eame espace m\u00e9moire (contrairement aux micro-kernels), donc les services (object manager, memory manager, etc&#8230;) partagent le m\u00eame pr\u00e9 carr\u00e9 et n&#8217;ont pas besoin de faire transiter de l&#8217;information d&#8217;un espace \u00e0 un autre.<br \/>\n&#8211; Il y a bien une s\u00e9paration induite par x86 entre l&#8217;espace m\u00e9moire r\u00e9serv\u00e9e au noyau et celui r\u00e9serv\u00e9 aux applications, m\u00eame si le d\u00e9coupage est diff\u00e9rent.<br \/>\n&#8211; Le processus a son propre espace d&#8217;adressage.<br \/>\n&#8211; Le noyau abstrait le mat\u00e9riel que ce soit SMP, HT, NUMA, etc&#8230;<\/p>\n<p>A y regarder d&#8217;un peu plus pr\u00e8s il existe quand m\u00eame quelques diff\u00e9rences d&#8217;impl\u00e9mentation des services syst\u00e8mes, qu&#8217;il faut prendre en consid\u00e9ration pour porter le code de SQL Server vers Linux.<\/p>\n<h2>Gestion de la m\u00e9moire :<\/h2>\n<p>La question du 32 bits \u00e9tant \u00e9vacu\u00e9e, que peut-on dire de la gestion de la m\u00e9moire ? L\u00e0 o\u00f9 les choses ont \u00e9t\u00e9 bien faites d\u00e8s le d\u00e9part (et hommage soit rendu \u00e0 Slava) c&#8217;est que la plupart des m\u00e9thodes d&#8217;allocation ont \u00e9t\u00e9 abstraites via des classes expos\u00e9es par le framework de SQLOS : cachestores, userstores, pools, etc&#8230; Donc ce code-l\u00e0 ne devrait pas bouger. C&#8217;est plus ce sur quoi reposent ces classes qui peuvent \u00eatre revues (HeapAlloc \/ VirtualAlloc).<\/p>\n<p>Pour ce qui est du support des Locked Pages, qui devient presque un standard de fait sur x64, il y a un \u00e9quivalent sur Linux dans la famille de fonctions<a href=\"https:\/\/access.redhat.com\/documentation\/en-US\/Red_Hat_Enterprise_MRG\/1.3\/html\/Realtime_Reference_Guide\/sect-Realtime_Reference_Guide-Memory_allocation-Using_mlock_to_avoid_memory_faults.html\"> mlock et mlockall<\/a>, mais il faudrait creuser franchement dans la fonctionnalit\u00e9 car en plus de la garantie de non-pagination, l&#8217;int\u00e9r\u00eat des Locked Pages pour SQL Server est aussi li\u00e9 au fait qu&#8217;il ne n\u00e9cessite <a href=\"https:\/\/blogs.msdn.microsoft.com\/slavao\/2005\/04\/29\/be-aware-using-awe-locked-pages-in-memory-on-64-bit\/\">qu&#8217;un seul appel au PFN Database lock<\/a>, c&#8217;est donc aussi une question de performance. Il n&#8217;est pas certain que le comportement soit similaire sur Linux.<\/p>\n<p>Pour le support des <em>Large Pages<\/em> sur Windows, il y a l&#8217;\u00e9quivalent <a href=\"https:\/\/www.pythian.com\/blog\/performance-tuning-hugepages-in-linux\/\"><em>Huge Pages<\/em><\/a> sur Linux.<\/p>\n<h2>SQLOS \/ Scheduling:<\/h2>\n<p>L\u00e0 il y a quelques diff\u00e9rences notables entre ce que permet Linux par rapport \u00e0 Windows, notamment sur la notion de <em>process<\/em> et de <em>thread<\/em>.<\/p>\n<p>Sous Windows, un processus est concr\u00e8tement repr\u00e9sent\u00e9 par un espace m\u00e9moire et au moins 1 thread, qu&#8217;on appelle thread 0. C&#8217;est ce thread qui porte l&#8217;ex\u00e9cution du code sur le CPU. Un process peut cr\u00e9er plusieurs threads.<\/p>\n<p>Historiquement, sous Linux, c&#8217;est le processus qui porte l&#8217;ex\u00e9cution du code. Il y a eu un d\u00e9but de support des threads POSIX dans le milieu des ann\u00e9es 90 (<em>pThreads<\/em> \/ <em>LinuxThreads<\/em> ) mais l&#8217;impl\u00e9mentation fait qu&#8217;\u00e0 chaque <em>pthread<\/em> sous linux un processus de type <em>LightWeight Process<\/em> \u00e9tait cr\u00e9\u00e9 au niveau du noyau. Et c&#8217;est ce <em>LWP<\/em> qui ex\u00e9cutait le code, ce qui fait ressembler le tout davantage aux fibers plut\u00f4t qu&#8217;aux threads win32. Parmi les limitations principales on peut citer le manque d&#8217;utilisation de la m\u00e9moire locale au thread (les registres), le fait qu&#8217;on soit oblig\u00e9 de cr\u00e9er un thread sp\u00e9cifique pour concentrer la gestion des signaux et respecter la norme POSIX (<em>manager thread<\/em>) et surtout le manque de primitive de synchronisation qui a fait que toute l&#8217;impl\u00e9mentation repose sur les signaux. C&#8217;est pourquoi la plupart des \u00e9diteurs de bases de donn\u00e9es sous Linux n&#8217;ont (pratiquement) jamais chang\u00e9 leur mod\u00e8le multi-processus \/ m\u00e9moire partag\u00e9e (Oracle jusqu&#8217;\u00e0 la 12c, postgreSQL et Sybase jusqu&#8217;\u00e0 la 15.7, MySQL \u00e9tant une exception).<\/p>\n<p>Vers 2005, Red Hat (Ulrich Drepper \/ Ingo Molnar) proposa une alternative appel\u00e9e Native POSIX Thread Library (<a href=\"https:\/\/www.akkadia.org\/drepper\/nptl-design.pdf\">NPTL<\/a>) pour am\u00e9liorer le support des threads en version 2.5 \u00a0du noyau, bien plus prometteuse notamment sur la synchronisation, avec l&#8217;apparition des <a href=\"https:\/\/www.akkadia.org\/drepper\/futex.pdf\">futexes<\/a>\u00a0(Fast Userspace Mutexes). L&#8217;utilisation de NPTL est maintenant g\u00e9n\u00e9ralis\u00e9e.<\/p>\n<p>Depuis le noyau 2.6, la s\u00e9mantique se rapproche de Windows dans la mesure o\u00f9 l&#8217;unit\u00e9 d&#8217;ex\u00e9cution est bien devenue le thread. Un thread a un Thread ID et un Thread\u00a0Group ID qui correspond grosso-modo au PID. Lorsqu&#8217;on appelle <em>clone<\/em> ou <em>fork<\/em> depuis un autre thread, soit on va cr\u00e9er un nouveau couple (TGID,TID), donc un nouveau process, soit un nouveau TID en conservant le TGID du cloneur, donc un nouveau thread dans le processus courant. La notion de process est devenue plus un espace m\u00e9moire et un ensemble de threads sous le m\u00eame TGID aujourd&#8217;hui.<\/p>\n<p>Si on en revient \u00e0 SQL Server, on peut se demander quelle sera la strat\u00e9gie adopt\u00e9e. J&#8217;imagine mal que soient sortis les workers syst\u00e8mes (CHECKPOINT, LOG MANAGER, SIGNAL HANDLER, RESSOURCE MONITOR, les TASK MANAGERs, etc&#8230;), du process address space de l&#8217;ex\u00e9cutable principal et discuter via de la m\u00e9moire partag\u00e9e. \u00c7a serait pire qu&#8217;un grand coup de pied dans la fourmili\u00e8re. D&#8217;ailleurs, les t\u00e2ches syst\u00e8me dans Sybase ASE par exemple, qui est un peu le faux jumeau de SQL Server, sont int\u00e9gr\u00e9s \u00e0 base de threads. Ce sont les schedulers, les engines dans le jargon, qui avaient \u00e9t\u00e9 sortis sous forme de processus, mais ils peuvent \u00eatre r\u00e9int\u00e9gr\u00e9s sous forme de threads depuis la version 15.7.<\/p>\n<p>Donc il y a fort \u00e0 parier que les workers seront port\u00e9s sur NPTL qui est la version la plus aboutie du support des threads POSIX sur Linux. Quant aux fibers, ils pourraient \u00eatre remplac\u00e9s par des threads POSIX version LinuxThreads mais vu les limitations, ils pourraient carr\u00e9ment ne pas \u00eatre port\u00e9s du tout.<\/p>\n<p>Pour ce qui est du scheduler coop\u00e9ratif, tout se passe en usermode donc on ne voit pas bien ce qui pourrait poser probl\u00e8me. La valeur des quantums est presque \u00e9quivalente entre les 2 OS.<\/p>\n<p>J&#8217;ai remarqu\u00e9 un fait int\u00e9ressant en comparant le quantum interne de SQLOS de 4ms et celui de Sybase ASE (timeslice de \u00a0100ms + plus une p\u00e9riode de grace de 500 ticks d&#8217;horloge par d\u00e9faut), et la diff\u00e9rence est ENORME. Il faut dire que le timeslice sur ASE n&#8217;a pas \u00e9volu\u00e9 depuis \u00e0 peu pr\u00e8s 10 ans alors que la fr\u00e9quence des processeurs \u00e0 continu\u00e9 de progresser. Donc le probl\u00e8me serait-il plut\u00f4t c\u00f4t\u00e9 Sybase ? \u00a0On verra bien \u00a0si les 4ms de SQL Server \u00a0tiennent toujours sur Linux. Je suis d&#8217;avis que \u00e7a ne changera pas.<\/p>\n<p>On risque de voir quelques diff\u00e9rences toutefois sur tout ce qui est pr\u00e9empt\u00e9. Lorsque l&#8217;ex\u00e9cution va \u00e9chapper \u00e0 SQLOS sous Linux, le thread va h\u00e9riter d&#8217;une priorit\u00e9 et d&#8217;un quantum qui vont fluctuer selon sa consommation CPU. Plus le thread consomme de la CPU, plus sa priorit\u00e9 va baisser par rapport aux autres (<em>decay<\/em>) et plus son quantum par contre va augmenter (entre 10 et 100ms). C&#8217;est l\u00e0 une diff\u00e9rence avec Windows car un thread win32 h\u00e9rite de la priorit\u00e9 de base du processus puis peut augmenter mais ne peut jamais repasser sous sa priorit\u00e9 de d\u00e9part.<\/p>\n<p>C&#8217;est une mani\u00e8re \u00e9l\u00e9gante pour Linux de permettre un acc\u00e8s \u00e9quitable aux ressources entre les diff\u00e9rentes applications, en infligeant une p\u00e9nalit\u00e9 aux threads qui consomment le plus, tout en leur autorisant une plus grande plage de travail lors de leur prochaine ex\u00e9cution. Le martinet et le bonbon, en quelque sorte&#8230;<\/p>\n<h2>Quelques exemples de primitives \u00e0 substituer:<\/h2>\n<p>Un autre point cl\u00e9 du d\u00e9veloppement va \u00eatre de trouver des rempla\u00e7ants \u00e0 certaines fonctionnalit\u00e9s du type :<\/p>\n<h3><strong>WaitForSingleObject \/\u00a0WaitForMultipleObject<\/strong> :<\/h3>\n<p>Sur Windows, un thread peut bloquer sur n&#8217;importe quel handle : un fichier, un event, un mutex, un process, un s\u00e9maphore, un timer, une notification, etc&#8230; Il appelle l&#8217;une de ces deux primitives en lui passant le handle de l&#8217;objet, plus quelques autres informations comme le timeout par exemple (SQL Server utilise massivement INFINITE pour ce param\u00e8tre). \u00a0Typiquement un thread est associ\u00e9 \u00e0 un event par exemple, et l&#8217;initialise \u00e0 False, puis bloque dessus avec un timeout \u00e0 INFINITE. Un autre thread signale le premier en passant son event \u00e0 True, et celui-ci peut commencer \u00e0 travailler. C&#8217;est comme \u00e7a que fonctionne la yield routine au niveau SQLOS, le worker sortant signale le premier worker en runnable list.<\/p>\n<p>Sous Linux, les processus et les threads utilisent principalement des signaux pour discuter. Les signaux sont de simples interruptions logicielles utilis\u00e9es pour qu&#8217;un programme puisse discuter avec un autre.\u00a0Par exemple, les processus backends PostgreSQL (qui mat\u00e9rialisent les connexions utilisateur) correspondent avec le processus postmaster (le processus initial) via des signaux, comme SIGINT, \u00e9quivalent de Ctrl+C, pour annuler une requ\u00eate en cours d&#8217;ex\u00e9cution.<\/p>\n<p>Comme on part du principe que ce ne sera pas du multiprocess mais bien toujours du multithread, \u00e0 base de NPTL, on suppose que les workers se signaleront entre eux via les futexes, qui vont permettre de se rapprocher de ce que donnent les events sur win32. Les futexes supportent des notions telles que le timeout y compris l&#8217;\u00e9quivalent d&#8217;INFINITE (timeout \u00e0 NULL) et la synchronisation sur plus d&#8217;un \u00e9v\u00e9nement comme WaitForMultipleObjects.<\/p>\n<h3>Interlocked :<\/h3>\n<p>Les fonctions <a href=\"https:\/\/msdn.microsoft.com\/fr-fr\/library\/windows\/desktop\/ms684122(v=vs.85).aspx\">Interlocked<\/a> permettent de construire ce qu&#8217;on appelle en usermode des <a href=\"http:\/\/download.microsoft.com\/download\/D\/A\/A\/DAAD63AF-B06F-4F29-AF1D-68A78102ABF4\/SQLServerSpinlockContention.pdf\">spinlocks<\/a>, des outils de synchronisation entre threads. La diff\u00e9rence entre un spinlock et un event par exemple, est qu&#8217;un spinlock est une construction purement applicative, et ne fait pas r\u00e9f\u00e9rence \u00e0 un objet du noyau (donc pas de transition user -&gt; kernel). Donc elle est beaucoup plus l\u00e9g\u00e8re \u00e0 ex\u00e9cuter.<\/p>\n<p>Les spinlocks dans SQL Server permettent de prot\u00e9ger principalement des listes cha\u00een\u00e9es de structures, comme les BUFs, ces structures qui d\u00e9crivent les pages pr\u00e9sentes en Buffer Pool. Il existe tout un tas de listes de structures pour les m\u00e9tadatas, le plan cache, les verrous, les FCB, etc&#8230; Faire un <em>select name from <\/em><a href=\"http:\/\/www.sqlskills.com\/blogs\/paul\/advanced-performance-troubleshooting-waits-latches-spinlocks\/\"><em>sys.dm_os_spinlock_stats<\/em>\u00a0<\/a>pour l&#8217;exhaustivit\u00e9.<\/p>\n<p>Ces ressources sont uniques dans tout l&#8217;espace d&#8217;adresse de SQL Server, et sont accessibles potentiellement par de multiples workers donc il faut que l&#8217;on puisse garantir une s\u00e9quentialisation des acc\u00e8s. Lorsque l&#8217;on sait que la ressource ne va \u00eatre d\u00e9tenue que pendant un temps tr\u00e8s court, il peut \u00eatre plus int\u00e9ressant de br\u00fbler de la CPU dans une boucle et v\u00e9rifier \u00e0 chaque tour si la ressource est disponible plut\u00f4t que de bloquer et se mettre en attente. Si la ressource est volatile on a de grandes chances de pouvoir la verrouiller au prochain tour. En revanche, si on bloque, on va devoir attendre d&#8217;\u00eatre reschedul\u00e9.<\/p>\n<p>A l&#8217;int\u00e9rieur de la boucle, on va en m\u00eame temps tester une variable et tenter de modifier sa valeur :<\/p>\n<pre>Boucle tant que (teste_et_initialise (a,1) != 1)<\/pre>\n<p>Dans la plupart des langages, il existe des fonctions qui font ce travail de mani\u00e8re atomique (en garantissant qu&#8217;il n&#8217;y a qu&#8217;un seul thread sur tous les processeurs capable de modifier la valeur), mais en d\u00e9finitive ces fonctions font toutes r\u00e9f\u00e9rence \u00e0 une instruction du processeur cod\u00e9e en langage assembleur (CMPXCHG , CMPXCHG8B par exemple pour x86). Dans le monde Windows ce sont les fonctions de la famille Interlocked qui font ce travail. Dans le monde linux, il y a des \u00e9quivalent comme les fonctions type <a href=\"http:\/\/www.makelinux.net\/books\/lkd2\/ch09lev1sec1\">atomic<\/a>, ou <a href=\"https:\/\/lwn.net\/Articles\/22818\/\">seqlocks<\/a> en kernel 2.6.<\/p>\n<h3>IOCP :<\/h3>\n<p>L\u00e0 c&#8217;est ultra-chaud. Je ne vois qu&#8217;un seul endroit ou les <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa365198(v=vs.85).aspx\">IO completion ports<\/a> sont utilis\u00e9s, c&#8217;est sur la gestion des connexions sur chaque CPU node, ou NUMA node.<\/p>\n<p>L&#8217;int\u00e9r\u00eat d&#8217;un IOCP est de permettre de synchroniser des threads sur des IO asynchrones tout en n&#8217;autorisant qu&#8217;un certain nombre \u00e0 s&#8217;ex\u00e9cuter en parall\u00e8le. Si on a 8 CPU et qu&#8217;on a 150 demandes de connexions simultan\u00e9es, on va en traiter 8 en m\u00eame temps mais les autres seront toutes visibles par le scheduler windows et rien ne va l&#8217;emp\u00eacher de changer le contexte (<em>context switch<\/em>) des t\u00e2ches en ex\u00e9cution pour permettre \u00e0 chacune de disposer d&#8217;une m\u00eame quantit\u00e9 de temps CPU.<\/p>\n<p>Donc comme pour le scheduling coop\u00e9ratif dans SQLOS, il faut limiter le nombre de connexions visibles par Windows au nombre de CPU disponibles, via un IOCP et une propri\u00e9t\u00e9 de concurrence: on va dire \u00e0 l&#8217;IOCP que seulement 8 connexions peuvent passer en m\u00eame temps. La premi\u00e8re IO qui est termin\u00e9e \u00e9met un paquet de fin de traitement qui est notifi\u00e9 au thread en attente pendant que le suivant peut encha\u00eener sur une autre IO, etc&#8230; On ne conserve ainsi que le nombre optimal de threads ex\u00e9cutables \u00e0 un instant donn\u00e9. L&#8217;autre avantage est que l&#8217;IOCP g\u00e8re ses propres m\u00e9canismes de notification et est plus <em>scalable<\/em> qu&#8217;un fonctionnement \u00e0 base de SetEvent \/ WaitForSingleObject.<\/p>\n<p>Or cet objet du noyau n&#8217;existe pas sous Linux. Il y a potentiellement <a href=\"http:\/\/man7.org\/linux\/man-pages\/man7\/epoll.7.html\">epoll<\/a>\u00a0qui peut \u00eatre \u00e9tudi\u00e9, mais il y a plusieurs diff\u00e9rences dans le fonctionnement de base:<\/p>\n<p>&#8211; Un IOCP fonctionne avec des IO asynchrones : on effectue un appel \u00e0 une fonction sans \u00eatre bloqu\u00e9 (asynchrone), puis on re\u00e7oit une notification que l&#8217;op\u00e9ration est termin\u00e9e plus tard. Alors que sous Linux, l&#8217;approche est diff\u00e9rente, on attend qu&#8217;une donn\u00e9e soit disponible en lecture sur par exemple une socket, et on lit le contenu sans avoir \u00e0 attendre puisqu&#8217;il est disponible imm\u00e9diatement.<br \/>\n&#8211; Il n&#8217;y a pas de notion de concurrence max comme dans un IOCP. Avec epoll il n&#8217;y a qu&#8217;un seul thread qui travaille \u00e0 chaque fois. Il faut alors cr\u00e9er de multiples epoll pour arriver au m\u00eame principe de concurrence.<\/p>\n<p>Une <a href=\"http:\/\/fr.slideshare.net\/sm9kr\/iocp-vs-epoll-perfor\">\u00e9tude comparative r\u00e9cente<\/a> montre notamment qu&#8217;epoll serait plus consommateur en CPU que IOCP, mais qu&#8217;en dehors de \u00e7a les capacit\u00e9s de traitement sont comparables.<\/p>\n<h2>Entr\u00e9es \/ sorties (disque):<\/h2>\n<p>L\u00e0 aussi, compliqu\u00e9. Il y a plusieurs aspects des entr\u00e9es \/ sorties qui sont \u00e0 v\u00e9rifier:<\/p>\n<h3>La durabilit\u00e9 des \u00e9critures:<\/h3>\n<p>Il y a plusieurs fa\u00e7ons de faire. Par exemple sur <a href=\"http:\/\/blog.capdata.fr\/index.php\/sybase-ase-direct-io-dsync-onoff-raw-device\/\">Sybase ASE<\/a>\u00a0ou MySQL (innodb_flush_method), les fichiers de donn\u00e9es et journaux de transactions peuvent \u00eatre ouverts en O_DSYNC ou en O_DIRECT quand le file system le permet. Sur PostgreSQL, la durabilit\u00e9 est assur\u00e9e via des appels r\u00e9p\u00e9t\u00e9s \u00e0 <a href=\"http:\/\/linux.die.net\/man\/2\/fsync\">fsync()<\/a>. Au fil des versions des optimisations ont \u00e9t\u00e9 faites pour limiter le nombre d&#8217;appels \u00e0 fsync dans le code mais il reste toujours des workloads o\u00f9 cette approche est impactante.<\/p>\n<p>Or sur Windows l&#8217;ouverture du fichier est faite via un \u00e9quivalent \u00e0 O_DIRECT en quelque sorte, via <a href=\"http:\/\/blog.capdata.fr\/index.php\/consistence-des-ecritures-avec-sata\/\">deux flags pass\u00e9s lors du CreateFile()<\/a>. Donc il y aura n\u00e9cessairement des pr\u00e9conisations quant aux file systems support\u00e9s et aux options \u00e0 positionner pour avoir un \u00e9quivalent.<\/p>\n<h3>Les entr\u00e9es \/ sorties asynchrones :<\/h3>\n<p>La plupart des entr\u00e9es \/ sorties sont <a href=\"http:\/\/blog.capdata.fr\/index.php\/io-asynchrones-episode-1\/\">asynchrones<\/a> dans SQL Server. \u00a0Il y a deux impl\u00e9mentations des IO asynchrones sur Linux:<\/p>\n<p><strong>&#8211; Les POSIX asynchronous IO:<\/strong> dans ce cas, l&#8217;IO est vue non bloquante par celui qui l&#8217;initie mais dans les faits il clone un nouveau thread qui lui va bloquer \u00e0 sa place. Donc bon &#8230;<\/p>\n<p>&#8211; <strong>Les Kernel asynchronous IO (ou libaio)<\/strong> : dans ce cas, il s&#8217;agit d&#8217;une approche plus comparable avec ce que propose Windows. Elle est support\u00e9e depuis la 2.6 et a fait l&#8217;objet <a href=\"http:\/\/diku.dk\/forskning\/Publikationer\/tekniske_rapporter\/2004\/04-03.pdf\">de tests plut\u00f4t concluants<\/a> notamment chez MySQL AB \u00e0 l&#8217;\u00e9poque, et qui ont conduit \u00e0 son impl\u00e9mentation dans InnoDB. La contrainte dans ce cas est que le fichier doit \u00eatre ouvert en O_DIRECT ce qui semblerait donc orienter le choix sur la question de la durabilit\u00e9.<\/p>\n<h3>WriteFileGather \/ ReadFileScatter :<\/h3>\n<p>Lorsque le checkpoint doit \u00e9crire des pages modifi\u00e9es sur disque, il ex\u00e9cute une routine WriteMultiple dans laquelle il va aller r\u00e9cup\u00e9rer un certain nombre de pages marqu\u00e9es comme dirty dans le Buffer Pool, puis ex\u00e9cute un appel \u00e0 WriteFileGather() qui va les \u00e9crire sur disque. L&#8217;avantage de WriteFileGather par rapport \u00e0 WriteFile est que l&#8217;on n&#8217;est pas oblig\u00e9 d&#8217;avoir \u00e0 faire des I\/O s\u00e9par\u00e9es pour des blocks discontig\u00fcs en m\u00e9moire. SQL 2014 peut envoyer jusqu&#8217;\u00e0 32 pages dans une seule op\u00e9ration d&#8217;\u00e9criture avec cette technique, et SQL 2016 jusqu&#8217;\u00e0 128 (soit 1Mb). M\u00eame chose dans l&#8217;autre sens avec ReadFileScatter. On n&#8217;est pas oblig\u00e9 d&#8217;avoir un segment contig\u00fc de 64K de m\u00e9moire pour placer un prefetch de 8 pages. C&#8217;est comme cela que les pages sont remont\u00e9es du disque dans le Buffer Pool.<\/p>\n<p>Sur Linux, on va utiliser les IO vectoris\u00e9es (vectored IO) avec <a href=\"http:\/\/linux.die.net\/man\/2\/readv\">readv<\/a> et <a href=\"http:\/\/linux.die.net\/man\/2\/writev\">writev<\/a>. Leur fonctionnement est en apparence semblable \u00e0 leurs cousines win32, elles passent un tableau de buffers \u00e0 \u00e9crire ou lire (iovec sous Linux, FILE_SEGMENT_ELEMENT sous Windows). Actuellement le nombre de buffers discontigus \u00e0 passer \u00e0 readv \/ writev est limit\u00e9 \u00e0 1024 ce qui est toujours au-dessus de ce que transmet SQL Server. (IOV_MAX dans <a href=\"http:\/\/pubs.opengroup.org\/onlinepubs\/009695399\/basedefs\/limits.h.html\">limits.h<\/a>). Une diff\u00e9rence r\u00e9side dans le fait que sur Windows on indique une quantit\u00e9 d&#8217;octets \u00e0 \u00e9crire ou lire \u00a0alors que sur Linux, on indique un nombre de segments iovec \u00e0 traiter.<\/p>\n<p>Autre note int\u00e9ressante, WriteFileGather \/ ReadFileScatter d\u00e9clarent une structure Overlapped dans leur signature, donc les IO sont n\u00e9cessairement asynchrones. Sur Linux, les Kernel asynchronous IO ont \u00e9t\u00e9 \u00e9tendues aux IO vectoris\u00e9es dans un patch qui daterait de la 2.5, donc aio_write et aio_read ont chacune <a href=\"http:\/\/lwn.net\/Articles\/170954\/\">une signature qui inclue un iovec<\/a>\u00a0depuis ce patch.<\/p>\n<h2>NTFS vs ext4:<\/h2>\n<p>Un certain nombre de fonctionnalit\u00e9s sont \u00e9galement li\u00e9es aux possibilit\u00e9s offertes par NTFS, parmi lesquelles on peut citer:<\/p>\n<p>&#8211; Les sparse files <em>AKA<\/em> Database Snapshots.<br \/>\n&#8211; La possibilit\u00e9 de z\u00e9ro &#8211; initialiser (dans le cas des journaux de transactions) ou non ( dans le cas des fichiers de donn\u00e9es) les portions de fichiers allou\u00e9es sur disque.<br \/>\n&#8211; La possibilit\u00e9 de r\u00e9duire un fichier sur disque.<\/p>\n<p>Il y a peut \u00eatre des pistes \u00e0 creuser en regardant ce que font <a href=\"http:\/\/linux.die.net\/man\/1\/truncate\">truncate<\/a> \/ <a href=\"http:\/\/linux.die.net\/man\/1\/fallocate\">fallocate<\/a> par exemple. Truncate doit permettre de cr\u00e9er des sparse files et de r\u00e9duire des fichiers sur ext4. Fallocate doit permettre de faire l&#8217;\u00e9quivalent de <a href=\"https:\/\/msdn.microsoft.com\/fr-fr\/library\/windows\/desktop\/aa365531(v=vs.85).aspx\">SetEndOfFile<\/a> pour l&#8217;initialisation instantan\u00e9e.<\/p>\n<p>Pour retrouver l&#8217;\u00e9quivalent du cluster size NTFS \u00e0 64K, il existe une option <a href=\"https:\/\/ext4.wiki.kernel.org\/index.php\/Bigalloc\">bigalloc<\/a> qui est utilis\u00e9e lors du mkfs, attention toutefois l&#8217;option n&#8217;est disponible qu&#8217;\u00e0 partir des noyaux 3.2, et rencontrerait toujours pas mal de probl\u00e8mes jusqu&#8217;en 3.7. Sachant que les noyaux 3.2 <a href=\"http:\/\/www.databasesoup.com\/2014\/09\/why-you-need-to-avoid-linux-kernel-32.html\">rencontrent eux-m\u00eames pas mal de probl\u00e8mes<\/a>\u00a0, \u00e7a risque donc de ne pas \u00eatre pour tout de suite.<\/p>\n<p>Il est \u00e9galement possible d&#8217;utiliser mkfs.ext4 -T largefile pour le formatage, cela permet de diminuer le nombre d&#8217;inodes pour les gros fichiers (1 inode pour 1Mb au lieu de 1 inode pour 16K).<\/p>\n<h2>Autres points cl\u00e9s :<\/h2>\n<p>D&#8217;autres points qui peuvent \u00eatre compliqu\u00e9s \u00e0 traduire dans le monde Linux:<\/p>\n<ul>\n<li>Ulimits\u00a0?<\/li>\n<li>Integrated security \/ ACLs<\/li>\n<li>Collations syst\u00e8me<\/li>\n<li>VDI \/ VSS<\/li>\n<li>Int\u00e9gration avec Perfmon.<\/li>\n<li>MSDTC<\/li>\n<li>WMI<\/li>\n<li>ETW<\/li>\n<li>&#8230;<\/li>\n<\/ul>\n<h2>Synergies avec les autres projets type Ubuntu in Windows:<\/h2>\n<p><a href=\"https:\/\/blogs.msdn.microsoft.com\/wsl\/2016\/04\/22\/windows-subsystem-for-linux-overview\/\">L&#8217;annonce a \u00e9t\u00e9 faite il y a quelques semaines<\/a>, Windows 10 inclut d\u00e9j\u00e0 en beta la possibilit\u00e9 de d\u00e9marrer un shell linux et d&#8217;interop\u00e9rer avec les ressources windows (processes, fichiers, etc&#8230;). Un cygwin en mieux car int\u00e9gr\u00e9 sous la forme d&#8217;un nouveau sous-syst\u00e8me comme win32, POSIX\u00a0et feu OS\/2, qui ex\u00e9cute directement de l&#8217;ELF64.<\/p>\n<p>Alors que dans le cas de cygwin, ls.exe \u00e9tait un ex\u00e9cutable win32, ici \/bin\/ls sera le m\u00eame \/bin\/ls que l&#8217;on trouve sur Ubuntu.<\/p>\n<p>Il n&#8217;y a toutefois pas de synergie \u00e0 proprement parler avec le portage de SQL Server sur Linux. On peut entrer dans le d\u00e9lire de dire que l&#8217;on pourra ex\u00e9cuter sqlservr en ELF64 sur un windows 10, mais \u00e7a n&#8217;aurait bien \u00e9videmment aucun sens.<\/p>\n<p>En tous cas les deux projets vont clairement dans le sens d&#8217;un rapprochement entre les 2 mondes. Et chez CapData, o\u00f9 l&#8217;on jongle avec diff\u00e9rents SGBD sur diff\u00e9rentes plateformes, \u00e7a ne peut que nous r\u00e9jouir davantage \ud83d\ude42<\/p>\n<h2>Conclusion:<\/h2>\n<p>Franchement que retenir de tout \u00e7a ?<\/p>\n<p>1) Un peu d&#8217;auto-critique ne fait pas de mal : \u00e0 quoi \u00e7a sert de sp\u00e9culer avant que le produit ne soit sorti ? C&#8217;est s\u00fbr qu&#8217;on aura plus de choses \u00e0 dire quand il sera l\u00e0. Et il y aura l\u00e0 de quoi quoi faire un article plus consistant, promis jur\u00e9.<\/p>\n<p>2) Ensuite est-ce qu&#8217;on ne fait pas fausse route en partant du principe qu&#8217;il faut traduire le comportement de Windows \u00e0 Linux ? Est-ce qu&#8217;ils (les dev) n&#8217;ont pas plus intelligemment oubli\u00e9 Windows et imagin\u00e9 directement\u00a0en Linux ?<\/p>\n<p>3) Enfin, apr\u00e8s ces quelques recherches, je me rends compte que le foss\u00e9 pr\u00e9tendument abyssal n&#8217;est pas si profond que \u00e7a. Et qu&#8217;avec une solide \u00e9quipe, de bonnes id\u00e9es, de l&#8217;aide ext\u00e9rieure peut \u00eatre parmi la communaut\u00e9 des d\u00e9veloppeurs kernel, et un regard port\u00e9 sur les choix qu&#8217;ont fait les autres (Oracle \/ PostgreSQL \/ Sybase \/ MySQL), on peut croire qu&#8217;on va avoir bient\u00f4t entre les mains un nouveau petit bijou de d\u00e9veloppement.<\/p>\n<p>Apr\u00e8s tout, n&#8217;est-ce pas un retour aux sources de Shiloh (la 7.0), \u00e0 l&#8217;heure o\u00f9 une \u00e9quipe de 4 brillants architectes (<a href=\"https:\/\/www.microsoft.com\/about\/technicalrecognition\/sql-server-7-team.aspx\">Spiro \/ Campbell \/ Berenson \/ Flessner<\/a>) avait d\u00e9cid\u00e9 de tout p\u00e9ter de la 6.5 et de reconstruire sur des cendres ?<\/p>\n<p>L&#8217;histoire le dira.<\/p>\n<p>A+<\/p>\n<a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-twitter nolightbox\" data-provider=\"twitter\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Twitter\" href=\"https:\/\/twitter.com\/intent\/tweet?url=https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F5286&#038;text=Article%20sur%20le%20blog%20de%20la%20Capdata%20Tech%20Team%20%3A%20\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"twitter\" title=\"Share on Twitter\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/twitter.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-linkedin nolightbox\" data-provider=\"linkedin\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Linkedin\" href=\"https:\/\/www.linkedin.com\/shareArticle?mini=true&#038;url=https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F5286&#038;title=Pas%20de%20la%20tarte\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"linkedin\" title=\"Share on Linkedin\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/linkedin.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-mail nolightbox\" data-provider=\"mail\" rel=\"nofollow\" title=\"Share by email\" href=\"mailto:?subject=Pas%20de%20la%20tarte&#038;body=Article%20sur%20le%20blog%20de%20la%20Capdata%20Tech%20Team%20%3A%20:%20https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F5286\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"mail\" title=\"Share by email\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/mail.png\" \/><\/a>","protected":false},"excerpt":{"rendered":"<p>Non vraiment, \u00e7a va pas \u00eatre de la tarte. Et si vous vivez dans une grotte depuis le d\u00e9but de l&#8217;ann\u00e9e, vous ne savez peut \u00eatre pas encore que SQL Server doit \u00eatre port\u00e9 sur Linux. D&#8217;ailleurs mister Slava Oks,&hellip; <a href=\"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/\" class=\"more-link\">Continuer la lecture <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":7828,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[173,5],"tags":[30,174],"class_list":["post-5286","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-operating-system","category-sqlserver","tag-linux","tag-win32"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.8 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Pas de la tarte - Capdata TECH BLOG<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Pas de la tarte - Capdata TECH BLOG\" \/>\n<meta property=\"og:description\" content=\"Non vraiment, \u00e7a va pas \u00eatre de la tarte. Et si vous vivez dans une grotte depuis le d\u00e9but de l&#8217;ann\u00e9e, vous ne savez peut \u00eatre pas encore que SQL Server doit \u00eatre port\u00e9 sur Linux. D&#8217;ailleurs mister Slava Oks,&hellip; Continuer la lecture &rarr;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/\" \/>\n<meta property=\"og:site_name\" content=\"Capdata TECH BLOG\" \/>\n<meta property=\"article:published_time\" content=\"2016-05-12T15:39:16+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-09-13T12:12:52+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/05\/notpie.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1000\" \/>\n\t<meta property=\"og:image:height\" content=\"1106\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"David Baffaleuf\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u00c9crit par\" \/>\n\t<meta name=\"twitter:data1\" content=\"David Baffaleuf\" \/>\n\t<meta name=\"twitter:label2\" content=\"Dur\u00e9e de lecture estim\u00e9e\" \/>\n\t<meta name=\"twitter:data2\" content=\"20 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/\"},\"author\":{\"name\":\"David Baffaleuf\",\"@id\":\"https:\/\/blog.capdata.fr\/#\/schema\/person\/136297da9f61d6e4878abe0f48bc5fbf\"},\"headline\":\"Pas de la tarte\",\"datePublished\":\"2016-05-12T15:39:16+00:00\",\"dateModified\":\"2019-09-13T12:12:52+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/\"},\"wordCount\":4065,\"commentCount\":2,\"publisher\":{\"@id\":\"https:\/\/blog.capdata.fr\/#organization\"},\"keywords\":[\"linux\",\"win32\"],\"articleSection\":[\"Operating System\",\"SQL Server\"],\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/\",\"url\":\"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/\",\"name\":\"Pas de la tarte - Capdata TECH BLOG\",\"isPartOf\":{\"@id\":\"https:\/\/blog.capdata.fr\/#website\"},\"datePublished\":\"2016-05-12T15:39:16+00:00\",\"dateModified\":\"2019-09-13T12:12:52+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/blog.capdata.fr\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Pas de la tarte\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.capdata.fr\/#website\",\"url\":\"https:\/\/blog.capdata.fr\/\",\"name\":\"Capdata TECH BLOG\",\"description\":\"Le blog technique sur les bases de donn\u00e9es de CAP DATA Consulting\",\"publisher\":{\"@id\":\"https:\/\/blog.capdata.fr\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.capdata.fr\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"fr-FR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/blog.capdata.fr\/#organization\",\"name\":\"Capdata TECH BLOG\",\"url\":\"https:\/\/blog.capdata.fr\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\/\/blog.capdata.fr\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2023\/01\/logo_capdata.webp\",\"contentUrl\":\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2023\/01\/logo_capdata.webp\",\"width\":800,\"height\":254,\"caption\":\"Capdata TECH BLOG\"},\"image\":{\"@id\":\"https:\/\/blog.capdata.fr\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.linkedin.com\/company\/cap-data-consulting\/mycompany\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.capdata.fr\/#\/schema\/person\/136297da9f61d6e4878abe0f48bc5fbf\",\"name\":\"David Baffaleuf\",\"sameAs\":[\"http:\/\/www.capdata.fr\"],\"url\":\"https:\/\/blog.capdata.fr\/index.php\/author\/dbaffaleuf\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Pas de la tarte - Capdata TECH BLOG","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/","og_locale":"fr_FR","og_type":"article","og_title":"Pas de la tarte - Capdata TECH BLOG","og_description":"Non vraiment, \u00e7a va pas \u00eatre de la tarte. Et si vous vivez dans une grotte depuis le d\u00e9but de l&#8217;ann\u00e9e, vous ne savez peut \u00eatre pas encore que SQL Server doit \u00eatre port\u00e9 sur Linux. D&#8217;ailleurs mister Slava Oks,&hellip; Continuer la lecture &rarr;","og_url":"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/","og_site_name":"Capdata TECH BLOG","article_published_time":"2016-05-12T15:39:16+00:00","article_modified_time":"2019-09-13T12:12:52+00:00","og_image":[{"width":1000,"height":1106,"url":"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/05\/notpie.jpg","type":"image\/jpeg"}],"author":"David Baffaleuf","twitter_card":"summary_large_image","twitter_misc":{"\u00c9crit par":"David Baffaleuf","Dur\u00e9e de lecture estim\u00e9e":"20 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/#article","isPartOf":{"@id":"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/"},"author":{"name":"David Baffaleuf","@id":"https:\/\/blog.capdata.fr\/#\/schema\/person\/136297da9f61d6e4878abe0f48bc5fbf"},"headline":"Pas de la tarte","datePublished":"2016-05-12T15:39:16+00:00","dateModified":"2019-09-13T12:12:52+00:00","mainEntityOfPage":{"@id":"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/"},"wordCount":4065,"commentCount":2,"publisher":{"@id":"https:\/\/blog.capdata.fr\/#organization"},"keywords":["linux","win32"],"articleSection":["Operating System","SQL Server"],"inLanguage":"fr-FR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/","url":"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/","name":"Pas de la tarte - Capdata TECH BLOG","isPartOf":{"@id":"https:\/\/blog.capdata.fr\/#website"},"datePublished":"2016-05-12T15:39:16+00:00","dateModified":"2019-09-13T12:12:52+00:00","breadcrumb":{"@id":"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.capdata.fr\/index.php\/pas-de-la-tarte\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/blog.capdata.fr\/"},{"@type":"ListItem","position":2,"name":"Pas de la tarte"}]},{"@type":"WebSite","@id":"https:\/\/blog.capdata.fr\/#website","url":"https:\/\/blog.capdata.fr\/","name":"Capdata TECH BLOG","description":"Le blog technique sur les bases de donn\u00e9es de CAP DATA Consulting","publisher":{"@id":"https:\/\/blog.capdata.fr\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.capdata.fr\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"fr-FR"},{"@type":"Organization","@id":"https:\/\/blog.capdata.fr\/#organization","name":"Capdata TECH BLOG","url":"https:\/\/blog.capdata.fr\/","logo":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/blog.capdata.fr\/#\/schema\/logo\/image\/","url":"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2023\/01\/logo_capdata.webp","contentUrl":"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2023\/01\/logo_capdata.webp","width":800,"height":254,"caption":"Capdata TECH BLOG"},"image":{"@id":"https:\/\/blog.capdata.fr\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.linkedin.com\/company\/cap-data-consulting\/mycompany\/"]},{"@type":"Person","@id":"https:\/\/blog.capdata.fr\/#\/schema\/person\/136297da9f61d6e4878abe0f48bc5fbf","name":"David Baffaleuf","sameAs":["http:\/\/www.capdata.fr"],"url":"https:\/\/blog.capdata.fr\/index.php\/author\/dbaffaleuf\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/posts\/5286","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/comments?post=5286"}],"version-history":[{"count":145,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/posts\/5286\/revisions"}],"predecessor-version":[{"id":5440,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/posts\/5286\/revisions\/5440"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/media\/7828"}],"wp:attachment":[{"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/media?parent=5286"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/categories?post=5286"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/tags?post=5286"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}