Tvůrce MySQL sází na budoucnost MariaDB

28. 3. 2013

Sdílet

Autor: © Monty Program
Michael „Monty“ Widenius, který vytvořil MySQL, nevidí budoucnost svého dítka růžově.

Michael Widenius je jeden ze tří zakladatelů společnosti MySQL Ab, která od svého vzniku v roce 1995 byla typickou představitelkou druhé generace společností, jejichž produkty jsou založené na otevřeném zdrojovém kódu. Jejich obchodní model je jednak založený na prodeji podpory, ale také na dvojím licencováním – MySQL je bezplatně dostupná v rámci licence GPL, ale řada vývojářů preferuje možnost zakoupit si tradičnější licenci, která jim lépe umožňuje začlenit technologie MySQL Ab do jejich uzavřených produktů.

MySQL Ab byla v roce 2008 zakoupena společností Sun Microsystems, ta byla ale o rok později pohlcena firmou Oracle Corporation. Den, kdy se tuto informaci Michael Widenius dozvěděl, zareagoval přesně v tradicích své komunity – rozhodl se vytvořit odnož MySQL a zahájil práce na MariaDB. Připojila se k němu i řada vývojářů MySQL. Společně založili společnost Monty Program Ab, která poskytla domov pro MariaDB a pro hlavní vývojáře MySQL. „Mnoho původních hlavních vývojářů MySQL, včetně mne, nevěřilo, že by Oracle mohl být dobrým správcem MySQL, a chtěli jsme zajistit, aby její zdrojový kód zůstal navždy bezplatný,“ vysvětluje Widenius.

Další vývoj ho nijak nepřesvědčil, že se mýlil. Databáze MySQL je stále velmi populární, podle db-engines.com si drží mezi relačními databázemi třetí pozici za řešeními od Oraclu a Microsoftu, zatímco MariaDB obsazuje až 35. příčku. Ale Oracle zrušil veřejnou dostupnost databáze chyb, ohlásil komerční extenze kódu a v některých případech místo opravování chyb prostě z produktu odstraňuje funkce. Ani přes sliby na konferenci MySQL v dubnu 2009 nebyla dokumentace MySQL převedena do otevřené licence. A klíčové funkce ohlášené pro MySQL 6.0 nebyly nikdy uvedeny, a to i přesto, že byly dokončeny a připraveny pro začlenění.

Mezitím popularita MariDB postupně posiluje. Byla od začátku vyvíjena jako náhrada za MySQL a kompatibilita byla považována za zásadní a na tom se nic nezmění, dokud bude uživatelská báze MySQL větší než MariaDB. Tento požadavek ale nebrání vývojářům v přepracování kódu a přidání nových funkcí. Michael Widenius odvážně tvrdí, že dnes je MariaDB asi 30 člověkoroků (počítáno v násobcích roční práce jednoho vývojáře) před Oraclem a jeho MySQL. „MariaDB 5.5 obsahuje vše, co nabízí MySQL 5.5 Enterprise a řadu věcí navíc,“ prohlásil Widenius

MariaDB postupně roste, co se týče počtu instalací. Tento proces může probíhat ve skocích, protože řada linuxových distribucí ohlásila, že MariaDB budou nabízet jako výchozí databázové řešení. Patří sem Fedora (výhledově tedy i komerční Red Hat Enterprise Linux), OpenSUSE (výhledově komerční SUSE) a od 23. března i Slackware. Jestli dnes můžeme odhadovat počet instalací MariaDB na jeden milion, může se toto číslo řádově změnit během jediného roku.

'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }