355

Is it possible for me to turn on audit logging on my mysql database?

I basically want to monitor all queries for an hour, and dump the log to a file.

public static
  • 12,702
  • 26
  • 66
  • 86

8 Answers8

273

Besides what I came across here, running the following was the simplest way to dump queries to a log file without restarting

SET global log_output = 'FILE';
SET global general_log_file='/Applications/MAMP/logs/mysql_general.log';
SET global general_log = 1;

can be turned off with

SET global general_log = 0;
peterh
  • 11,875
  • 18
  • 85
  • 108
Ram
  • 2,988
  • 1
  • 11
  • 4
  • 10
    Absolutely love this, works for existing and new connections on the DB – Carlton Feb 19 '15 at 13:57
  • 1
    There were some Statistics entries - not sure what those are but, otherwise, works really well. – Snowcrash Apr 21 '15 at 15:04
  • 1
    For this to work your user must have the SUPER privilege which is a global DB privilege and so cannot be limited to specific schemas or tables: `GRANT SUPER ON *.* TO user1@localhost` – RobM Jul 16 '18 at 20:55
  • I'd upvote that more than once if I could, I have a bookmark pointing here :) Thanks a lot! – resi Dec 09 '19 at 11:50
  • better than the accepted answer, starting mysql with mysqld is a bit clumsy in many situations. This is useful in the most common case where you want to do some quick debugging and then switch it off. – shelbypereira Jul 26 '20 at 15:10
  • Status update: this is still one of my favorite bookmarks :) – resi Apr 21 '21 at 10:12
  • Oh, look who's visiting again :) If we ever meet I'm so gonna pay you beer/coffee/lunch! – resi Oct 18 '21 at 10:27
  • this doesn't do anything, nothing gets written to the log – Andrew Koster Jun 01 '23 at 08:41
264

(Note: For mysql-5.6+ this won't work. There's a solution that applies to mysql-5.6+ if you scroll down or click here.)

If you don't want or cannot restart the MySQL server you can proceed like this on your running server:

  • Create your log tables on the mysql database
  CREATE TABLE `slow_log` (
   `start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP 
                          ON UPDATE CURRENT_TIMESTAMP,
   `user_host` mediumtext NOT NULL,
   `query_time` time NOT NULL,
   `lock_time` time NOT NULL,
   `rows_sent` int(11) NOT NULL,
   `rows_examined` int(11) NOT NULL,
   `db` varchar(512) NOT NULL,
   `last_insert_id` int(11) NOT NULL,
   `insert_id` int(11) NOT NULL,
   `server_id` int(10) unsigned NOT NULL,
   `sql_text` mediumtext NOT NULL,
   `thread_id` bigint(21) unsigned NOT NULL
  ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'
  CREATE TABLE `general_log` (
   `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
                          ON UPDATE CURRENT_TIMESTAMP,
   `user_host` mediumtext NOT NULL,
   `thread_id` bigint(21) unsigned NOT NULL,
   `server_id` int(10) unsigned NOT NULL,
   `command_type` varchar(64) NOT NULL,
   `argument` mediumtext NOT NULL
  ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'
  • Enable Query logging on the database
SET global general_log = 1;
SET global log_output = 'table';
  • View the log
select * from mysql.general_log
  • Disable Query logging on the database
SET global general_log = 0;
user10089632
  • 5,216
  • 1
  • 26
  • 34
Alexandre Marcondes
  • 5,859
  • 2
  • 25
  • 31
  • 17
    I'm not sure if this is true for every version of MySQL (I'm on 5.5), but I didn't have to create the tables. I followed the same advice minus creating the tables, which is mentioned here: http://stackoverflow.com/a/678310/135101 – Tyler Collier Mar 27 '14 at 23:18
  • Maybe it was already created for one or other reason, @TylerCollier – Alexandre Marcondes Mar 28 '14 at 10:10
  • 4
    It should be noted that the `CREATE TABLE` commands should (if the tables do not already exist) be executed on the `mysql` database, not on any user-created databases. Perhaps the SQL statements could be updated to reflect that. – Robert Rossmann Jan 23 '15 at 13:12
  • 2
    For viewing the log `SELECT * FROM mysql.general_log order by (event_time) desc` will do better. just saying.:-) – vinrav Dec 08 '15 at 06:23
  • 1
    Don't agree with *note* - with server version 5.6.37 works fully correctly. Thanks. – Dmitriy Olhovsky Nov 05 '17 at 20:11
  • To know if logging is enable : SHOW VARIABLES LIKE 'general_log'; – Groco Dec 17 '18 at 16:29
178

UPDATE: NO LONGER VALID FOR MYSQL 5.6+

Start mysql with the --log option:

mysqld --log=log_file_name

or place the following in your my.cnf file:

log = log_file_name

Either one will log all queries to log_file_name.

You can also log only slow queries using the --log-slow-queries option instead of --log. By default, queries that take 10 seconds or longer are considered slow, you can change this by setting long_query_time to the number of seconds a query must take to execute before being logged.

mvorisek
  • 3,290
  • 2
  • 18
  • 53
Robert Gamble
  • 106,424
  • 25
  • 145
  • 137
  • 73
    It should go without saying, but leaving this turned on in a production box winds up being non-entertaining very quickly. *g* – ceejayoz Nov 20 '08 at 02:40
  • 6
    If you have trouble enabling logging in this manner, doublt-check that the mysql user can write to the appropriate file location. – Jon Topper Nov 20 '08 at 16:56
  • On Ubuntu, `mysqld` changes to `/var/lib/mysql`, so unless you specify an absolute path, the file will end up there. – bradley.ayers Jun 28 '12 at 06:58
  • 3
    Is it possible to log queries over 1 particuarl db / table only? – Temujin Aug 04 '12 at 16:08
  • 2
    @Temujin phpmyadmin has now a 'tracking' option for tables where you specify a log('version') and it will keep record of the queries affecting it with information about time and the whole query. – gadget00 Aug 07 '13 at 14:57
  • So you have to start/stop to change this setting? – public static Oct 01 '14 at 20:27
  • 1
    general_log = on general_log_file=/path/to/query.log – Kiren S Jun 29 '15 at 11:26
  • 4
    This accepted answer should be deleted or edited to reflect the fact that it doesn't work with MySQL 5.6.+. – itoctopus Jul 31 '16 at 17:29
  • Is it somehow possible to log only queries that alternate the data, so no selects but updates, deletes etc? – Tobi Feb 07 '17 at 13:38
  • none of the answers actually work for -all- queries. the only thing that gets logged are CORRECT queries (wether they have a result set or effect or not). queries that trigger syntax errors are NOT logged. therefore these logs are suitable for optimizing already bug-free code's performance, but not for figuring out what's going on if the resulting queries are not correct SQL syntax wise. also the 2 tables 'created' already seem to ship with the default installation, at least on any machine i've tried it with. :P – HRH Sven Olaf of CyberBunker Feb 18 '19 at 09:33
167

Top answer doesn't work in mysql 5.6+. Use this instead:

[mysqld]
general_log = on
general_log_file=/usr/log/general.log

in your my.cnf / my.ini file

Ubuntu/Debian: /etc/mysql/my.cnf
Windows: c:\ProgramData\MySQL\MySQL Server 5.x
wamp: c:\wamp\bin\mysql\mysqlx.y.z\my.ini
xampp: c:\xampp\mysql\bin\my.ini.

alexeydemin
  • 2,672
  • 3
  • 27
  • 26
  • 1
    If you have used it, can you tell me the performance impact of the above, and would it be wise to enable logging this way? – Ramesh Pareek Jan 31 '16 at 06:10
  • 1
    Ramesh performance impact seems to be around 5-15% decrease in performance. More info here https://www.percona.com/blog/2009/02/10/impact-of-logging-on-mysql%E2%80%99s-performance/ – Firze Mar 08 '16 at 06:53
  • 1
    I don't understand why Mysql 5.6 doesn't allow log file to be set from queries ? How to log all queries in MySQL 5.6 and later when you don't have access to server directory tree but only `phpMyAdmin` ? – Vicky Dev Jun 17 '16 at 16:10
  • restart mysql service from xampp control panel after these changes. – Paramjeet Sep 01 '17 at 06:08
  • This worked for me in my local Xampp Apache environment, but I still had to turn the logging on via phpMyAdmin. Also, it couldn't locate the file in the /usr/log folder, nor would it create it, but it worked just fine as `general_log_file=filename.log` – JoeP May 21 '19 at 11:31
  • Don't forget to restart MySQL server 'sudo systemctl restart mysqld` – M at Oct 19 '22 at 09:37
56

Enable the log for table

mysql> SET GLOBAL general_log = 'ON';
mysql> SET GLOBAL log_output = 'table';

View log by select query

SELECT * FROM mysql.general_log

If there's too much queries, truncate the table:

TRUNCATE table mysql.general_log;
Snehal Parmar
  • 5,453
  • 3
  • 35
  • 46
Vipin Yadav
  • 707
  • 5
  • 6
  • is there a wildcard to log all tables? (there are quite a lot :C) – RicardoE Dec 06 '17 at 17:37
  • Thanks, this setting was very useful for me as I could not take down the mysql-server. I also want the log to appear in the log-table – Gunnar Sigfusson Aug 21 '18 at 11:50
  • 1
    This table has a column called 'thread_id' that helps to distinguish to bifurcate the queries issues in a particular session, as against the dump of all the queries issued to the entire database, which is what otherwise you get it for your SELECT query on the mysql.general_log table. – itsraghz May 09 '21 at 17:46
22

Quick way to enable MySQL General Query Log without restarting.

mysql> SET GLOBAL general_log_file = '/var/www/nanhe/log/all.log';
mysql> SET GLOBAL general_log = 'ON';

I have installed mysql through homebrew, mysql version : mysql Ver 14.14 Distrib 5.7.15, for osx10.11 (x86_64) using EditLine wrapper.

Nanhe Kumar
  • 15,498
  • 5
  • 79
  • 71
8

For the record, general_log and slow_log were introduced in 5.1.6:

http://dev.mysql.com/doc/refman/5.1/en/log-destinations.html

5.2.1. Selecting General Query and Slow Query Log Output Destinations

As of MySQL 5.1.6, MySQL Server provides flexible control over the destination of output to the general query log and the slow query log, if those logs are enabled. Possible destinations for log entries are log files or the general_log and slow_log tables in the mysql database

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Marcello Romani
  • 2,967
  • 31
  • 40
6

OS / mysql version:

$ uname -a
Darwin Raphaels-MacBook-Pro.local 15.6.0 Darwin Kernel Version 15.6.0: Thu Jun 21 20:07:40 PDT 2018; root:xnu-3248.73.11~1/RELEASE_X86_64 x86_64

$ mysql --version
/usr/local/mysql/bin/mysql  Ver 14.14 Distrib 5.6.23, for osx10.8 (x86_64) using  EditLine wrapper

Adding logging (example, I don't think /var/log/... is the best path on Mac OS but that worked:

sudo vi ./usr/local/mysql-5.6.23-osx10.8-x86_64/my.cnf

[mysqld]
general_log = on
general_log_file=/var/log/mysql/mysqld_general.log

Restarted Mysql

Result:

$ sudo tail -f /var/log/mysql/mysqld_general.log
181210  9:41:04    21 Connect   root@localhost on employees
           21 Query /* mysql-connector-java-5.1.47 ( Revision: fe1903b1ecb4a96a917f7ed3190d80c049b1de29 ) */SELECT  @@session.auto_increment_increment AS auto_increment_increment, @@character_set_client AS character_set_client, @@character_set_connection AS character_set_connection, @@character_set_results AS character_set_results, @@character_set_server AS character_set_server, @@collation_server AS collation_server, @@collation_connection AS collation_connection, @@init_connect AS init_connect, @@interactive_timeout AS interactive_timeout, @@license AS license, @@lower_case_table_names AS lower_case_table_names, @@max_allowed_packet AS max_allowed_packet, @@net_buffer_length AS net_buffer_length, @@net_write_timeout AS net_write_timeout, @@query_cache_size AS query_cache_size, @@query_cache_type AS query_cache_type, @@sql_mode AS sql_mode, @@system_time_zone AS system_time_zone, @@time_zone AS time_zone, @@tx_isolation AS transaction_isolation, @@wait_timeout AS wait_timeout
           21 Query SET NAMES latin1
           21 Query SET character_set_results = NULL
           21 Query SET autocommit=1
           21 Query SELECT USER()
           21 Query SELECT USER()
181210  9:41:10    21 Query show tables
181210  9:41:25    21 Query select count(*) from current_dept_emp
Raphvanns
  • 1,766
  • 19
  • 21