MySQL_DBA整理

前言

几乎所有的资料整理都在Linux系统、mySQL5.0.27版本和MyISAM存储引擎环境下试验和总结的,以及参考前人经验与MySQL官网资料进行总结的。关于MySQL的安装与升级,我相信很多MySQL_DBA都比我厉害,MySQL官网与其他网站上应该有很多相关资料:

关于安装写一条简单的命令与一些必要的说明:

1.源码安装的脚本

./configure --prefix=/usr/local/mysql --with-mysqld-user=mysql --with-charset=gb2312--with-extra-charsets=all

由于我的数据库只使用gb2312,所以为了一致性就这样设置,你也可以设置为自己的类型。

2.必要说明:

为了方便程序的升级以及性能更高,应该把MySQL程序与数据文件放在不同的目录下面,最好还是不同的磁盘上。若起用了日志功能,最好是把MySQL程序、数据文件和日志文件分别放在三个不同的磁盘上,从而避免程序升级带来的潜在而致命的问题,提高数据的读写能力(注:毕竟磁盘的转速有限)。

第一部分:数据库的备份与还原

对于MyISAM存储引擎的表,由于只有表级的锁,所以目前还没有出现象InnoDB存储引擎的那种可以不缩定表的备份方法。目前用得最多最普遍的两种方法:文件的拷贝与dump数据库。

文件的拷贝:就是在备份期间锁定数据库表,不允许其他用户进行任何更新操作,然后直接把*.MYD

、*MYI、db.opt文件拷贝到备份的目录下。一般使用免费的工具:mysqlhotcopy,至于如何使用会在备份脚本中给出参考,但是该方法没有办法备份存储过程、函数等,但是另系统库(mysql)一起备份的话,是可以实现备份存储过程、函数等的效果。

Dump方法:也是非常类似,就是把指定数据库的所有数据表结构与数据生成Create与Insert语句。

总结:这两种方法各有优劣,需要看根据实际情况使用那种备份方法。

1>、文件拷贝:此方法备份的速度快,锁定表的时间相对短,且恢复起来也非常快。但是恢复的时候,一般需要在同一种类型的系统、MySQL版本上进行恢复备份的数据库文件。缺乏跨平台的、跨版本等缺点。

2>、Dump:此方法备份的速度慢,锁定表的时间长,且恢复起来也慢。可是此种备份的文件,具有跨平台、跨版本、跨存储引擎(备份时设置好就可以)等优势。

介于上面的描述,我们应该是两种方法结合。比如:平时进行完整备份时,可以采用文件拷贝的方式;对于备份的文件需要放到不同类型系统平台的或不同MySQL版本上再进行还原话,建议采用Dump方式。建议以上两种备份方式可以只作为完整备份的方式,若需要精确到秒的话,可以考虑:

文件拷贝+日志备份或Dump+日志备份,最好是采用文件拷贝+日志备份。至于备份的频率,需要根据自己的系统特点与数据重要指定。在此介绍一种比较普遍的策略:

每天的05:00:00左右进行完整备份,然后每小时进行一次日志文件备份。(注意:日志文件太大的话,使用MySQL客户端工具进行重做的话,会比较慢)。

下面给出完使用mysqlhotcopy工具备份与自动还原的代码:

完整备份:

#!/bin/bash

#First,create direct /back

# setting servername

server=test

#the directory of backup

backdir=/back/mysql

#use log file record log

logfile=$backdir/mysqlbak.log

today=`date +%y-%m-%d`

todaydir=$server-$today

backup=$backdir/$todaydir

#the password of mysql

rootpass=123456a

dbname=eugene

#remake the directory of backup

if [ ! -d $backdir ] ; then

mkdir $backdir

else

chattr -i $backdir

fi

cd $backdir

if [ ! -f $logfile ] ; then

touch $logfile

else

chattr -i $logfile

fi

echo "" >> $logfile

echo "fully backup starting!" >> $logfile

echo $(date +"%y%m%d %h:%m%s") >> $logfile

echo "" >> $logfile

mkdir $backup

#backup with database

/usr/local/mysql/bin/mysqlhotcopy $dbname --flushlog -u admin -p $rootpass $backup | logger -t mysqlhotcopy

echo "fully backup database success!" >> $logfile

#compress backup file and deleted unregimented file

cd $backdir

tar -zcf $todaydir.tgz $todaydir/$dbname/

rm -rf $todaydir

#cd $backdir

#Keep Down Thirty Days

for f in `find . -type f -mtime +30 -maxdepth 1`

do

filename=`basename $f`

#can't deleted log file

if [ $f != 'mysqlbak.log' ] ; then

rm -fr $f

fi

done

#add property

chattr +i $backdir

日志备份:

#!/bin/bash

#everyday and hourly backup log files once

#setting server's name

server=test

#log files's directory

logfile=/usr/local/mysql/var

#the directory of backup

backdir=/back/increment

hourly=`date +"%y-%m-%d-%H-%M-%S"`

today=`date +%y-%m-%d`

todaydir=$backdir/$server-$today

hourlydir=$server-$hourly

backupdir=$todaydir/$hourlydir

rootpass=123456a

#create directory ,but back is exist

#increment is exist or bot exist,General,first It need creatting

if [ ! -d $backdir ] ; then

mkdir $backdir

else

chattr -i $backdir

fi

#judge today directory is exist or not exist

if [ ! -d $todaydir ] ; then

mkdir $todaydir

else

chattr -i $todaydir

fi

#create directory is using storage log files

mkdir $backupdir

#execute flush logs

/usr/local/mysql/bin/mysqladmin -u admin -p$rootpass flush-logs

#stat mysql-bin log file total, throw off lastly and mysql-bin.index

total1=`ls $logfile/mysql-bin.*|wc -l`

total=$(expr $total1 - 2)

for f in `ls $logfile/mysql-bin.*|head -n $total`

do

mv $f $backupdir

done

#compress log files

cd $todaydir

#Because file'name include mark of : ,it will make a mistake,So we dispart two-step complete

tar -zcf $hourlydir.tgz $hourlydir/

rm -rf $hourlydir

#deleted overdue files and directs

cd $backdir

#Keep Down Thirty Days;deleted *.tgz file

for d in `find . -type d -mtime +30 -maxdepth 1`

do

#filename=`basename $f`

rm -fr $d

done

# alter file and directoryproperty

chattr +i $backdir

自动还原:

#!/bin/bash

#this is restore database script

#author:eugene

#date:2007-07-26

#***************Define Begin***************************#

#fully backup database file directory

fulldir=/back/mysql

#increment backup log file directory

incrementdir=/back/increment

#it is mysqlbinlog's directory

bindir=/usr/local/mysql/bin

vardir=/usr/local/mysql/var

para=07-08-15

time=04

#setting fully backup database at 05:30

backuptime=05

#databse'sname

dbname=eugene

#root's password

passwrd=123456a

#log file's name

logfile=mysql-bin

#*************** Define End ***************************#

#*************** Function Start************************#

#parameter: yy-mm-dd

#return: max(day)

mon_max_day()

{

day=0

#Because parameter of date's format yy-mm-dd,so we must convert to yyyy-mm-dd

year=$( expr $2 + 2000 )

if [ $1 -gt 0 -a $1 -lt 13 ]; then

case $1 in

1|01|3|03|5|05|7|07|8|08|10|12) day=31;;

4|04|6|06|9|09|11) day=30;;

2|02)

if [ `expr $year % 4` -eq 0 ] ; then

if [ `expr $year % 400` -eq 0 ] ; then

day=29

elif [ `expr $year % 100` -eq 0 ] ; then

day=28

else

day=29

fi

else

day=28

fi

esac

fi

echo $day

}

#usage: get discretionary date's yesterday date,parameter:yy-mm-dd

#return: yy-mm-dd

yesterday()

{

num=$1

year=$(echo $num|awk -F- '{print $1}')

month=$(echo $num|awk -F- '{print $2}')

day=$(echo $num|awk -F- '{print $3}')

day=$(expr $day - 1)

if [ $day -eq 0 ] ; then

month=$(expr $month - 1)

if [ $month -eq 0 ] ; then

year=$(expr $year - 1)

month=12

fi

day=$(mon_max_day $month $year)

value=$year-$month-$day

else

value=$year-$month-$day

fi

echo $value

}

#parameter: $1---yy-mm-dd; $2---0 or 1 or 2 or 3; $3---fulldir;$4---vardir

#0---copy current day's file,

#1---copy yesterday day's file

#2---copy last month day's file

#3---copy last year day's file

fullycp()

{

strdate=$1

num=$2

fullydir=$3

vardir=$4

year=$(echo $strdate | awk -F- '{print $1}') #create directory's year

month=$(echo $strdate | awk -F- '{print $2}') #create directory'smonth

day=$(echo $strdate | awk -F- '{print $3}') #create directory's day

case $num in

0) ;;

1|2|3) strdate=$(yesterday $strdate)

year=$(echo $strdate | awk -F- '{print $1}') #create directory's year

month=$(echo $strdate | awk -F- '{print $2}') #create directory'smonth

day=$(echo $strdate | awk -F- '{print $3}') #create directory's day

;;

esac

for f in `ls $fullydir`

do

#if [ -d $fullydir/$f ] ; then

filename=`basename $f`

if [ $filename!='mysqlbak.log' ] ; then#test catalog include mysqlbak.log,so filt the file

num1=$(echo $f | awk -F- '{print $2}') #create directory's year

num2=$(echo $f | awk -F- '{print $3}') #create directory'smonth

num4=$(echo $f | awk -F- '{print $4}') #create directory's day.tgz

num3=$(echo $num4 | awk -F. '{print $1}') #create directory's day

if [ $year -eq $num1 -a $month -eq $num2 -a $day -eq $num3 ] ; then

echo "success!"

tar zxvf $f

cp -rf $fullydir/$f/$dbname $vardir

fi

fi

done

}

#*************** Function End************************#

#alter back/increment directory attribute

chattr -i $incrementdir

year=$(echo $para | awk -F- '{print $1}')

month=$(echo $para | awk -F- '{print $2}')

day=$(echo $para | awk -F- '{print $3}')

#shutdown mysql service

#Judge mysqld is running or stopping

#for d in `ps -e|grep mysql|awk '{ print $4 }'`

#do

#if [ $d == 'mysqld' ] ; then

##/etc/init.d/mysql stop

#fi

#done

if [ $backuptime-lt $time ] ; then#05 < time

#deal with fully backup files withtransfer function fullycp($strdate $flag $fulldir $vardir)

fullycp $para 0 $fulldir $vardir

#deal with log files

for f1 in `ls $incrementdir`

do

num1=$(echo $f1 | awk -F- '{print $2}') #create directory's year

num2=$(echo $f1 | awk -F- '{print $3}') #create directory'smonth

num3=$(echo $f1 | awk -F- '{print $4}') #create directory's day

if [ -d $incrementdir/$f1 ] ; then#judge target is file or director

if [ $year -eq $num1 -a $month -eq $num2 -a $day -eq $num3 ] ; then

for f2 in `ls $incrementdir/$f1`

do

bf2=$(echo $f2 | awk -F: '{print $1}')

bf3=$(echo $bf2 | awk -F- '{print $5}')

if [ $bf3 -le $time ] ; then#bf3 <= time

for f4 in `ls $incrementdir/$f1/$f2/$logfile.*|head`

do

$bindir/mysqlbinlog --database=$dbname $f4 >> $incrementdir/test.sql

done

fi

done

fi

fi

done

else

#Because fully backup event is happened in 05:30,so use yesterday's fully backup ,

#and deal with yesterday's log file and intraday's log files

#don't consider restore every month's first day ,must be considered

#deal with yesterday's fully backup files withtransfer function fullycp($strdate $flag $fulldir $vardir)

fullycp $para 1 $fulldir $vardir

curryear=$(echo $para | awk -F- '{print $1}')

currmonth=$(echo $para | awk -F- '{print $2}')

currday=$(echo $para | awk -F- '{print $3}')

#get the current's date of yesterday's date

lastdate=$(yesterday $para)

lastyear=$(echo $lastdate | awk -F- '{print $1}')

lastmonth=$(echo $lastdate | awk -F- '{print $2}')

lastday=$(echo $lastdate | awk -F- '{print $3}')

#need deal with currently and yesterday log files

#first,deal with year-mm-(day - 1)'s log files

for f1 in `ls $incrementdir`

do

if [ -d $incrementdir/$f1 ] ; then#judge target is file or director

num1=$(echo $f1 | awk -F- '{print $2}') #create directory's year

num2=$(echo $f1 | awk -F- '{print $3}') #create directory'smonth

num3=$(echo $f1 | awk -F- '{print $4}') #create directory's day

if [ $lastyear -eq $num1 -a $lastmonth -eq $num2 -a $lastday -eq $num3 ] ; then

for f2 in `ls $incrementdir/$f1`

do

bf2=$(echo $f2 | awk -F: '{print $1}')

bf3=$(echo $bf2 | awk -F- '{print $5}')

if [ $bf3 -ge $backuptime ] ; then#bf3 >= backuptime or backuptime - 1

for f4 in `ls $incrementdir/$f1/$f2/$logfile.*|head`

do

$bindir/mysqlbinlog --database=$dbname $f4 >> $incrementdir/test.sql

done

fi

done

elif [ $curryear -eq $num1 -a $currmonth -eq $num2 -a $currday -eq $num3 ] ; then

for f2 in `ls $incrementdir/$f1`

do

bf2=$(echo $f2 | awk -F: '{print $1}')

bf3=$(echo $bf2 | awk -F- '{print $5}')

if [ $bf3 -le $time ] ; then#bf3 <=time

for f4 in `ls $incrementdir/$f1/$f2/$logfile.*|head`

do

$bindir/mysqlbinlog --database=$dbname $f4 >> $incrementdir/test.sql

done

fi

done

fi

fi

done

fi

if [ -f $incrementdir/test.sql ] ; then

sed '/^ROLLBACK/ d' $incrementdir/test.sql > $incrementdir/template.sql

else

echo "don't exist backup database files!"

exit

fi

#start mysql service

#must copy mysql.mysql to /etc/init.d/mysql

#/etc/init.d/mysql start

/usr/local/mysql/bin/mysql -uadmin -p$passwrd $dbname < $incrementdir/template.sql

rm $incrementdir/test.sql

rm $incrementdir/template.sql

#add /back/increment directory attribute

chattr +i $incrementdir

对此申明下:本人的Shell脚本属于现学现卖的那种,我知道这些脚本肯定可以写得更简单,其实我写的自动还原的脚本是一种特殊情况下用的。。。比如有N多天前的完整备份存在问题,而只有N+1条的完整备份是完好的,所以需要使用N+1前天的完整备份再加上N+1条到目前的日志完整,若N>=2条的话,日志就有很多了,手工还原就麻烦,这个脚本就有用了。

对于游戏、金融等行业需要只针对某个帐号的信息进行回档处理,在MySQL5.0及以上的版本就非常容易了,只要根据需要回档的时间,就可以使用此时间段的日志文件进行回档,二进制日志翻译的语句如下:

usr/local/mysql/bin/mysqlbinlog –start_datetime=”2007-10-29 05:21:00” –stop_datetime=” 2007-10-29 05:25:00 ”eugene.01831 > mysql –uroot –p Eugene

解释下:只要需要翻译某段时间之间的二进制的日志,可以指定start_datetime与stop_datetime,不指定则是把eugene.01831日志文件全部翻译成SQL语句并且通过mysql客户端工具执行,eugene为指定在那个数据库上执行生成的SQL语句。

以游戏行业恢复某个玩家角色的物品为例解释下,可能会比较好理解。假设A玩家在2007-10-29 03:24:00至2007-10-29 03:29:00之间出现装备丢失。

若update语句的where条件是根据角色的编号ID,我们可以先根据角色名称找到对应的ID(社为1001),然后再执行:

usr/local/mysql/bin/mysqlbinlog –start_datetime=” 2007-10-29 03:24:00” –stop_datetime=” 2007-10-29 03:29:00 ”eugene.01832 > Eugene.sql,再把eugene.sql放到eugene.doc文档中查找下ID=1001的update角色表的语句,复制出来并稍微修改下再利用客端执行下修改后的update语句就可以实现只更改装备的数据了。

php转型mysql dba_MySQL_DBA整理(转)相关推荐

  1. MySQL 语句整理 2019-5-3

    MySQL 语句整理 在整理完Oracle的一些常见用语句后,由于MySQL的语法跟Oracle略有不同,随跟PN的MySQL视频进行了间接整理. 查询薪水大于1800, 并且部门编号为20或30的员 ...

  2. MYSQL学习整理(4):函数

    MYSQL零基础小白,梳理学习内容督促自己,也为方便自己日后回忆,也希望可以帮助到网友. 这里推荐宋红康老师的MySQL课程,学习资源(如有侵权请联系删除): MySQL数据库教程天花板,mysql安 ...

  3. mysql碎片整理 提速_MySQL 优化:碎片整理

    MySQL碎片就是MySQL数据文件中一些不连续的空白空间,这些空间无法再被全部利用,久而久之越来多,越来越零碎,从而造成物理存储和逻辑存储的位置顺序不一致,这就是碎片. 碎片是如何产生的 delet ...

  4. MySQL优化--整理

    MySQL如何优化 表的设计合理化(符合3NF) 添加适当索引(index) [四种: 普通索引.主键索引.唯一索引unique.全文索引] SQL语句优化 分表技术(水平分割.垂直分割) 读写[写: ...

  5. MySQL练习整理(每日习题)

    2022年3月26日笔记 # 1.查询员工12个月的工资总和,并起别名为ANNUAL SALARY #第一种理解方式,只计算了基本工资 SELECT employee_id,last_name,sal ...

  6. MySQL语句整理以及通配符_和%

    数据库 英文名 DataBase 简写 DB 数据库的特点: 持久化存储数据,其实就是一个文件系统 方便存储和管理 使用统一的方式操作数据 今天给大家整理了一些常用的MySQL数据库的语句 对于数据库 ...

  7. 经常使用的MySQL语句整理

    本文參考:http://www.blogjava.net/bolo 部分自己补充,长期更新 MySQL的SQL语句写法,除了那些主要的之外,另一些也算比較经常使用的,这里记录下来,以便以后查找. 好记 ...

  8. mysql 知识整理(待续)

    文章目录 1:MySQL 索引的数据结构有那些 2:MySQL的存储引擎有哪些 3:InnoDB 是否支持hash 4:扰动函数 5:hash表的索引结构 6:二叉树,红黑树的索引结构 10:最左匹配 ...

  9. mysql中整理设置__MySQL整理

    登录 命令:mysql -h [IP 地址/域名] -P [端口] -u [用户名] -p[密码] 端口默认是3306 mysql -hlocalhost -uroot -p 断开 exit; \q; ...

最新文章

  1. 教你怎样快速DIY自己的博客园SKIN
  2. mac OS下显示.htaccess等隐藏文件
  3. java面向对象认定的特征_Java面向对象的三大特征(一)
  4. mybatis返回map键值对_mybatis返回map key怎么指定
  5. 通过避免下列 10 个常见 ASP.NET 缺陷使网站平稳运行
  6. 修改hadoop配饰文件文件后导致hive无法找到原有的dfs文件
  7. highchart 曲线图
  8. unity3D游戏开发一之初识unity
  9. 【强化学习论文精读】Timeliness Guaranteed Traffic Flow Forecasting Based on Federated Online Learning
  10. 谷歌 Android 12 Go 正式发布!
  11. 时光不负有心人 --又是折腾的一年
  12. 第二十一章 : 文本处理
  13. [转载]JS和AS交互 作者:ludanlove
  14. 浮动的简介——CSS
  15. 基于JavaWeb的工厂仓库管理系统
  16. 苹果手机悬浮窗怎么打开_悬浮窗搜题神器_悬浮窗搜题神器app源码苹果软件预约 v1.0...
  17. 高频电路相关知识(四)
  18. java.lang.UnsatisfiedLinkError:D:\arcsoft-lib\libarcsoft_face.dll: Can‘t find dependent libraries
  19. Kubernetes详细教程
  20. 给定一个链表,一次颠倒链表k的节点并返回其修改列表。如果节点的数量不是k的倍数,那末最后的剩余节点应该保持原样。

热门文章

  1. 图片复印如何去除黑底_如何用AE制作可爱漂亮闪烁霓虹灯效果?只需简单几步任何人都可以...
  2. 如何使用模板生成多个页面_Divi不再只是页面构建器。 使用主题生成器,可以完全设计整个网站。...
  3. C++ 函数重载的实现原理
  4. systemd.generator — systemd unit generators
  5. FD.io VSAP(VPP Stack Acceleration Project),通过FD.io VSAP构建用户态协议栈
  6. C语言动态库libxxx.so的几种使用方法
  7. pydobc连接sql server_pyodbc 连接sql server
  8. python爬虫基本原理_Python爬虫【一】爬虫的基本原理
  9. OpenCv之图像二值化(笔记12)
  10. 在线预览文档简单例子