{"id":6579,"date":"2013-10-01T08:50:08","date_gmt":"2013-10-01T06:50:08","guid":{"rendered":"http:\/\/code.openark.org\/blog\/?p=6579"},"modified":"2013-10-01T08:50:08","modified_gmt":"2013-10-01T06:50:08","slug":"on-mysql-plugin-configuration","status":"publish","type":"post","link":"https:\/\/code.openark.org\/blog\/mysql\/on-mysql-plugin-configuration","title":{"rendered":"On MySQL plugin configuration"},"content":{"rendered":"<p>MySQL offers <a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.5\/en\/plugin-api.html\">plugin API<\/a>, with which you can add <a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.5\/en\/plugin-types.html\">different types<\/a> of plugins to the server. The API is roughly the same for all plugin types: you implement an init() function, a deinit(); you declare status variables and global variables associated with your plugin, and of course you implement the particular implementation of plugin call.<\/p>\n<p>I wish to discuss the creation and use of global variables for plugins.<\/p>\n<p>Consider the following declaration of a global variable in <a href=\"https:\/\/github.com\/outbrain\/audit_login\">audit_login<\/a>:<\/p>\n<blockquote>\n<pre>static MYSQL_SYSVAR_BOOL(enabled, plugin_enabled, PLUGIN_VAR_NOCMDARG,\r\n\"enable\/disable the plugin's operation, namely writing to file\", NULL, NULL, 1);\r\n\r\nstatic struct st_mysql_sys_var * audit_login_sysvars[] = {\r\n\u00a0\u00a0\u00a0 MYSQL_SYSVAR(enabled),\r\n\u00a0\u00a0\u00a0 NULL\r\n};<\/pre>\n<\/blockquote>\n<p>The above creates a new global variables called <strong>&#8220;simple_login_audit_enabled&#8221;<\/strong>: it is composed of the plugin name (known to be <strong>&#8220;simple_login_audit&#8221;<\/strong> in our example) and declared name (<strong>&#8220;enabled&#8221;<\/strong>). It is a boolean, defaults to <strong>1<\/strong>, and is associated with the internal <strong>plugin_enabled<\/strong> variable.<\/p>\n<p>Once this variable is declared, you can expect to be able to:<!--more--><\/p>\n<blockquote>\n<pre>mysql&gt; show global variables like '%audit%';\r\n+----------------------------+-------+\r\n| Variable_name\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 | Value |\r\n+----------------------------+-------+\r\n| simple_login_audit_enabled | ON\u00a0\u00a0\u00a0 |\r\n+----------------------------+-------+\r\n\r\nmysql&gt; set global simple_login_audit_enabled := 0;\r\nQuery OK, 0 rows affected (0.00 sec)<\/pre>\n<\/blockquote>\n<p>and you can expect using the following in your <strong>my.cnf<\/strong> file:<\/p>\n<blockquote>\n<pre>[mysqld]\r\n...\r\nsimple_login_audit_enabled=1<\/pre>\n<\/blockquote>\n<h4>Assuming your server agrees to start<\/h4>\n<p>Here&#8217;s the catch: the <strong>simple_login_audit_enabled<\/strong> variable is <em>only recognized as long as the plugin is installed<\/em>. As you may know, plugins can be loaded upon startup time using an explicit <strong>my.cnf<\/strong> entry such as:<\/p>\n<blockquote>\n<pre>plugin_load=audit_login.so<\/pre>\n<\/blockquote>\n<p>But you may also, at any given time, <a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.5\/en\/install-plugin.html\">INSTALL<\/a> or <a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.5\/en\/uninstall-plugin.html\">UNINSTALL<\/a> the plugin dynamically.<\/p>\n<blockquote>\n<pre>install plugin SIMPLE_LOGIN_AUDIT soname 'audit_login.so';\r\nuninstall plugin SIMPLE_LOGIN_AUDIT;<code>\r\n<\/code><\/pre>\n<\/blockquote>\n<p>In fact there are good reasons to do so: you may be upgrading your plugin. You can&#8217;t just throw in the new binary (it&#8217;s a guaranteed crash on next server shutdown). You need to first <strong>UNINSTALL<\/strong> it; you then put the new binary, and re-<strong>INSTALL<\/strong>. This works well, and the price is some downtime for your plugin.<\/p>\n<p>But what happens if you restart the server while your plugin is uninstalled? Yep: the global variable is unrecognised, and your MySQL server refuses to start:<\/p>\n<blockquote>\n<pre>130919\u00a0 8:11:30 [ERROR] \/usr\/bin\/mysqld: <strong>unknown variable 'simple_login_audit_enabled=1'<\/strong>\r\n130919\u00a0 8:11:30 [ERROR] <strong>Aborting<\/strong>\r\n130919\u00a0 8:11:30\u00a0 InnoDB: Starting shutdown...\r\n130919\u00a0 8:11:31\u00a0 InnoDB: Shutdown completed; log sequence number 40185651\r\n130919\u00a0 8:11:31 [Note] \/usr\/bin\/mysqld: Shutdown complete<\/pre>\n<\/blockquote>\n<p>I did happen on this case a couple times; it is frustrating.<\/p>\n<h4>What are the alternatives?<\/h4>\n<p>So adding variables to my.cnf may prevent MySQL from starting. In my dictionary, this spells <strong>&#8220;NO GO&#8221;<\/strong>.<\/p>\n<p>With <strong>audit_login<\/strong> I chose to (additionally) support an external config file, <strong>audit_login.cnf<\/strong>, expected to be found in the <strong>@@datadir<\/strong>. It is similar in essence to the <strong>master.info<\/strong> file which is expected by replication.\u00a0The plugin reads this file (if existing) upon init(), which makes it execute upon server startup or upon <strong>INSTALL PLUGIN<\/strong>. I can&#8217;t argue that this is the best solution, but it is a solution that does not interfere with anyone. The file is ignored by all and does not disturb the public peace. The plugin does not require it to exist.<\/p>\n<p>I was hoping to be able to directly read from <strong>my.cnf<\/strong>, but am unsure if there is a definitive way to do so from within the plugin. I did not go deep into this.<\/p>\n<h4>What would be best?<\/h4>\n<p>Hopefully I&#8217;m not missing on anything. But it would be nice to have plugin-dedicated variables in my.cnf which are ignored by the server. These could take the form of:<\/p>\n<blockquote>\n<pre>[mysql_plugin]\r\nsimple_login_audit_enabled=0<\/pre>\n<\/blockquote>\n<p>or similar. It would be the server&#8217;s responsibility to pass these declarations to the plugins, but ignore them itself (or just pass warning).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>MySQL offers plugin API, with which you can add different types of plugins to the server. The API is roughly the same for all plugin types: you implement an init() function, a deinit(); you declare status variables and global variables associated with your plugin, and of course you implement the particular implementation of plugin call. [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"enabled":false},"version":2}},"categories":[5],"tags":[11,120,80],"class_list":["post-6579","post","type-post","status-publish","format-standard","hentry","category-mysql","tag-configuration","tag-development","tag-plugin"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2bZZp-1I7","_links":{"self":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/6579","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/comments?post=6579"}],"version-history":[{"count":9,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/6579\/revisions"}],"predecessor-version":[{"id":6602,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/6579\/revisions\/6602"}],"wp:attachment":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/media?parent=6579"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/categories?post=6579"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/tags?post=6579"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}