How to show all user-defined variables (MySQL) - mysql

I set two user-defined variables as shown below but after some time, I forgot the names:
SET #a = 2, #b = 3;
So, does MySQL have the command that displays all user-defined variables?

Starting with MySQL 5.7, the performance schema exposes user variables.
See table performance_schema.user_variables_by_thread
https://dev.mysql.com/doc/refman/5.7/en/performance-schema-user-variable-tables.html

If you have MariaDB (a binary "drop-in" equivalent of MySQL) there is a plugin available, provided by MariaDB itself.
MariaDB 10.2 (equivalent to MySQL 5.7) and above has a plugin that creates a "USER_VARIABLES" table.
Here is how to install the plugin.
Here is an example of its use:
SELECT * FROM information_schema.USER_VARIABLES ORDER BY VARIABLE_NAME;
+---------------+----------------+---------------+--------------------+
| VARIABLE_NAME | VARIABLE_VALUE | VARIABLE_TYPE | CHARACTER_SET_NAME |
+---------------+----------------+---------------+--------------------+
| var | 0 | INT | utf8 |
| var2 | abc | VARCHAR | utf8 |
+---------------+----------------+---------------+--------------------+
MariaDB installs the plugin by default after version MariaDB 10.2.6.
The link above shows how to install it for prior versions.
Double check what version of "mysql" you're running, because sometimes people will refer to a MariaDB as MySQL, due to its use as a "binary drop in replacement" for MySQL. So it's possible that you are running a MariaDB database.
I am not aware of MySQL providing anything similar.
How to check which version of mysql you're running (the prompt is in bold)
From the command line:
$ mysql -v
From the mysql command client:
mysql> SHOW VARIABLES LIKE "%version%";
It is also shown when you first log into the mysql command client, which you can do via:
$ mysql -u your_mysql_username --password=your_mysql_password

With performance_schema.user_variables_by_thread, you can show all user-defined variables as shown below:
mysql> SELECT * FROM performance_schema.user_variables_by_thread;
+-----------+---------------+--------------------------------+
| THREAD_ID | VARIABLE_NAME | VARIABLE_VALUE |
+-----------+---------------+--------------------------------+
| 69 | first_name | 0x4A6F686E |
| 69 | last_name | 0x536D697468 |
+-----------+---------------+--------------------------------+

Related

from_base64() not decoding back to original text

The from_base64() does not decode correctly. Please see the problem demo below.
mysql> select to_base64('sometext');
+-----------------------+
| to_base64('sometext') |
+-----------------------+
| c29tZXRleHQ= |
+-----------------------+
1 row in set (0.27 sec)
mysql> select from_base64('c29tZXRleHQ=');
+----------------------------------------------------------+
| from_base64('c29tZXRleHQ=') |
+----------------------------------------------------------+
| 0x736F6D6574657874 |
+----------------------------------------------------------+
1 row in set (0.00 sec)
This was working till i moved to latest ubuntu 19.10.
Server version: 8.0.19 MySQL Community Server - GPL
mysql --version
mysql Ver 8.0.19-0ubuntu0.19.10.3 for Linux on x86_64 ((Ubuntu))
This is because of the following.
--binary-as-hex
When this option is given, mysql displays binary data using hexadecimal notation (0xvalue). This occurs whether the overall output dislay format is tabular, vertical, HTML, or XML.
As of MySQL 8.0.19, when mysql operates in interactive mode, this option is enabled by default. In addition, output from the status (or \s) command includes this line when the option is enabled implicitly or explicitly:
To disable hexadecimal notation, use --skip-binary-as-hex
MySQL client options

Rails5: Why is a migration breaking my production environment but not my test environment?

I have a migration in rails that does the following:
class AddMissingIndexes < ActiveRecord::Migration[5.1]
def change
# Applications
add_index :applications, :evid, length: { evid: 255 }
end
end
This seems to run smoothly in my test environment
However when I run the migration in my production environment
I get this error:
Mysql2::Error: Specified key was too long; max key length is 767 bytes: CREATE INDEX `index_applications_on_evid` ON `applications` (`evid`(255))
I'm trying to fix this issue using the second answer from this question
class AddMissingIndexes < ActiveRecord::Migration[5.1]
def change
# Applications
add_index "applications", ["evid"], :name => :evid, :length => { :evid => 255 }
end
end
However I want to make sure this works before making any further changes to the schema. So I need to be able to reproduce this error in my test environment.
Test environment:
+-------------------------+------------------+
| Variable_name | Value |
+-------------------------+------------------+
| innodb_version | 5.5.62 |
| protocol_version | 10 |
| slave_type_conversions | |
| version | 5.5.62-0+deb8u1 |
| version_comment | (Debian) |
| version_compile_machine | x86_64 |
| version_compile_os | debian-linux-gnu |
+-------------------------+------------------+
Production environment
+-------------------------+---------------------+
| Variable_name | Value |
+-------------------------+---------------------+
| innodb_version | 5.6.40 |
| protocol_version | 10 |
| slave_type_conversions | |
| version | 5.6.40-log |
| version_comment | Source distribution |
| version_compile_machine | x86_64 |
| version_compile_os | Linux |
+-------------------------+---------------------+
Using SHOW GLOBAL VARIABLES LIKE 'innodb_%';
I'm able to see my test environment database and this is what I found that my local db environment has the following variables like this:
Test Environment
innodb_file_format=Barracuda;
innodb_large_prefix=1;
innodb_file_per_table=1;
innodb_file_format_max=Barracuda;
innodb_strict_mode=1;
character_set_server='utf8mb4';
Production Environment
innodb_file_format=Antelope;
innodb_large_prefix=OFF;
innodb_file_per_table=ON;
innodb_file_format_max=Antelope;
innodb_strict_mode=OFF;
character_set_server='utf8mb4';
I tried to reproduce my production environment setting the variables going 1 at a time. But to no avail.
Run SHOW CREATE TABLE applications\G in both your test and production environment. I predict the difference will be:
Test:
CREATE TABLE `applications` (
...
`evid` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Production:
CREATE TABLE `applications` (
...
`evid` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
An index must be able to fit in 767 bytes, as the error says. The utf8 character set counts 3 bytes per character toward this limit, so 3*255 = 765, which fits.
Whereas utf8mb4 counts 4 bytes per character. 4*255 = 1020, which is too long.
You can index VARCHAR(191) when you use utf8mb4, to stay within 767 bytes.
Alternatively, you can use newer InnoDB row format to support index size up to 3072 bytes. See mysql change innodb_large_prefix
If you want to avoid these sorts of surprises, it's important to run the same version of MySQL in your testing and production, and make sure you make the MySQL config options as close as possible, and make sure the table definitions are identical.
Re your updated question with innodb config variables.
I see your production environment has settings that mean it is unable to define tables with the Barracuda file format, which means no DYNAMIC row format, which means no innodb_large_prefix.
You need to make the settings match your test environment, and then you probably need to rebuild your table so it's really in Barracuda format with DYNAMIC row format.
I also recommend (again) that you upgrade your test server to the same MySQL version you run in production.
Also compare other config settings, to see if there are other differences (besides those that are appropriate to be different from production, like innodb_buffer_pool_size).
You should also make sure you use the same version of other parts of your tech stack like Linux version, Ruby version, etc. It's a well-known source of project instability and schedule delays if you are surprised by version incompatibilities, if you fail to make your dev and test environments match your production environment.

Mysql binlog path from mysql console

Is there a way to know the bin log files path from mysql console as we can know whether its ON or OFF by using
Select * information_schema.GLOBAL_VARIABLES
where variable_name like '%log_bin%'.
Use this to show on/off:
SHOW VARIABLES LIKE 'log_bin'
Also:
SHOW GLOBAL VARIABLES LIKE '%bin%'
Or
SHOW SESSION VARIABLES LIKE ...
More Information: (notice that some of these values and results changed from 5.5 to 5.6!)
http://dev.mysql.com/doc/refman/5.5/en/show-master-status.html
mysql > SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73 | test | manual,mysql |
+---------------+----------+--------------+------------------+
mysql> SHOW BINARY LOGS;
+---------------+-----------+
| Log_name | File_size |
+---------------+-----------+
| binlog.000015 | 724935 |
| binlog.000016 | 733481 |
+---------------+-----------+
From the docs regarding log-bin"
Setting this option causes the log_bin system variable to be set
to ON (or 1), and not to the base name. This is a known issue;
see Bug #19614 for more information.
There is a workaround using mysqld instead in the Bug 19614 which I modified a bit. If you are scripting, you can use from the mysql client (which I found a bit tedious to do, see the next workaround):
mysql >\! dirname $(mysqld --help --verbose 2> /dev/null | egrep "^log-bin " | grep -o "\/.*")
Looks like there is a patch submitted by Mark Callaghan, and it was never committed. There is a function in WP5465 (which is the work in progress for this patch), however it didn't work properly for me, as the location of the logs can be different across setups.

How to kill MySQL connections

I'm building a website with MySQL. I'm using TOAD for MySQL and suddenly I can't connect to the database as I'm getting an error:
"Too many connections"
Is there any way in Toad for MySQL to view existing connections to be able to kill them or simple close all connections all together?
No, there is no built-in MySQL command for that. There are various tools and scripts that support it, you can kill some connections manually or restart the server (but that will be slower).
Use SHOW PROCESSLIST to view all connections, and KILL the process ID's you want to kill.
You could edit the timeout setting to have the MySQL daemon kill the inactive processes itself, or raise the connection count. You can even limit the amount of connections per username, so that if the process keeps misbehaving, the only affected process is the process itself and no other clients on your database get locked out.
If you can't connect yourself anymore to the server, you should know that MySQL always reserves 1 extra connection for a user with the SUPER privilege. Unless your offending process is for some reason using a username with that privilege...
Then after you can access your database again, you should fix the process (website) that's spawning that many connections.
mysql> SHOW PROCESSLIST;
+-----+------+-----------------+------+---------+------+-------+---------------+
| Id | User | Host | db | Command | Time | State | Info |
+-----+------+-----------------+------+---------+------+-------+----------------+
| 143 | root | localhost:61179 | cds | Query | 0 | init | SHOW PROCESSLIST |
| 192 | root | localhost:53793 | cds | Sleep | 4 | | NULL |
+-----+------+-----------------+------+---------+------+-------+----------------+
2 rows in set (0.00 sec)
mysql> KILL 192;
Query OK, 0 rows affected (0.00 sec)
USER 192 :
mysql> SELECT * FROM exept;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
mysql> SELECT * FROM exept;
ERROR 2013 (HY000): Lost connection to MySQL server during query
While you can't kill all open connections with a single command, you can create a set of queries to do that for you if there are too many to do by hand.
This example will create a series of KILL <pid>; queries for all some_user's connections from 192.168.1.1 to my_db.
SELECT
CONCAT('KILL ', id, ';')
FROM INFORMATION_SCHEMA.PROCESSLIST
WHERE `User` = 'some_user'
AND `Host` = '192.168.1.1'
AND `db` = 'my_db';
I would recommend checking the connections to show the maximum thread connection is
show variables like "max_connections";
sample
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 13 |
+-----------------+-------+
1 row in set
Then increase it by example
set global max_connections = 500;
In MySQL Workbench:
Left-hand side navigator > Management > Client Connections
It gives you the option to kill queries and connections.
Note: this is not TOAD like the OP asked, but MySQL Workbench users like me may end up here
As above mentioned, there is no special command to do it. However, if all those connection are inactive, using 'flush tables;' is able to release all those connection which are not active.

Why does the MySQL built-in function 'current_user()' return a hostname containing a '%' symbol?

Does MySQL have built in function to get host name?
Similar to
select user(); //this returns user#userip
Edit:
select current_user(); //returns user#10.0.3.%
Last symbol is % -- why?
SELECT ##hostname;
--mysql 4.1 didn't have this one.
select current_user(); returns user#10.0.3.% last simbol is % why ??
the % is the record in mysql.user that match your current login
which can be derived from
select concat(user, '#', host) from mysql.user;
the % is determined by host value.
wouldn't his work?
select substring_index(user(),'#', -1) as hostname;
The above is wrong, it returns the user's IP not host's. I was fooled by testing on local. Sorry about that.
I guess this returns host name, but this wouldn't be useful unless you are ready to grep, pipe and cut Just a FYI:
C:\>mysqladmin -u username -pmypassword -h dev.naishelabs.com version
mysqladmin Ver 8.41 Distrib 5.0.22, for Win32 on ia32
Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This software comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to modify and redistribute it under the GPL license
Server version 5.0.77
Protocol version 10
Connection dev.naishelabs.com via TCP/IP
TCP port 3306
Uptime: 73 days 5 hours 7 min 45 sec
If you want the hostname of the database server, you can use SHOW VARIABLES:
mysql> SHOW VARIABLES LIKE 'hostname';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| hostname | munda |
+---------------+-------+
1 row in set (0.00 sec)
It's not a built-in function so it can't be used in a SELECT statement.
Are you looking for CURRENT_USER function.
Returns the user name and host name
combination for the MySQL account that
the server used to authenticate the
current client. This account
determines your access privileges.
The value of CURRENT_USER() can differ
from the value of USER().
You can use user() and current_user() functions. If you want only hostname do something like select substr(current_user(),LOCATE('#', current_user())+1) AS localhost;
You can find details here
The ##hostname variable contains the system hostname:
$ cat /etc/hostname
bruno
$ hostname
bruno
$ mysql
mysql> SELECT ##hostname;
+------------+
| ##hostname |
+------------+
| bruno |
+------------+
Note that this can be combined and used in other queries:
mysql> SELECT name, ##hostname FROM people;
+-------+-------------+
| name | ##hostname |
+-------+-------------+
| Dotan | bruno |
+-------+-------------+
mysql> SELECT CONCAT('I am on server ', ##hostname);
+---------------------------------------+
| CONCAT('I am on server ', ##hostname) |
+---------------------------------------+
| I am on server bruno |
+---------------------------------------+