简体   繁体   中英

Running a SQL query in the background using MySQL

Is there a way to have a SQL query run on the servers even after I turn off my computer?

I heard from a coworker that there was and she wanted me to do that. I believe she said it was called a "screen"?

I'm going to assume you are ssh-ing to a server and you want to be able to shutdown you local workstation.

You can use nohup and background processes. Also useful to know the -e option for the mysql command.

So something like this:

nohup mysql <options> -u <user> -p <pass> -e 'Insert Query Here' &
  • nohup is for 'no hang up' ie don't end the process when I disconnect.

  • mysql ... The mysql command you usually run to connect, just add the -e option to run the query without opening a mysql session

  • & starts the process in the background

I'm unsure about this BUT: If you don't want to put your password in the command, run the command without the password, type fg the password prompt should come back, enter your password, ctrl-z will send the process back to the background, then you can disconnect.

If you find you are experiencing issues using nohup with mysql – I found an alternative solution inspired by @dan08's answer on this page, as well as @Node's answer about putting an already running process into the background from another question on SO.


I had found that when trying the suggestion of using nohup mysql... to 'background' a long-running mysql command, that the remote MySQL server I was attempting to connect to refused the connection. When running the same mysql command without prefixing it with nohup , the connection succeeded and the mysql command worked as expected.

As such I looked for alternative methods of achieving the same end-result of being able to run a long-running SQL command (or set of SQL commands) without concerns about the process terminating if I disconnected from the shell session or if a networking issue caused a disconnection from the remote server. This research led to the working solution proposed below:

  1. Run your mysql command as though you would like to run it in the foreground; for example: mysql <options> -h <host> -u <user> -p -e "source /absolute/path/to/commands.sql" <database name> 2>&1 > ./mysql_output.log
  2. When asked, input the relevant password at the MySQL command prompt for the specified <user> (this is triggered by the inclusion of the -p flag in the mysql command above).
  3. Immediately press Ctrl + Z to suspend the current process, in this case mysql .
  4. Run the bg command to move the currently suspended process into the background, and resume its processing.
  5. Run the jobs command to list the jobs currently running in the shell session (you may only have one job listed if you don't have any other background processes running in the current session). From this list note the job number for mysql , which will likely be 1 if you only have one job running.
  6. Last, but not least, run the disown -h %<job number> command, thus disown -h %1 (assuming the job number obtained in step #5 above was 1 ). This last command is very important, as it disassociates the current shell session from our mysql process which we have just moved into the background, so that the mysql process does not get killed when the terminal shell session ends. Without the call to disown , your mysql process that is now running in the background could still get killed if your terminal session ends.

The above sequence of commands effectively mimics a call to nohup mysql... by allowing you to move a long-running call to mysql into the background and not have the process terminated if you close your terminal session or get disconnected from the remote server. If you find that running nohup mysql... works in your circumstances that is great as it is certainly the easier and quicker approach, but at least in our application/server environment, we were unable to use nohup mysql... successfully.

The above sequence should also give you more control over executing the mysql command as you are initially running the command in the foreground; for instance running mysql in the foreground will allow you to enter your MySQL connection password securely at the MySQL prompt without having to provide the password as plain-text on the command line (which may be an important security consideration in some hosting/server environments, especially shared hosting where passwords entered on the command line would likely end up in log files such as ~/.bash_history or similar). Additionally, running the command in the foreground, will allow you to see and respond to any connection or other errors before the MySQL command gets moved into the background.

Credit must also go @dan08's answer on this page, and to @Node for his answer regarding placing an already running foreground process into the background, for helping inspire the solution proposed here.

Hopefully this proposed solution will help others who find themselves in a similar situation, where running nohup mysql... does not work as expected.

I prefer this way:

mysql -u <user> -p<pass> -e 'Insert Query Here' &>> query.log & disown

Example:

mysql -u root -pmypassword -e 'UPDATE bigtable SET column = "value";' &>> query.log & disown
  • no space after -p
  • &>> query.log redirects both stdout and stderr into query.log (use your path), otherwise entire output will be translated into terminal
  • & runs the command in background
  • disown detaches the command from current terminal, if you close the terminal then command won't die after timeout

You can control the command using

SHOW FULL PROCESSLIST;

Also you can stop it using

KILL [id]; -- get the ID from previous command
nohup mysql -h [host_ip_addr] -u [username] -p[password] [database_name] -e "sql_query" &

注意: -p 后不要留空格

Here is a good way...

  1. Create such environment that will NOT prompt password when try to login mysql client. Make sure that you can logged in your database just typing "mysql" without user and password from your terminal.

  2. Then use this command -

    nohup sh -c "mysql -e 'ALTER TABLE YourDatabaseName.TableName ADD anyColumnYouWantToAdd VARCHAR(50) NULL AFTER anyOldColumn'" > /dev/null 2>&1 &

NOTE: You must provide database name otherwise you have to put "use database" command also. Another issue may arise if you use column, table or database name with quote.

If you want to see log just use log file instead of "/dev/null"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM