mysql backup shell script

mysql backup shell script
#!/bin/sh
# mysql_backup.sh: backup mysql databases and keep newest 5 days backup.
#
# Last updated: 2006.9.6
# ———————————————————————-
# This is a free shell script under GNU GPL version
# Feedback/comment/suggestions : http://www.strongd.net
# ———————————————————————-


# your mysql login information
# db_user is mysql username
# db_passwd is mysql password
# db_host is mysql host
# —————————–
db_user=”root”
db_passwd=”passwd”
db_host=”localhost”


# the directory for story your backup file.
backup_dir=”/backup”


# date format for backup file (dd-mm-yyyy)
time=”$(date +”%d-%m-%Y”)”


# mysql, mysqldump and some other bin’s path
MYSQL=”$(which mysql)”
MYSQLDUMP=”$(which mysqldump)”
MKDIR=”$(which mkdir)”
RM=”$(which rm)”
MV=”$(which mv)”
GZIP=”$(which gzip)”


# check the directory for store backup is writeable
test ! -w $backup_dir && echo “Error: $backup_dir is un-writeable.” && exit 0


# the directory for story the newest backup
test ! -d “$backup_dir/backup.0/” && $MKDIR “$backup_dir/backup.0/”


# get all databases
all_db=”$($MYSQL -u $db_user -h $db_host -p$db_passwd -Bse ‘show databases’)”


for db in $all_db
do
    $MYSQLDUMP -u $db_user -h $db_host -p$db_passwd $db | $GZIP -9 > “$backup_dir/backup.0/$time.$db.gz”
done


# delete the oldest backup
test -d “$backup_dir/backup.5/” && $RM -rf “$backup_dir/backup.5”


# rotate backup directory
for int in 4 3 2 1 0
do
    if(test -d “$backup_dir”/backup.”$int”)
    then
        next_int=`expr $int + 1`
        $MV “$backup_dir”/backup.”$int” “$backup_dir”/backup.”$next_int”
    fi
done


exit 0;


Removing HTML tags using mysql

Try this (ported from a T-SQL func by Robert Davis):


SET GLOBAL log_bin_trust_function_creators=1;
DROP FUNCTION IF EXISTS fnStripTags;
DELIMITER |
CREATE FUNCTION fnStripTags( Dirty varchar(4000) )
RETURNS varchar(4000)
DETERMINISTIC
BEGIN
  DECLARE iStart, iEnd, iLength int;
    WHILE Locate( ‘<‘, Dirty ) > 0 And Locate( ‘>’, Dirty, Locate( ‘<‘, Dirty )) > 0 DO
      BEGIN
        SET iStart = Locate( ‘<‘, Dirty ), iEnd = Locate( ‘>’, Dirty, Locate(‘<‘, Dirty ));
        SET iLength = ( iEnd – iStart) + 1;
        IF iLength > 0 THEN
          BEGIN
            SET Dirty = Insert( Dirty, iStart, iLength, ”);
          END;
        END IF;
      END;
    END WHILE;
    RETURN Dirty;
END;
|
DELIMITER ;
SELECT fnStripTags(‘this <html>is <b>a test</b>, nothing more</html>’);


Exploring Mysql CURDATE and NOW. The same but different.


Sometimes I see people attempting to use VARCHARS or CHARS to store dates in their MySQL database application. This is really fighting against MySQL, which has a variety of interchangeable date types. Internally MySQL is storing dates as numbers, which allows it to do all sorts of nice arithmetic and comparisons with very little effort on your part. For example, when you use a mysql DATE column to store a date, you don’t have to worry about sortation, or comparing that date to another DATE, because MySQL already understands how to do those things internally. A lot of people also don’t realize that they can output a DATE column in just about any way they choose using the DATE_FORMAT function. This causes people to shy away from using DATE, DATETIME, TIME, or TIMESTAMP columns, when they really should.


We can break down mysql DATE columns into 3 categories:

DATE: Has no Time component.

DATETIME and TIMESTAMP: Has both Date and Time component.

TIME: Has only Time component.


I tend to use DATETIME most often, and occassionally will use TIMESTAMP. I’ll talk about TIMESTAMP another day, and explain the pros and cons of using it.

In this entry I’m going to concentrate on two very important MySQL date functions: CURDATE() and NOW(). Take a look at these examples, and keep in mind that the semicolons are added to terminate the SQL statements as you would have to if you were using the mysql client application. If you’re using phpMyAdmin you don’t need the semicolons.


SELECT CURDATE();



CODE:

+————+
| CURDATE()  |
+————+
| 2004-11-30 |
+————+
1 row in set (0.00 sec)


CURDATE() returns you the date part of the mysql server’s datetime. The server gets this from the operating system, so basically it’s whatever the Date/Time is on the machine that is running your mysql server.

Notice that CURDATE() as its name implies has no TIME component. Let’s assume that what your application needs to do is find out what date it was “yesterday”. If Time really isn’t important, then CURDATE is the way to go, as it’s not concerned with TIME.

Although it’s not that intuitive, the way to get “YESTERDAY” is to use the DATE_ADD() function. The INTERVAL component allows us to Add a -1 DAY


SELECT DATE_ADD(CURDATE(), INTERVAL1 DAY);



CODE:

+————————————–+
| DATE_ADD(CURDATE(), INTERVAL -1 DAY) |
+————————————–+
| 2004-11-29                           |
+————————————–+
1 row in set (0.00 sec)


This is not to say that you can’t then use the DATE to compare against a DATETIME. You can! What happens is that mysql assumes for comparison purposes that your DATE is the equivalent to the “first second of that day” or that day at 12:00 am.

This little experiment illustrates the idea.


CODE:

mysql> create table onedate (onedate DATETIME);
Query OK, 0 rows affected (0.00 sec)

mysql> insert into onedate VALUES(NOW());
Query OK, 1 row affected (0.00 sec)

mysql> select * from onedate where onedate >= CURDATE();
+———————+
| onedate             |
+———————+
| 2004-11-30 17:52:01 |
+———————+
1 row in set (0.00 sec)


Notice that a row was returned, because CURDATE() will always be less than or equal to NOW().

Compare CURDATE() with NOW(). Like CURDATE(), NOW() returns you the system DATE but also includes the time component. If you need TIME in your application, tracking logins, or the date and time a message was entered by a user, then you need a mysql DATETIME rather than a MYSQL date, or you will not be able to capture the important time component.


SELECT * FROM onedate WHERE onedate >= CURDATE();



CODE:

+———————+
| NOW()               |
+———————+
| 2004-11-30 18:00:34 |
+———————+
1 row in set (0.00 sec)


Notice the 24 Hour time component.

Putting a nail in the issue, here’s the same DATE_ADD function called against NOW().


SELECT NOW(), DATE_ADD(NOW(), INTERVAL1 DAY);



CODE:

+———————+———————————-+
| NOW()               | DATE_ADD(NOW(), INTERVAL -1 DAY) |
+———————+———————————-+
| 2004-11-30 18:07:17 | 2004-11-29 18:07:17              |
+———————+———————————-+
1 row in set (0.00 sec)


What we get is exactly the same time, yesterday.

The intrinsic DATE types in a relational database are always the way to go when you need to handle date and time in your application. Let the database do the heavy lifting, and you will make your application faster, more reliable and easier to maintain in the long run.