MySQL Proxy - Giuseppe Maxia
Transcription
MySQL Proxy - Giuseppe Maxia
Designing Scalable Architectures with MySQL Proxy Giuseppe Maxia MySQL Community Team Leader - Sun Microsystems John Loehrer Data Architect, Gaia Online Jimmy Guerrero Sr Product Marketing Manager - Sun Microsystems, Database Group Copyright 2008 MySQL AB The World’s Most Popular Open Source Database 1 Agenda • • • • Proxy concepts MySQL Proxy architecture Proxy with a single back-end Proxy with multiple back-ends broken? • • missing feature? • not flexible? This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License. Solving database problems traditional way This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License. Solving database problems traditional way 1. file a bug report This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License. Solving database problems traditional way 1. 2. file a bug report wait This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License. Solving database problems traditional way 1. 2. file a bug report wait This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License. Solving database problems • Open source way source code compile new source code This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License. modify Solving database problems • creative (shortsighted) way bring the logic at application level This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License. Solving database problems • creative (enlightened) way set the logic at server level (stored routines) This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License. Solving database problems • creative (more enlightened) way set the logic at protocol level (proxy) This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License. what can you do with MySQL Proxy • • • • • • • • • • • • create new commands filter queries (deny specific queries) collect statistics on usage implement usage quotas execute shell commands create customized logs implement server-side pivot tables start/stop a MySQL server remotely play movies (seriously!) make coffee (really?) sharding load balancing servers Basic principles Basic principles PROXY CORE Lua script connection hook function function function read query hook function read result hook function Lua ?? Why not ... { Perl ? PHP? Javascript? [whatever]? Lua • SMALL ( < 200 KB) • DESIGNED for EMBEDDED systems • Widely used (lighttpd) lighttpd, like MySQL Proxy, was created by Jan Kneschke Lua Very popular among game writers Proxy overview global context Lua script connect_server session context session context session context session context session context session context session context read_handshake read_auth read_auth_result read_query read_query_result disconnect_client Proxy overview /usr/local/sbin/mysql-proxy \ --proxy-lua-script=/path/name.lua IMPORTANT! THE SCRIPT DOES NOT START UNTIL THE FIRST CLIENT CONNECTION read_query and read_query_result client query result function read_query function read_query_result MySQL Proxy query result SERVER if a query is passed directly to the server, its result is NOT evaluated by read_query_result read_query and read_query_result client query result function function read_query read_query_result MySQL Proxy query queue query query query result SERVER only if a query is added to the query queue, its result is evaluated by read_query_result An example: user quotas • • • You want to limit user access When the user reaches a given amount of data, further queries should be rejected the quota must work across sessions (code online) http://forge.mysql.com/tools/tool.php?id=111 User quotas -- some global variables -- proxy.global.bandwidth -- will sum up the used bytes proxy.global.bandwidth = proxy.global.bandwidth or {} -- session_user will identify the user -- throughout the session local session_user User quotas -- session_user needs to be initialized -- when the user information is passed -- (during the authentication) function read_auth( auth ) session_user = auth.username proxy.global.bandwidth[session_user] = proxy.global.bandwidth[session_user] or 0 end BREAK (a handy Lua idiom) -- simple assignment a = a or 0 -- corresponds to: if a == nil then a = 0 else a = a end if a ~= nil then a = a else a = 0 end BREAK (a handy Proxy Lua function ) -- returns an error to the client function error_result (msg) proxy.response = { type = proxy.MYSQLD_PACKET_ERR, errmsg = msg, errcode = 7777, sqlstate = 'X7777', } return proxy.PROXY_SEND_RESULT end User quotas -- read_query (1) -- checking if the quota has been -- exceeded function read_query (packet ) if proxy.global.bandwidth[session_user] > 10000 and session_user ~= 'root' then return error_result( 'you have exceeded your query quota') end -- ... User quotas -- read_query (2) -- adding to the totalizer -- ... proxy.global.bandwidth[session_user ] = proxy.global.bandwidth[session_user] + packet:len() proxy.queries:append(1, packet ) return proxy.PROXY_SEND_QUERY end User quotas -- read_query_result (1) -- adding row headers to the totalizer function read_query_result(inj) local fields = inj.resultset.fields local rows = inj.resultset.rows if fields then for i = 1, #fields do proxy.global.bandwidth[session_user] = proxy.global.bandwidth[session_user] + (fields[i] and fields[i].name:len() or 0) end User quotas -- read_query_result (2) -- adding rows contents to the totalizer if rows then for row in rows do for i = 1, #fields do proxy.global.bandwidth[session_user] = proxy.global.bandwidth[session_user] + (row[i] and row[i]:len() or 0) end end end end User quotas -- read_query_result (3) -- displaying the current bandwidth end print (session_user .. ' -> ' .. proxy.global.bandwidth[session_user]) User quotas - what the user sees mysql> select repeat('a', 10000); ERROR 7777 (X7777): you have exceeded your query quota User quotas (VERY advanced) ------ you can create another module to be loaded at run time (this is really advanced) and in such module you define a SHOW QUOTAS command User quotas (VERY advanced) -- load_multi User quotas (VERY advanced) mysql> pload show_quotas.lua; +--------------------------------+ | info | +--------------------------------+ | module "show_quota.lua" loaded | +--------------------------------+ mysql> show quotas; +----------+-------+ | name | quota | +----------+-------+ | simple | 3578 | | root | 2111 | | msandbox | 102 | +----------+-------+ Designing Scalable Architectures with MySQL Proxy Giuseppe Maxia MySQL Community Team Leader - Sun Microsystems John Loehrer Data Architect, Gaia Online Jimmy Guerrero Sr Product Marketing Manager - Sun Microsystems, Database Group Copyright 2008 MySQL AB The World’s Most Popular Open Source Database 36 quick-start guide to mysql muxing ME online hangout for teens 5 million unique users per month 1.3 billion forum entries How does Gaia use the proxy? connection multiplexer turning 7,500 connections ... into 100 MySQL connections MySQL Proxy 7,500 connections PHP 100 connections MySQL Server Why MUX? a little history ... Gaia’s data center in 2003 our server farm... as our site grew ... some scaling issues added more servers ... site explodes diagnose the problem GAIA, under the hood typical LAMP stack Linux Share-Nothing Architecture each apache server = 50 connections Parent Process httpd child httpd worker thread worker thread child httpd ... listener thread ... 50 connections * 150 servers = stampede close connections each time setup / tear-down is expensive connecting to MySQL connect read challenge write auth read auth OK connect read challenge write auth read auth OK write query read result 75% connect read challenge write auth read auth OK 19% 6% write query read result close MySQL Thread spawning Client Client connect MySQL Server Client connect MySQL Server Client MySQL Server Thread connect new Client MySQL Server Thread connect new accept threads stack up MySQL I/O listen accept listen close end program NEW THREAD accept listen close end program accept NEW THREAD blocking read listen close end program accept NEW THREAD blocking read data blocking write listen close accept end program NEW THREAD blocking read data eof close blocking write close thread talking to multiple databases ... Forum Page Session DB start session get userdata get topic get related users save session User DB Forum DB idle threads we need a connection pool ideally ... Event Queue Thread Pool Thread allocate thread process query free release the thread after each query it’s like a limo ... ... vs. a taxi decouple threads from connections Libevent’s callback I/O very sweet! listen register callback event dispatch active descriptor Trigger callback epoll/kqueue rulez! (proxy uses it) MySQL 6.0 taking the right steps ... In the meantime ... by default, mysql-proxy isn’t a pooler lua hooks are awesome! hack some lua scripts ... goal: recycle back-end connections keep clients connected proxy stays transparent how to twist the proxy into a pooler connecting: find an idle back-end Proxy client Proxy client connect ahead idle pool authentication Client Proxy Back-End Pool MySQL Server Client Proxy Back-End Pool MySQL Server Client Proxy connect Back-End Pool MySQL Server Client Proxy Back-End Pool MySQL Server connect allocate Client Proxy Back-End Pool MySQL Server connect allocate Client Proxy Back-End Pool MySQL Server connect allocate com-change-user Client Proxy Back-End Pool MySQL Server connect allocate com-change-user challenge Client Proxy Back-End Pool MySQL Server connect allocate com-change-user challenge authenticate Client Proxy Back-End Pool MySQL Server connect allocate com-change-user challenge authenticate OK Client Proxy Back-End Pool MySQL Server connect allocate com-change-user challenge authenticate OK free back-end run the query don’t be afraid to let go Client Proxy query Client Proxy Back-End Pool query allocate Client Proxy Back-End Pool MySQL Server query allocate process query Client Proxy Back-End Pool MySQL Server query allocate process query free back-end connections scale! Designing Scalable Architectures with MySQL Proxy Giuseppe Maxia MySQL Community Team Leader - Sun Microsystems John Loehrer Data Architect, Gaiaonline Jimmy Guerrero Sr Product Marketing Manager - Sun Microsystems, Database Group This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License. Copyright 2008 MySQL AB The World’s Most Popular Open Source Database 160 MySQL Load Balancer MySQL software which can route database queries to the appropriate database in a scale-out environment. • • • • Intelligently route reads across slaves Use database least behind, least loaded Remove latent slaves from read rotation Other distribution algorithms • Improves/scales throughput of reads for online applications • Helps customers reduce cost of adding slaves Copyright 2008 MySQL AB The World’s Most Popular Open Source Database 161 MySQL Query Analyzer MySQL Enterprise Monitor feature that allows users to trace, monitor, and analyze MySQL query activity for specific servers, users, and applications. • Adaptive “Evil” query collection/tracing • Historical browsing/analysis • “Needle in a haystack” identification of worst queries • Worst execution times, # of execs, etc. SQL code is the #2 cause of performance issues 97% of those surveyed will use this Copyright 2008 MySQL AB The World’s Most Popular Open Source Database 162 MySQL Query Analyzer Copyright 2008 MySQL AB The World’s Most Popular Open Source Database 163 MySQL Proxy Forum Next Steps http://forums.mysql.com/list.php?146 Documentation – MySQL Proxy http://dev.mysql.com/doc/refman/5.1/en/mysql-proxy.html Documentation – MySQL Load Balancer http://dev.mysql.com/doc/refman/5.1/en/load-balancer.html Beta Testing MySQL Proxy-Enabled Products [email protected] MySQL Proxy Online Poll http://dev.mysql.com/tech-resources/quickpolls/ Copyright 2008 MySQL AB The World’s Most Popular Open Source Database 164 Questions? Giuseppe Maxia MySQL Community Team Leader - Sun Microsystems John Loehrer Data Architect, Gaiaonline Jimmy Guerrero Sr Product Marketing Manager - Sun Microsystems, Database Group This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License. Copyright 2008 MySQL AB The World’s Most Popular Open Source Database 165