mysqldump -u username -p database_name > backup_db.sql
转储可能包含错误。
命令
mysqldump
中是否有特定选项来确保在实时系统上安全地完成此操作?我可以为用户禁用读/写几秒钟(数据库<50MB)#1 楼
所有数据都是InnoDB这将为您提供数据的准确时间点快照:
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql
--single-transaction
产生一个检查点,该转储允许转储在捕获数据之前捕获所有数据。检查点,同时接收传入的更改。这些传入的更改不会成为转储的一部分。这样可以确保所有表的时间点相同。--routines
转储所有存储过程和存储函数--triggers
转储具有它们的每个表的所有触发器所有数据都是MyISAM或Mix of InnoDB / MyISAM
您将必须强加全局读取锁,执行mysqldump并释放全局锁。
mysql -uuser -ppass -Ae"FLUSH TABLES WITH READ LOCK; SELECT SLEEP(86400)" &
sleep 5
mysql -uuser -ppass -ANe"SHOW PROCESSLIST" | grep "SELECT SLEEP(86400)" > /tmp/proclist.txt
SLEEP_ID=`cat /tmp/proclist.txt | awk '{print }'`
echo "KILL ${SLEEP_ID};" > /tmp/kill_sleep.sql
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql
mysql -uuser -ppass -A < /tmp/kill_sleep.sql
请尝试一下!
更新2012-06 -22 08:12 EDT
由于您的总数据少于50MB,因此我有另一种选择。与其在后台启动SLEEP命令以保持全局读取锁定86400秒(即24小时)只是为了获取进程ID并在外部杀死,我们不如尝试在mysql中而不是在OS中设置5秒超时:
SLEEP_TIMEOUT=5
SQLSTMT="FLUSH TABLES WITH READ LOCK; SELECT SLEEP(${SLEEP_TIMEOUT})"
mysql -uuser -ppass -Ae"${SQLSTMT}" &
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql
对于小型数据库,这是一种更干净,更简单的方法。
评论
5秒只是预防措施。您可以尝试使用较低的值。
– RolandoMySQLDBA
2012年6月20日下午3:33
Rolando-第1行中的错误2013(HY000)是在查询期间与MySQL服务器的连接丢失是否是预期的错误消息?
–user784637
2012年6月22日上午11:32
是否所有MySQL数据都在mysqldump中输出?
– RolandoMySQLDBA
2012年6月22日上午11:56
我不确定错误消息。这只是一个猜测,但这可能来自单行脚本,该脚本杀死了我在第二个脚本中提到的用户定义的SLEEP函数调用。
– RolandoMySQLDBA
2012年6月22日上午11:59
试试我的新建议,看看是否顺利。希望不会有错误消息。
– RolandoMySQLDBA
2012年6月22日12:16
#2 楼
对于InnoDB表,您应该使用
--single-transaction
选项,如另一个答案中所述。 对于MyISAM,有
--lock-tables
。在此处查看官方文档
#3 楼
如果要对MyISAM或混合表执行此操作,而又不会因锁定表而造成任何停机,则可以设置一个从数据库,并从那里获取快照。不幸的是,设置从属数据库会导致导出实时数据库的停机时间,但是一旦运行该数据库,您应该能够锁定它的表,并使用其他人描述的方法进行导出。发生这种情况时,它将落后于主服务器,但不会阻止主服务器更新其表,并且在备份完成后会立即赶上。#4 楼
这是我的方法。由于使用FLUSH TABLES WITH READ LOCK
,因此它在所有情况下均应工作。 #!/bin/bash
DB=example
DUMP_FILE=export.sql
# Lock the database and sleep in background task
mysql -uroot -proot $DB -e "FLUSH TABLES WITH READ LOCK; DO SLEEP(3600);" &
sleep 3
# Export the database while it is locked
mysqldump -uroot -proot --opt $DB > $DUMP_FILE
# When finished, kill the previous background task to unlock
kill $! 2>/dev/null
wait $! 2>/dev/null
echo "Finished export, and unlocked !"
shell
sleep
命令只是为了确保在运行mysqldump之前执行运行mysql lock命令的后台任务。您可以将其减少到1秒,但仍然可以。将其增加到30秒,然后尝试在30秒钟内将另一个客户端的任何表中的值插入,您会看到它已被锁定。使用此手动背景锁定有两个优点,而不是使用
mysqldump
选项--single-transaction
和--lock-tables
:如果您混合使用MyISAM / InnoDB表,则这将锁定所有内容。
在相同的锁定期间,除了
mysqldump
之外,您还可以运行其他命令。期。例如,在主节点上设置复制时,这很有用,因为您需要在创建的转储的确切状态(在解锁数据库之前)使用SHOW MASTER STATUS;
获取二进制日志位置,以便能够创建复制从属。#5 楼
mysql官方文档的建议是,您应该有一个Master“ M1”数据库和一个Slave“ S1”数据库,如“方案2:使用只读Slave进行备份”中所述,备份Master或通过将其设置为只读进行从属
您应该将从属数据库设置为只读并执行
#6 楼
如果MYISAM表很大,并且需要不加锁转储该表并避免高服务器负载,则可以使用以下脚本。#!/bin/sh
my_user="user"
my_password="password"
my_db="vpn"
my_table="traffic"
my_step=100000
read -p "Dumping table ${my_db}.${my_table} to ${my_table}.sql?" yn
case $yn in
[Yy]* ) break;;
* ) echo "User cancel."; exit;;
esac
my_count=$(mysql $my_db -u $my_user -p$my_password -se "SELECT count(*) FROM $my_table")
my_count=$(($my_count + 0))
if [ ! $my_count ]
then
echo "No records found"
exit
fi
echo "Records in table ${my_db}.${my_table}: ${my_count}"
echo "" > $my_table.sql
max_progress=60
for (( limit=0; limit<=$my_count; limit+=$my_step )); do
progress=$((max_progress * ( limit + my_step) / my_count))
echo -ne "Dumping ["
for ((i=0; i<$progress; i ++)); do
echo -ne "#"
done
for ((; i<$max_progress; i ++)); do
echo -ne "."
done
mysqldump -u $my_user -p$my_password --complete-insert --no-create-info --opt --where="1 limit $limit , $my_step" $my_db $my_table >> $my_table.sql
echo "" >> $my_table.sql
echo -ne "] $((100 * ( limit + my_step ) / my_count)) %"
echo -ne "\r"
sleep 1
done
echo -ne "\n"
评论
哦...我希望有一个安全的方法,因为不仅转储中可能包含错误,而且如果在转储过程中发生了未保存的记录,数据库本身也不会得到未保存的记录。偶尔会发生这种情况,也许是在扫描相应的db表进行转储的同时保存了记录。因此,我担心在单个事务中进行备份,我想它会增加丢失记录的机会。