Showing posts with label mysql-proxy. Show all posts
Showing posts with label mysql-proxy. Show all posts

Thursday, January 15, 2009

MySQL Proxy is back


MySQL Proxy

MySQL Proxy is back. After a long hiatus due to many deadlines in the Proxy team, the GPL version of MySQL Proxy has been updated.
The most important news is the location. Proxy is now hosted on Launchpad, like many more MySQL related projects, and MySQL code itself.

Kay and Jan announced and commented the changes. The repository is now on Bazaar, and there are rules for contributions.
On the technical side, the differences are quite a lot, although the changes are not documented yet. So I am exploring and reporting my findings while I meet them.
The architecture has changed. The Proxy has been split into plugins, to make it more manageable.
The admin interface, as explained in the manual, is gone. Instead, there is a plugin, and you can design your own or expand the existing one (which does very little.) For example, from the code directory, after compiling, you could try this one:
./src/mysql-proxy --plugin-dir=$PWD/plugins/ \
--admin-lua-script=$PWD/lib/admin.lua
The only command enabled is SELECT * FROM backends (case sensitive). To use the admin interface now you need to provide a username and a password (default: root/secret).
$ mysql -h 127.0.0.1 -P 4041 -u root -psecret
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.0.99-agent-admin

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> SELECT * FROM backends;
+-------------+----------------+-------+------+
| backend_ndx | address | state | type |
+-------------+----------------+-------+------+
| 1 | 127.0.0.1:3306 | 0 | 1 |
+-------------+----------------+-------+------+
1 row in set (0.00 sec)
Another important change is an option governing the amount of information from the Proxy. By default, the Proxy is silent. If you want to see warnings and errors, you must use the option
--log-level=(error|warning|info|message|debug)
Performance has been increased as well, by skipping result sets by default. If you really need a result set to be used in a Lua script, now you need to say it explicitly. When you append a query to the query queue, you must add {resultset_is_needed = true } as third parameter. If you don't the resultset is not made available to read_query_result().
There are more news, related to load balancing and query splitting, but I will report on that some other time.

Friday, July 25, 2008

OSCON 2008 - MySQL Proxy - from architecture to implementation


The presentation about MySQL Proxy at OSCON 2008 is over.

Here are the slides.

Thanks to my co-presenter Ronald Bradford and to all the participants. If you have more questions about the session, please use this blog's comments.

Wednesday, July 09, 2008

Proxy webinar - slides, script, FAQ

We did it. Designing Scalable Architectures with MySQL Proxy was delivered successfully, with over 150 attendees.
There is a large number of questions that were asked during the session, and you can find them in MySQL Proxy FAQ.
The slides, with the highly entertaining images used by John Loehrer to illustrate his point are also online
Finally, John posted his Connection pooler Lua script in the Forge.
Thanks to John Loehrer for his lively presentation, to Jimmy Guerrero and Rich Taylor for organizing the event, to Jan Kneschke, for answering questions online while we were talking, and to all the attendees, for showing such degree of interest.
And don't forget that there is still a quick poll on the future of MySQL Proxy that you can still vote on.

Tuesday, July 08, 2008

Shaping the future of MySQL Proxy


Here is a chance for all users to influence the future development of MySQL Proxy.
If you care about Proxy, you may want to check the current quickpoll in the Dev Zone, and vote for your favorite features.
The developers have a truckload of ideas, of course, but only a finite amount of time. So they can't develop all the features at once. They must start somewhere, and your vote can help them decide which ones should get higher priority.


In the meantime, don't forget the incoming webinar on Designing Scalable Architectures with MySQL Proxy. It's TODAY (tomorrow for some, depending on your time zone), July 8, 2008 at 10am PDT, 1pm EDT, 7pm CEST.

Wednesday, June 25, 2008

Scalable architectures with MySQL Proxy

MySQL community, mark your calendars!. On July 8th, 2008, there is a Webinar on Designing scalable architectures with MySQL Proxy.
This is not the usual marketing sponsored webinar. Although we love to show off, this is not a "look-how-good-we-are" presentation. This is a community driven event, where a community member, using only MySQL Proxy and some creativity, solved his production problems.

This is a real story of a community member who used open source software to build a customized scalable architecture to suit his purposes. Isn't it a good story?
I won't steal his thunder and tell you in advance what was the problem about. I will introduce the general concepts about Proxy, and then our guest John Loehrer will tell hist story in full colors.
Don't miss this one!

Tuesday, May 27, 2008

Chaining Proxies

If you need to combine two scripts with MySQL Proxy you have three choices.
  • You can manually rewrite the two scripts (good luck!)
  • you can use the load-multi module to load scripts on demand;
  • or you can use the proxy chaining technique.

To chain two proxies, you need to start one Proxy with the first Lua script, pointing at the real backend, listening to a non-standard port. Then you start the second Proxy with the second Lua script, having the first proxy as a backend, and listening to the standard proxy port.
It's a difficult and error prone procedure. You would forget about it, unless there were an easy workaround. And indeed you can have such a workaround. Just use the chain_proxy script from MySQL Forge and use it with this simple syntax:
$ chain_proxy first_script.lua second_script.lua
When I made this script, I had the problem of handling the standard output for each proxy instance. The brute force solution is to start each instance in a separate terminal window, but that is less than optimal. It would be almost as much work as doing things manually.
Considering that usually I need the output of a Proxy session only for debugging and that I am a frequent user of GNU screen, I made this arrangement:
The script starts each proxy inside a separate screen. At the end, it gives the list of screens being used, and creates a customized script in /tmp/ to kill the chained proxies and remove the screens.
$ chain_proxy digits.lua loop.lua
proxy started on screen "second_proxy" using script "loop.lua" - pid_file : /tmp/proxy1.pid
proxy started on screen "first_proxy" using script "digits.lua" - pid_file : /tmp/proxy_chain1.pid
stop script is /tmp/proxy_chain_stop
There are screens on:
21257.first_proxy (Detached)
21258.second_proxy (Detached)
2 Sockets in /tmp/uscreens/S-gmax.
In this example, the two proxies are started in sequence, and the script gives information on what is going on. The output of "loop.lua" is in the "first_proxy" screen. To see it, I only need to do
$ screen -r first_proxy
When I am finished using the chained Proxy, I type
$ /tmp/proxy_chain_stop
There are screens on:
21257.first_proxy (Detached)
21258.second_proxy (Detached)
2 Sockets in /tmp/uscreens/S-gmax.

No Sockets found in /tmp/uscreens/S-gmax.
This script can also be implemented by redirecting the output of each proxy to a different file. YMMV. I like the screen solution better.

I will be speaking about this feature (and more) during my MySQL University session on advanced Lua scripting.

Tuesday, April 08, 2008

MySQL Proxy Recipes - Returning a non dataset result

Working with MySQL Proxy, besides returning a dataset and an error you could also return a status of successfully executed query, without a dataset being involved. For example, every data modification query (INSERT, UPDATE, DELETE, CREATE ..., DROP ...) returns such a result.
The procedure is similar to returning an error. You must return a different response type and fill in the appropriate fields.
function affected_rows (rows, id)
proxy.response.type = proxy.MYSQLD_PACKET_OK
proxy.response.affected_rows = rows
proxy.response.insert_id = id
return proxy.PROXY_SEND_RESULT
end
If you call the above function with
 return affected_rows(3000,20)
your client will receive
Query OK, 3000 rows affected (0.01 sec)
Notice that you can't check the LAST_INSERT_ID with MySQL command line client, but you must use an API call from your favorite language to access that value.

This post is part of a set of recipes that will eventually become a long article.
Want to hear more? Attend MySQL Proxy - The complete tutorial at the MySQL Users Conference 2008.

Saturday, April 05, 2008

MySQL Sandbox 1.18 - server groups and Proxy support

MySQL Sandbox 1.18 was released today. The changes log has mostly bug fixes, but also two major additions:
  • The ability of creating a group of unrelated servers. Previously, there was only the set_replication.pl command, to create a set of master+slaves. Now the set_many.pl command will create unrelated servers;
  • The creation of a start_proxy script with replication installations. This script starts MySQL Proxy using as backends all the servers in the group.

If you missed the previous episodes, MySQL Sandbox is a tool used to install an isolated MySQL server, independently from existing instances in the host. It can also install a replicated system of 1 master + N slaves. All the above happens in seconds.

I will be speaking about the Sandbox at the Hamburg meetup and at the MySQL Users Conference and Expo.

Thursday, April 03, 2008

MySQL Proxy Recipes - Debugging messages on demand

MySQL Proxy, in addition to dealing with the packets sent between client and server, can optionally send text messages to the terminal window where it was launched. These messages, using the built-in function print(), can be very useful when you develop an application, because can give you information on what is going on. However, when the script is well tuned, all these messages can be distracting and even annoying.
OTOH, if you plan to extend the development of the script, leaving the telling messages in place can be very useful. One handy solution is to include conditional print messages, controlled by an environment variable.
  1. Change all occurrences of print to print_debug;
  2. Create a function print_debug that will print the message depending on the value of a local variable DEBUG;
  3. At the start of the script, initialize the DEBUG variable from the environment.
local DEBUG = os.getenv('DEBUG') or 0
DEBUG = DEBUG + 0

function read_query (packet )
if packet:byte() ~= proxy.COM_QUERY then return end
print_debug(packet:sub(2),1)
print_debug('inside read_query', 2)
end

function print_debug(msg, level)
level = level or 1
if DEBUG >= level then
print (msg)
end
end
print_debug accepts two parameters. The second one is optional and defaults to 1. If the global DEBUG variable is equal or higher than the level parameter, the message is printed. With this usage, you can define messages that will be printed only if the debug level is 2 or more, and others that will be printed when the level is 1. If you don't set the DEBUG variable, no messages will be printed. For example:
DEBUG=1 /usr/local/sbin/mysql-proxy --proxy-lua-script=simple_messages.lua
When the proxy is started in this way, you will get the queries (level 1). If you change DEBUG=1 into DEBUG=2, you will also see the "inside read_query" messages.
This technique can be tweaked and hacked to get more interesting results. For example, you can get conditional messages without changing the function name, or you can change the verbosity level at run time. These goodies will come to you - guess when? - during the tutorial mentioned below.

This post is part of a set of recipes that will eventually become a long article.
Want to hear more? Attend MySQL Proxy - The complete tutorial at the MySQL Users Conference 2008.

Wednesday, April 02, 2008

MySQL Proxy Recipes - Conditional query execution

MySQL Proxy allows you to execute multiple queries, by inserting them into the query queue.
What happens if one of the queries in the pipeline generates an error?
If you don't handle this occurrence, the Proxy will continue sending to the server all the queries in the pipeline, regardless of the result. It's easy to understand that, if the second query depends on the execution of the first one, checking the result of each query is essential.
We know already how to return an error. We only need to apply that knowledge in the right place.
The read_query_result() from the previous recipe (executing multiple queries) should be modified as follows:
function read_query_result (inj )
local res = assert(inj.resultset)
if res.query_status and (res.query_status < 0 ) then
proxy.queries:reset()
return error_result('ERROR IN LOOP ' .. tostring(inj.id),
9999, 'XLOOP')
end
-- do something with the result
if inj.id ~= max_loop then
return proxy.PROXY_IGNORE_RESULT
end
end
The error status is inside the resultset, which is contained in the injection packet received by the function. If that status is negative, some error occurred.

This post is part of a set of recipes that will eventually become a long article.
Want to hear more? Attend MySQL Proxy - The complete tutorial at the MySQL Users Conference 2008.

Tuesday, April 01, 2008

MySQL Proxy Recipes - Executing multiple queries

One of the goodies of MySQL Proxy is the execution of multiple queries in response of a single query from the client.
One example given in the manual is a normal query sent by the user, with a SHOW STATUS executed before and after the query to evaluate the efficiency of the query itself.
Another common possibility is to create a loop, i.e. the client sends a query with appropriate commands for the Proxy, and the query is executed N times.
Both cases are accomplished using the query queue, a data structure that the Proxy uses to process user defined queries.
The tricky part in multiple query execution is that the client has only sent one query, and thus it expects only one result. If we execute multiple queries, we will get multiple results from the server. Thus, we need to handle the results that we want to process within the Proxy and prevent them from reaching the client, while making sure that the client receives one and one only result.
  1. within read_query()
    1. insert the queries in the query queue;
    2. return an appropriate result (proxy.PROXY_SEND_QUERY), so the Proxy knows that it has to process the query queue
  2. within read_query_result()
    1. check the query ID
    2. based on the query ID, return the result to the client, or discard it
For example, to create a simple loop, where each query starting with the "LOOP N" prefix will be executed N times, we can do the following:

local max_loop = 0

function read_query (packet )
if packet:byte() ~= proxy.COM_QUERY then return end
local query = packet:sub(2)
local loop_no, repeat_query = query:match('^LOOP%s+(%d+)%s+(.+)')
if loop_no then
loop_no = loop_no + 0
if loop_no < 2 then return end
for x = 1, loop_no do
proxy.queries:append(x, string.char(proxy.COM_QUERY) .. repeat_query )
end
max_loop = loop_no
return proxy.PROXY_SEND_QUERY
end
return
end

function read_query_result (inj )
-- do something with the result
if inj.id ~= max_loop then
return proxy.PROXY_IGNORE_RESULT
end
end

Some interesting points:
  • loop_no must be transformed to a number before using it;
  • The query to be appended must be prefixed by proxy.COM_QUERY;
  • if no explicit return is given on read_query(), the default behavior is to send the query from the client to the server without changes;
  • if no explicit return is given on read_query_result(), the default behavior is to send the result from the server to the client without changes.
This recipe is quite complex and it exposes the developers to many pitfalls. Most of the nuances will be discussed in the incoming Users Conference tutorial.

This post is part of a set of recipes that will eventually become a long article.
Want to hear more? Attend MySQL Proxy - The complete tutorial at the MySQL Users Conference 2008.

Friday, March 28, 2008

MySQL Proxy recipes: tokenizing a query

Using regular expressions for query handling can become prohibitively complex after a while. If you need to manipulate parts of a query, either you are a regexp guru (I mean it, really, someone who speaks regular expressions more fluently than English) or you find some alternatives.

MySQL Proxy ships equipped with a tokenizer, a method that, given a query, returns its components as an array of tokens. Each token contains three elements:
  • name, which is a human readable name of the token (e.g. TK_SQL_SELECT)
  • id, which is the identifier of the token (e.g. 204)
  • text, which is the content of the token (e.g. "select").
For example, the query SELECT 1 FROM dual will be returned as the following tokens:
1:
text select
token_name TK_SQL_SELECT'
token_id 204
2:
text 1
token_name TK_INTEGER
token_id 11
3:
text from
token_name TK_SQL_FROM
token_id 105
4:
text dual
token_name TK_SQL_DUAL
token_id 87
It's an array of 4 elements, each one containing three items.

Armed with this new knowledge, we can try now to catch the UPDATE queries using a tokenizer.
    local tokens = proxy.tokenize(query)
if tokens[1]['token_name'] == 'TK_SQL_UPDATE' then
print ('this is an update of table ' .. tokens[2]['text'])

end
The tokenizer can do some more things, and there are some performance problems to be handled when using tokens. If you tokenize every query, it may take thrice as long as using regular expressions. With long queries, the difference can skyrocket. Tokenizing a query can cost you 10 times more than using a regular expression. The tutorial mentioned below will deal with this issue as well.

This post is part of a set of recipes that will eventually become a long article.
Want to hear more? Attend MySQL Proxy - The complete tutorial at the MySQL Users Conference 2008.

Thursday, March 27, 2008

MySQL Proxy recipes: parsing a query with regular expressions

If you want to filter a query for further usage, you need first to identify the query as the one to process, and then you need to isolate the elements to use for the task.

Both needs can be satisfied using the Lua string.match(string,pattern) function. Since Lua is an object orieneted language, this function can also be used as stringvar:match(pattern).

Let's see an example. We need to do something with with the UPDATE statements to the employees table.
function read_query( packet )
if packet:byte() ~= proxy.COM_QUERY then
return
end
local query = packet:sub(2)
local cmd, table_name = query:match('^(%w+)%s+(%w+)')
if cmd and cmd:lower() == 'update' then
print( 'updating table ' .. table_name)
if table_name == 'employees' then
print ('doing something to employees')
end
end
end
The regular expression used in this example will capture the first two words in the query. ("%w" is any character in a word. "%w+" means many word characters), and then uses the string.lower() function to check if the captured word is the one we are looking for.
Notice the idiom if cmd and cmd:lower().
If the regular expression fails, i.e. if there is no word to catch, the cmd variable will be nil, and the comparison will fail. This is necessary, because if we use if cmd:lower() when cmd is nil, we get an error message.
In this case, we get a word, and we compare it with a fixed string. If the fixed string is 'update', then we proceed, and compare the table name. If all matches, we can do what we wanted to.
For further pattern matching, see this regular expression patterns tutorial.
The above double check (first isolating a word and then comparing its contents) is necessary because Lua does not support the case insensitive pattern matching (some price to pay for its small footprint). There are some tricks to avoid this, and they will be explained during the tutorial mentioned below.

This post is part of a set of recipes that will eventually become a long article.
Want to hear more? Attend MySQL Proxy - The complete tutorial at the MySQL Users Conference 2008.

Wednesday, March 26, 2008

MySQL Proxy recipes: returning an error

Returning an error message is one of the tasks that may become common when working with MySQL Proxy.
Let's say that you want to prevent users from querying your database at a given time. The most sensible answer that you would send to the client that is requesting a query in the forbidden period is an error message. Not only that, the client must receive an error code and SQL state, as if the error were issued by the database server.
With MySQL Proxy, an error set is a legitimate packet to be sent back to the client, and thus you can return a customized error in answer to any query.
function error_result (msg, code,state)
proxy.response = {
type = proxy.MYSQLD_PACKET_ERR,
errmsg = msg,
errcode = code,
sqlstate = state,
}
return proxy.PROXY_SEND_RESULT
end
proxy.response is a variable type structure. When its type is set to proxy.MYSQLD_PACKET_ERR, you can return the three components of a error packet quite easily. For example, to prevent queries between 13:00 and 14:00, you can use this code:
    local t = os.date('*t')
if t.hour == 13 then
return error_result(
'no queries allowed between 13:00 and 14:00', -- error message
1314, -- error code
'!1314' -- SQL state
)
end
and the user will receive the error that looks like any other issued by the server:
show tables;
ERROR 1314 (!1314): no queries allowed between 13:00 and 14:00
This post is part of a set of recipes that will eventually become a long article.
Want to hear more? Attend MySQL Proxy - The complete tutorial at the MySQL Users Conference 2008.

Tuesday, March 25, 2008

MySQL Proxy recipes: returning a dataset

How do you return a dataset using MySQL Proxy?
This being a common task, as many that we will see in these pages, it is worth implementing with a function.
When you return a dataset, there are two main cases:
  • Returning a single row with just one column. For example, when you need to give the user a simple message;
  • Returning one or more rows with several columns. This is much more useful, and covers case like displaying help information, or creating a tabular set of information.
The first case is quite simple:
function simple_dataset (header, message)
proxy.response.type = proxy.MYSQLD_PACKET_OK
proxy.response.resultset = {
fields = {
{type = proxy.MYSQL_TYPE_STRING, name = header}
},
rows = {
{ message}
}
}
return proxy.PROXY_SEND_RESULT
end
This function is, as required, quite simple. The dataset has just one column, and the name of the column is user defined.
Calling this function with return simple_dataset('from user', 'this message') will cause the Proxy to return a dataset to the client, as if it was received from the database server.
The client will receive:
+--------------+
| from user |
+--------------+
| this message |
+--------------+
A multiple column dataset requires some more work. You need to pass an array for the headers, and a two-dimensional array for the values.
function proxy.global.make_dataset (header, dataset)
proxy.response.type = proxy.MYSQLD_PACKET_OK

proxy.response.resultset = {
fields = {},
rows = {}
}
for i,v in pairs (header) do
table.insert(
proxy.response.resultset.fields,
{type = proxy.MYSQL_TYPE_STRING, name = v})
end
for i,v in pairs (dataset) do
table.insert(proxy.response.resultset.rows, v )
end
return proxy.PROXY_SEND_RESULT
end
Using this function is straightforward. For example, to return a simple help for some custom made commands, we can do:
return make_dataset(
{'command', 'description' }, -- the header
{ -- the rows
{'FOO', 'removes the database'},
{'BAR', 'drops all tables'},
{'FOOBAR', 'makes the server explode'},
}
)
The result on the client is
+---------+--------------------------+
| command | description |
+---------+--------------------------+
| FOO | removes the database |
| BAR | drops all tables |
| FOOBAR | makes the server explode |
+---------+--------------------------+
If you keep these two functions at hand, your Proxy scripts will become more manageable.

This post is part of a set of recipes that will eventually become a long article.
Want to hear more? Attend MySQL Proxy - The complete tutorial at the MySQL Users Conference 2008.

Monday, March 24, 2008

Summer of Code projects for MySQL Proxy

Google Summer of Code opens for proposals from March 24th to 31st.
There are several projects available in the ideas page. I am available to mentor some projects about MySQL Proxy enhancements. If you like any of them or have any other Proxy related project to suggest, feel free to discuss a proposal in the SoC mailing list.
Some caveats for students willing to try their hand at any Summer Of Code project:
  • Please state your programming skills clearly. Don't inflate your previous experience.
  • Remember that this is a full time job. You won't have time to spend on long vacations, and you won't be able to work at these projects together with another job;
  • A Summer of Code is a full time job. You will be requested to put up 40 hours a week.
  • You will be requested to submit weekly reports;
  • There are dates when you are requested to submit your results. Please consider them carefully before accepting. If you don't make the deadline, you won't get paid.
The above remarks may sound too harsh, but consider that Google is going to pay a non trivial amount of money for your participation, and in exchange for that money you will have to produce what you agree with the mentoring organization.
And keep in mind that your mentors have a full time job of their own. They will be allowed by the mentoring organizations to dedicate a limited amount of time to Summer of Code (even though I know of mentors who have dedicated much of their free time to SoC projects). In this situation, if you work hard, you will be making your time and theirs worth the effort, and everyone wins.
Instead, if you overcommit at the beginning, or don't work hard throughout the summer, it will be a wasted experience for all.

That said, cooperation between companies with experienced developers and students willing to prove themselves has often resulted in excellent work. If you know what awaits you and you are willing to try, you are most welcome!

Monday, March 17, 2008

Using the event scheduler with OS commands

One of the major additions to MySQL 5.1 is the the event scheduler. It is an internal scheduler, which does not need any help from the operating system. As such, it works independently in every platform.
One drawback of this feature, though, is that it can't communicate with the operating system. i.e. the event scheduler can't read system files, can't send e-mail messages, store data into log files. It can only work within the database server. This is convenient for security, but it is quite limiting. Time for hacking!

In getting started with MySQL Proxy I showed an example of how to run shell commands from any MySQL client. Unfortunately, this method can't be used with the events, because events can't send queries to the outside. Or can they? Let's be creative, and combine Federated tables and MySQL Proxy:
drop table if exists t1, t1f;
create server fed
foreign data wrapper mysql
options (
host '127.0.0.1',
port 4040
database 'test',
user 'msandbox',
password 'msandbox'
);
create table t1 (
id int nt null, cmd varchar(250), primary key (id), key (cmd)
);
create table t1f (
id int not null, cmd varchar(250), primary key (id), key (cmd)
) engine=federated connection = 'fed/t1';
Table t1f is Federated, and it is accessed through the Proxy port (4040). Thus, every query directed to this table will be intercepted by MySQL Proxy, and then we can do what we want.
The Lua script associated with this Federated table is the following, which intercepts UPDATE statements directed to table t1, and sends the contents of the cmd column to an echo statement, using a OS call. (It's just a proof of concept)
function read_query(packet)
if packet:byte() ~= proxy.COM_QUERY then return end
local query = packet:sub(2)
if query:match('UPDATE') then
local tokens = proxy.tokenize(query)
if tokens[10]['token_name'] == 'TK_INTEGER'
and tokens[2]['text'] == 't1'
and tokens[10]['text'] == '1' then
print( " --- " .. query )
os.execute('echo "executing ### ' .. tokens[6]['text'] .. ' ###"')
end
end
end
In short, this script checks if we are updating table t1 (not t1f! The Federated engine accesses the base table) with id = 1, and if yes, uses the content of cmd as argument for an OS command.
Now, let's create and event and see what happens:
set global event_scheduler=1;
create event e1
on schedule every 10 second
do
update t1f set cmd=concat('do this ', now())
where id =1;
The result, as observed by the Proxy, is as follows:
--- UPDATE `t1` SET `cmd` = 'do this 2008-03-17 02:27:47' WHERE `id` = 1 LIMIT 1
executing ### do this 2008-03-17 02:27:47 ###
--- UPDATE `t1` SET `cmd` = 'do this 2008-03-17 02:27:57' WHERE `id` = 1 LIMIT 1
executing ### do this 2008-03-17 02:27:57 ###
QED!

Thursday, March 13, 2008

Looking for a MySQL Proxy guru


MySQL Proxy is the most exciting addition to the range of MySQL products since 5.0. Using Proxy you can convert your database server into an application server, or you can create new command on the fly, fix bugs, filter queries, add load balancing to a set of servers, and a myriad of wonderful things.
The company itself is planning to do more with MySQL Proxy, and we have come to a point where we have more works in our hands that we can manage with the current manpower. So, we are looking for a Proxy enthusiast to become a QA engineer. The job opening is online. Look it up. It's a challenging job, but I can promise you that it's really exciting! (Working with developers like Jan Kneschke, Kay Roepke, Mark Matthews, Eric Herman, and the rest of the Enterprise team is a rewarding experience)

Monday, March 10, 2008

Reason #7 to attend the MySQL UC 2008

MySQL Conference & Expo 2008
Disclaimer: Forget about my affiliation, this is my personal list of things that I am going to enjoy at the UC.

#7 MySQL Proxy : the complete tutorial


I shall start with a shameless plug, of course. I am going to enjoy this tutorial for several reasons.

For starters, it's the first tutorial I get to host at the Users Conference, and this is understandably satisfactory in itself.
Then, because it is going to give me the technical room that I was longing for. I have been writing and speaking about MySQL Proxy for 10 months, and on every occasion I felt that I had time or space limitations. There was not enough time to explain all that we can do with Proxy, or not enough time to write a longer article.
Now we can remedy. I and Jan Kneschke will have 6 full hours to explain Proxy beauty and intricacies, ranging from simple wizardry to replication goodies.
We will cover the basics of Lua language, with some internals, so that the attendees will leave the tutorial with the basic know-how to use the Proxy effectively.
There are still available seats. Hurry up and register!

Tuesday, January 29, 2008

Slides from MySQL Proxy presentation at LCA 2008


The MySQL Proxy presentation at Linux Conf Australia 2008 was done just before lunch.
As announced, here are the presentation slides
The penguin on the above image is actually painted on my room's window glass.