Details
-
Task
-
Status: Closed (View Workflow)
-
Minor
-
Resolution: Won't Fix
-
None
-
None
Description
Add a interface to plugins that allow a communication between plugin at server side and mysql client
The "mysql" keyword here can be mysql/mariadb (or maybe only mariadb =] )
I will use the php mysql* function to explain this MDEV
THIS IS VERY IMPORTANT TO DAEMON PLUGINS!
The mysql server will be used as a "PROXY" between mysql client api and plugin server side interface
—
with this MDEV we can add, via plugins, a nosql interface using ONLY ONE mysql client connection
the main goals here are:
- only one connection to mysql server (easier to firewalls and developers since we only need to configure one connection, and not a connection to mysql server and a connection to a memcached/handler socket/nosql server)
- connection via tcp/ip, unix socket, windows pipes, or anything else mysql protocol can use
- can use mysql embedded =]
- can use ssl security layer of mysql protocol, transparent to plugins (no external link to openssl or different ssl from mysql server) =)
- since we must have a mysql link, plugin communication is secured via mysql_connect() auth system using user, password, host, auth plugins and others kinds of validation
- we don't need to configure clients that can or can't connect to our plugin since every user that will connect here is know in mysql server user tables
- we don't need external links inside plugin source code to libevent, socket, or anyother communication api that allow a client-server communication to client side
- we can use it on linux and windows and any mysql supported operation system \o/
- many many others goals
problems:
- maybe some one will want many connections, and we could/should have a limit to this connections
- others buffers / connection limits that must be considered
- others client permissions that must be considered
- this allow to a bad user create a http proxy or a security problem at server side, but since it's open source maybe DBA will read the source of plugin before allowing it to execute
- maybe some plugins will want "query cache", it's not the mysql server query cache, but a interface to it... when a table change contact plugin that table changed to invalidate the plugin cached too, this allow a daemon plugin query cache that is in sync with mysql daemon tables
------------------
SERVER SIDE API
we need some functions to plugins.... (i don't know what plugin can use it...)
plugin_register_connection_name(
|
"some unique connection name, like the TCP port for IP protocol, or the unix socket file",
|
plugin function to create connections,
|
plugin function to kill connection,
|
plugin function to receive packets,
|
plugin function to query cache table / partition prune / or query cache reset
|
);
|
plugin_create_connection_function( THD being_used, server_unique_plugin_connection_id)
|
this function will be called when client create a connection
the server unique plugin connection id is created before calling it, it's unique in entire server (mutex must be used here)
the function will return OK - connection created, NO - connection rejected
maybe we could add a ERROR code and a ERROR message to client side plugin api
plugin_drop_connection_function( THD being_used, server_unique_plugin_connection_id, type)
|
this function will be called to drop communication and free resources used
use type variable parameter to check why connection is being droped
the plugin connection can be droped when:
- client side api drop a connection to plugin
- dba send a "KILL PLUGIN CONNECTION" (new command) to kill this plugin connection
- thread is killed in server (KILL command)
- server shutdown is being executed
- plugin is being removed (UNINSTALL PLUGIN command)
plugin_new_packet_function(THD being_used, server_unique_plugin_connection id, packet, length)
|
this function is called when client send a raw command to plugin
here the packet have the right order and right checksum (tcp/ip)
we must return a RAW packet or a QUERY return (used by mysql_query / mysql_fetch_assoc / mysql_num_rows client side api)
how we return isn't defined... maybe three functions...
- one for tell what kind of return (RAW or QUERY)
- one to send raw packets
- one to send the result (like a information schema plugin return - http://dev.mysql.com/doc/internals/en/com-query-response.html)
plugin_send_to_client(server_unique_plugin_connection_id, packet, length)
|
here we send a packet to client
that's not a client->plugin return, this is a new plugin->client message
for example a video stream, send server informations like a thread created, or a slow query executed, or anything else that occur first at server, and client don't need to pool server every second to know if something changed...
plugin_close_connection(server unique plugin connection id)
|
this can be used by plugin to kill a connection to client side api
maybe we could send a packet to client to tell that the connection was dropped by plugin
plugin_query_cache_prune(parameters)
|
this function will be called when:
a table/partition change that cause a query cache invalidation
query cache was reseted (truncated)
------------------
DBA INTERFACE
1)we must know if a thread have plugin connections associated with it or not...
this can be done via information schema tables...
UNIQUE PLUGIN CONNECTION ID | THREAD ID | PLUGIN NAME | CONNECTION NAME | STATE |
---|---|---|---|---|
1 | 2 | 1 | "slow query monitor" | SENDING DATA TO CLIENT |
2 | 2 | 1 | "memcached" | OPEN |
3 | 2 | 1 | "handler socket write" | OPEN |
4 | 2 | 1 | "handler socket read" | OPEN |
STATE = OPEN / CLOSING / RECEIVED DATA FROM CLIENT / RETURNING DATA TO CLIENT / SENDING DATA TO CLIENT
2)we can kill a plugin connection ...
using unique plugin connection id:
KILL PLUGIN CONNECTION <unique plugin connection id>, <unique plugin connection id>, <unique plugin connection id>
|
kill one connection (or a list of connections)
using thread id
KILL PLUGIN CONNECTION THREAD <thread id>
|
kill all connection from a thread
using user name
KILL PLUGIN CONNECTION USER <user>
|
kill all connection from a user
------------------
CLIENT SIDE API
Today we have some commands at mysql protocol http://dev.mysql.com/doc/internals/en/text-protocol.html
this MDEV will add 5 new commands (maybe more if we need):
1)PLUGIN_CREATE_CONNECTION
2)PLUGIN_DROP_CONNECTION
3)PLUGIN_CLIENT_SEND
4)PLUGIN_SERVER_RETURN
5)PLUGIN_SERVER_SEND
—
1) Create a new communication with plugin (PLUGIN_CREATE_CONNECTION)
this command will create a new ID that client will use to communicate between mysql client, and the plugin at mysql server, and the plugin to client, example:
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
|
$plugin_socket = mysql_plugin_connect($link,"plugin_connection_name"); // <---HERE
|
the mysql_plugin_connect call mysql server to create a new communication with plugin
mysql server will check if any plugin have a interface registered as "plugin_connection_name"
if yes, it will ask plugin if we could or couldn't create a new plugin connection
the return of this function is a unique id that represent the plugin and connection being used in entire server (like query_id), this must be mutex locked
2) Drop communication with plugin
based on mysql_plugin_connect(), we need a plugin close command:
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
|
$plugin_socket = mysql_plugin_connect($link,"plugin_connection_name");
|
mysql_plugin_close($link,$plugin_socket);
|
here the connection with $plugin_socket will be closed at mysql server side
plugin will be called to free all resources used in this connection
3,4) sending packets to plugin (PLUGIN_CLIENT_SEND), and plugin returning packets to client (PLUGIN_SERVER_RETURN)
now that we have a link between mysql client, and plugin, we need to send and receive data...
this can be done in many ways... here i will give an example, but we can improve it (like always =] )
the communication can (must check if it's easy) start at plugin side, or at client side
when returning a client command (a plugin return):
the plugin can send a query result (like a SQL command) that can be used with mysql_fetch_assoc, mysql_num_rows, operating like a mysql_query function
the plugin can send a raw command (like a raw tcp/ip protocol) that can be used to create http proxy, nosql protocol, and anything using client/server idea
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
|
$plugin_socket = mysql_plugin_connect($link,"plugin_connection_name");
|
while(true){
|
$return=mysql_plugin_send($link,$plugin_socket,"here i'm sending a raw text command to plugin");
|
//$return have information about what kind of return we have, a mysql command, or a raw command
|
if(mysql_plugin_return_type($return)==MYSQL_PLUGIN_RETURN_RAW){ // we have a raw packet
|
$data=mysql_plugin_return_read($return); // get raw data
|
mysql_plugin_return_free($return); // free return buffer
|
// here we can process data (maybe create a handler socket protocol or a memcache protocol or any other nonsql protocol
|
}else{ // we have a query return
|
for($i=0;$i<mysql_num_rows($return);$i++){
|
$data=mysql_fetch_assoc($return);
|
}
|
mysql_free_result($return);
|
}
|
}
|
mysql_plugin_close($plugin_socket);
|
now we have 3 new functions (they are sync and blocking in this example, but we can add more functions in future...)
$return=mysql_plugin_send($link,$plugin_socket,"here i'm sending a raw text command to plugin");
|
mysql_plugin_send(<mysql link>,<plugin socket id>, <message>)
this function send raw data to plugin and wait a return,
the return can be used by three others functions:
mysql_plugin_return_type($return)
|
this function tell if we have:
raw return (MYSQL_PLUGIN_RETURN_RAW) or
query return ("COM_QUERY Response" like mysql_query function - http://dev.mysql.com/doc/internals/en/com-query-response.html )
$data=mysql_plugin_return_read($return);
|
this function will read raw data from raw return buffer
mysql_plugin_return_free($return);
|
this function will clean raw read buffer
5) PLUGIN_SERVER_SEND, plugin starting a communication to client
i didn't think about this kind of problem yet....
but we can use to know for example if a table have being changed
or if some trigger happened, this is usefull in situations that we 'pool' server
with queries to know what's happening, for example we could create a plugin that
report when a new client connect, or when a new query start, or when a slow query
is being executed
the main problem here is how to implement this at client side, since api don't have a async call (or have?)...
this is a solution like libevent, select, and many others client/server apis
maybe we could have a two functions:
mysql_plugin_check_new_message()
|
function to know if we received a new plugin packet
mysql_plugin_read_message()
|
to read the message
or a async api...
mysql_plugin_register_async_receive( function being called when new packet is received )
|
this will register a function that will be called when a new packet from plugin is received
and use the mysql_plugin_check and read functions to read
to return to server we can use the PLUGIN_CLIENT_SEND, PLUGIN_SERVER_RETURN flow (3,4)
—
that's all