MySQL其他和备份
事务
事务指的是一组操作,要么执行成功,要么都执行失败
我们来看下面一个例子:
我去银行给朋友汇款,我卡上有1000元,朋友卡有1000元,我给朋友转账100元(无手续费)。如果我的钱刚被扣完,这时候网络突然断了,而朋友账户的钱又没加,怎么办?
我们来模拟一下这个操作:
mysql> create table user(
id int auto_increment primary key,
name varchar(32) not null default '',
salary int not null default 0
)charset=utf8;
# 向表中插入数据
mysql> insert into user(name,salary) values ("qinyj",1000);
mysql> insert into user(name,salary) values ("jack",1000);
# 此时我们打开两个终端 查看数据
# 一个终端代表qinyj,另一个代表jack
mysql> select * from user where name="qinyj";
mysql> select * from user where name="jack";
# 当我开始转账的时候在我的窗口进行操作
mysql> update user set salary=900 where name="qinyj";
# 这时候模拟网突然断了,转不了账了
# 我们再来查看qinyj的账户
mysql> select * from user where name="qinyj";
# 我们再来看jack的账户
mysql> select * from user where name="jack";
# 发现qinyj已经转账了,账户的钱已经少了100,但是jack的账户的钱却没有增加,那么这就造成了一个数据上的不安全。
模拟完上面的操作之后呢,我们来解决这个问题
解决这个问题就需要用到mysql的事务:
start transaction:
使用事务
commit/rollback:
提交事务/回滚事务
例子:
mysql> start transaction; # 使用事务
Query OK, 0 rows affected (0.00 sec)
mysql> update user set salary=900 where name="qinyj";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update user set salary=1100 where name="jack";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> commit; # 提交事务
Query OK, 0 rows affected (0.01 sec)
# 如果在commit之前 所有转账sql已经执行完毕了,这时候突然断网了,那么mysql会默认执行rollback操作,将事务中所有操作回滚到使用事务之前的状态,保证了数据的安全
mysql> rollback; # 回滚提交
Query OK, 0 rows affected (0.00 sec)
# 我们再来看两个账户的金额:
mysql> select * from user where name="qinyj";
mysql> select * from user where name="jack";
pymysql使用事务
import pymysql
conn = pymysql.connect(
host="192.168.32.130",
password="123",
user="root",
database="test",
charset="utf8"
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
try:
sql = "start transaction"
cursor.execute(sql)
sql = "update user set salary=800 where name='qinyj'"
cursor.execute(sql)
import time
print(".......")
time.sleep(20)
sql = "update user set salary=1200 where name='jack'"
cursor.execute(sql)
sql = "commit"
cursor.execute(sql)
except Exception as e:
print("事务处理失败")
sql = "rollback"
cursor.execute(sql)
cursor.close()
conn.close()
那么我们来总结一下事务的特性特征:
- 原子性:原子意思为最小的粒子,即不能再分的书屋,要么全部执行,要么全部取消,就像上面银行转账的例子。
- 一致性:指事务发生前和发生后数据的总额依然匹配。
- 隔离性:指得是某个事务的操作对其他事务不可见,隔离开来的。
- 持久性:当事务完成后,影响应该保留下来,不能撤销,只能通过“补偿性事务”来取消之前的错误。
存储引擎
存储引擎负责MySQL中的数据的存储和提取。
MySQL存储引擎有很多,不同的存储引擎保存数据和索引的方式是不同的。每一种存储引擎都有它的优势和劣势
InnoDB存储引擎
InnoDB是默认的事务型存储引擎,也是最重要,使用最广泛的存储引擎。在没有特殊情况下,一般优先使用InnoDB存储引擎。
数据存储形式
使用InnoDB时,会将数据表分为.frm 和 idb两个文件进行存储。
锁的粒度
InnoDB采用MVCC(多版本并发控制)来支持高并发,InnoDB实现了四个隔离级别,默认级别是REPETABLE READ,并通过间隙锁策略防止幻读的出现。它的锁粒度是行锁。【通过MVCC实现,MVCC在稍后会进行介绍】
事务
InnoDB是典型的事务型存储引擎,并且通过一些机制和工具,支持真正的热备份。
数据的存储特点
InnoDB表是基于聚簇索引建立的,聚簇索引对主键的查询有很高的性能,不过他的二级索引(非主键索引)必须包含主键列,索引其他的索引会很大。
MyISAM存储引擎
数据存储形式
MyISAM采用的是索引与数据分离的形式,将数据保存在三个文件中.frm.MYD,.MYIs。
锁的粒度
MyISAM不支持行锁,所以读取时对表加上共享锁,在写入是对表加上排他锁。由于是对整张表加锁,相比InnoDB,在并发写入时效率很低。
事务
MyISAM不支持事务。
数据的存储特点
MyISAM是基于非聚簇索引进行存储的。
其他
MyISAM提供了大量的特性,包括全文索引,压缩,空间函数,延迟更新索引键等。
进行压缩后的表是不能进行修改的,但是压缩表可以极大减少磁盘占用空间,因此也可以减少磁盘IO,从而提供查询性能。
全文索引,是一种基于分词创建的索引,可以支持复杂的查询。
延迟更新索引键,不会将更新的索引数据立即写入到磁盘,而是会写到内存中的缓冲区中,只有在清除缓冲区时候才会将对应的索引写入磁盘,这种方式大大提升了写入性能。
对比与选择
两种存储引擎各有各的有点,MyISAM专注性能,InnoDB专注事务。
如何在两种存储引擎中进行选择?
① 是否有事务操作?有,InnoDB。
②是否存储并发修改?有,InnoDB。
③是否追求快速查询,且数据修改较少?是,MyISAM。
④是否使用全文索引?如果不引用第三方框架,可以选择MyISAM,但是可以选用第三方框架和InnDB效率会更高。
我们在创建表的时候可以指定存储引擎,如果没有指定,默认在mysql5.5版本以上创建的表默认是InnoDB引擎
两个引擎的区别:
- InnoDB:支持事务;支持行锁
- MyIsam:不支持事务;支持表锁
查看当前默认存储引擎:
show engines;
在创建表的时候指定引擎:
create table test(id int auto_increment primary key)engine=InnoDB;
create table test(id int auto_increment primary key)engine=MyIsam;
在配置文件中指定:
default-storage-engine=INNODB
常见存储引擎以及使用场景:
- InnoDB:事务处理应用程序,对于类似击飞系统或者对数据要求比较高的
- MyIsam:对事务完整性,并发性要求不高,可以使用这个存储引擎。
视图
视图是一种虚拟存在的表,通俗的说 视图就是执行select语句后返回的结果。
增加视图:
create view 视图名 as sql语句
删除视图:
drop view 视图名
例子:
# 如果我们对下面的sql语句查询非常频繁并且这个sql非常长,那么我们可以创建出来一个视图
mysql> select * from user where name="qinyj";
# 创建视图
mysql> create view v1 as select * from user where name="qinyj";
Query OK, 0 rows affected (0.00 sec)
# 再查看表,会看到有一个v1的表
show tables;
# 那么我们如果想要去查第一个sql,并且这个sql非常长,又不想重新输入一遍,那么我们可以查这个视图,出来效果是一样的。
mysql> select * from v1;
触发器
假设现在有这样一个场景,有两张表,
订单表 库存表
当我们下一个订单的时候,订单表中需要增加一条记录,同时库存表中需要减1,这两个操作是同时发生的,并且前一个操作触发下一个操作,就可以使用触发器
使用方法:
增加触发器:
delimiter //
create trigger boy_before_insert_girl before insert on boy for each row
begin
insert into girl (girl_name) values ("aa");
end //
delimiter ;
例子:
mysql> delimiter //
mysql> create trigger boy_before_insert_girl before insert on boy for each row
-> begin
-> insert into girl (girl_name) values ("aa");
-> end //
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ; # 结束符
mysql> show triggers\G;
# 当我们在向boy表中插入数据的时候,我们再来查询girl表的数据会发现会多一条记录
mysql> insert into boy (boy_name) values ("qinyj");
Query OK, 1 row affected (0.01 sec)
mysql> select * from boy;
mysql> select * from girl;
删除触发器:
drop trigger 触发器名
存储过程
像一个SQL函数,一组sql语句集,存储过程就是一段预执行的sql语句,都是一组sql集,存储过程主动调用的时候才会执行。
创建存储过程:
delimiter //
create procedure p1()
begin
select * from boy where id=2;
end //
delimiter ;
查看存储过程:
mysql> show procedure status\G;
删除存储过程:
mysql> drop procedure p1;
调用存储过程:
mysql> call p1();
函数
参考:https://www.runoob.com/mysql/mysql-functions.html
备份
物理备份
可以使用percona-xtrabackup-2.0.7-552.rhel6.x86_64.rpm对mysql进行备份。
xtrabackup官方网址:https://www.percona.com/downloads/XtraBackup/
基本语法--多实例备份--语法解释:
--user=数据库用户
--password=数据库密码
--socket=指定socket
--default-file=指定配置文件
最后面是存放位置
例子:
innobackupex --user=root --port=3306 --host=127.0.0.1 --defaults-file=/etc/my.cnf --defaults-group=mysqld3306 --stream=tar /usr/local/backup |gzip > 127.0.0.1_3306.tar.gz
全数据还原
- /etc/init.d/mysqld stop //停掉mysql
- mv /var/lib/mysql /var/lib/mysql_bak //数据目录备份
- mkdir -p /var/lib/mysql //重建数据目录
- --apply-log选项的命令是准备在一个备份上启动mysql服务
- --copy-back 选项的命令从备份目录拷贝数据,索引,日志到my.cnf文件里规定的初始位置
- innobackupex --defaults-file=/etc/my.cnf --user=root --apply-log /home/tank/backup/2014-09-18_16-35-12
- chown -R mysql.mysql /var/lib/mysql //改变文件所属
- /etc/init.d/mysqld stop //启动mysql
备份脚本
#!/bin/bash
# Version V1.1
###############################################
# 保留备份的天数
DAY=3
#等待n秒后再执行备份
wait=60
#是否开启增量备份默认0为开启1为关闭
open_increase_bak=1
#全备时间点
default_time=4
#设置不进行备份的时间点
exclude_time="0 5"
###############################################
#载入环境变量,否则无法找到/usr/local/mysql/bin/mysql路径
source /etc/profile
DBIP="127.0.0.1"
DBUSER="xxx"
DBPWD="root"
DATE=`date +%F_%H-%M`
Hour=`date '+%H'`
PORT=`netstat -tunlp|grep mysql |awk '{print $4}'|awk -F: '{print $2}'`
MYCNF="/etc/my.cnf"
LOG_FILE="/home/msbakscript/logs/xtrabackup.log"
BACKUP_PATH="/usr/local/hero_all_backup"
MYSQL_LOG="/home/msbakscript/logs/mysql.log"
INNOBACKUPEX="/usr/bin/innobackupex"
bak_log="/home/msbakscript/logs/mysqlbak.log"
MYSQL_PATH="/usr/local/mysql/var"
HOST=$(awk -F= '/IPADDR=/ {print $2}' /etc/sysconfig/network-scripts/ifcfg-eth1)
CHECKPOINT=$(awk '/to_lsn/ {print $3}' /usr/local/hero_all_backup/xtrabackup_checkpoints 2>/dev/null)
all_bak=("$HOST"_"$DATE")
increase_bak=("$HOST"_"$DATE""-increase")
if [ $# -eq 0 -o $# -eq 1 -o $# -eq 2 ];then
echo "OK" > /dev/null
else
echo "sh $0 allbakfile 或者 sh $0 allbakfile incbakfile"
exit 1
fi
[ ! -d ${BACKUP_PATH} ] && mkdir -p ${BACKUP_PATH}
[ ! -d /home/msbakscript/logs ] && mkdir -p /home/msbakscript/logs
if [ -z "`/sbin/pidof -s mysqld`" ];then
echo "mysqld is not running"
exit 1
fi
if [ `rpm -qa |grep -c xtrabackup-0.9-2.rhel4` -eq 1 ];then
rpm -e xtrabackup-0.9-2.rhel4
fi
if [ ! -f /usr/bin/innobackupex ];then
echo "xtrabackup is not installed"
rpm -i --nodeps http://122.228.194.133:8080/percona-xtrabackup-2.0.7-552.rhel5.x86_64.rpm
elif [ -f /usr/bin/innobackupex ] && [ `ps -ef|grep -v grep |grep -c /usr/bin/innobackupex` -ge 1 ];then
echo "xtrabackup process already exist."
exit 1
fi
complete_bak ()
{
cd ${BACKUP_PATH}
${INNOBACKUPEX} --user=${DBUSER} --password=${DBPWD} --port=${PORT} --host=${DBIP} --defaults-file=${MYCNF} --stream=tar ${BACKUP_PATH}/ 2>>${LOG_FILE} |gzip >${BACKUP_PATH}/${all_bak}_${P
ORT}.tar.gz
if [ $? -eq 0 ] && [ `tail -10 "${LOG_FILE}" | grep -ic "completed OK"` -eq 1 ];then
tar zxvfi ${BACKUP_PATH}/${all_bak}_${PORT}.tar.gz xtrabackup_checkpoints
echo "${all_bak}_${PORT}.tar.gz backup successed" >>${bak_log}
echo -en "ok\n${all_bak}_${PORT}.tar.gz" >${MYSQL_LOG}
sh /home/msbakscript/redis_backup.sh
chown nobody.nobody *
else
echo "${all_bak}_${PORT}.tar.gz backup failed" >>${bak_log}
echo -e "failure\n${all_bak}_${PORT}.tar.gz" >${MYSQL_LOG}
exit 1
fi
}
complete_bak
increase_bak ()
{
cd ${BACKUP_PATH}
if [ ! -f ${BACKUP_PATH}/xtrabackup_checkpoints -o -z ${BACKUP_PATH}/xtrabackup_checkpoints ];then
echo "xtrabackup_checkpoints does not exist" >>/{LOG_FILE}
complete_bak
exit 0
fi
${INNOBACKUPEX} --user=${DBUSER} --password=${DBPWD} --port=${PORT} --host=${DBIP} --defaults-file=${MYCNF} --no-timestamp --incremental --throttle=30 ${BACKUP_PATH}/${increase_bak}_${PORT
} --incremental-lsn=${CHECKPOINT} >>${LOG_FILE} 2>&1
if [ $? -eq 0 ] && [ `tail -10 "${LOG_FILE}" | grep -ic "completed OK"` -eq 1 ];then
tar zcfi ${increase_bak}_${PORT}.tar.gz ${increase_bak}/
rm -rf ${increase_bak}_${PORT}
echo "${increase_bak}_${PORT}.tar.gz backup successed" >>${bak_log}
echo -e "ok\n${increase_bak}_${PORT}.tar.gz" >${MYSQL_LOG}
else
echo "${increase_bak}_${PORT} backup failed" >>${bak_log}
echo -e "failure\n${increase_bak}_${PORT}.tar.gz" >${MYSQL_LOG}
exit 1
fi
}
increase_bak
del_bakfile ()
{
for dbfile in `find "${BACKUP_PATH}/" -name "[0-9]*.tar.gz" -type f -mtime +${DAY}`; do
rm -f ${dbfile}
done
}
del_bakfile
bakmysql ()
{
for i in ${exclude_time[@]};do
[ "${Hour}" -eq "$i" ] && exit 0
done
if [ "${Hour}" -eq "${default_time}" ];then
complete_bak
elif [ "${Hour}" -ne "${default_time}" -a ${open_increase_bak} -eq 0 ];then
increase_bak
else
exit 0
fi
}
bakmysql
case $# in
0)
bakmysql
del_bakfile
;;
1)
if [ "$1" = "all" ];then
complete_bak
del_bakfile
elif [ "$1" = "inc" ];then
increase_bak
del_bakfile
else
echo "sh $0 all or sh $0 inc" && exit 0
fi
;;
esac
逻辑备份
mysqldump工具:逻辑备份工具,适用所有存储引擎温备;支持完全或部分备份;对InnoDB存储引擎支持热备;Schema(数据库的定义)和数据存储在一起。
mysqldump参考:
https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html
语法:
mysqldump [OPTIONS] database [tables]
mysqldump [OPTIONS] –B DB1 [DB2 DB3...]
mysqldump [OPTIONS] –A [OPTIONS]
选项:
-A:备份所有库
-B db_name1,[db_name2,...]:备份指定库
-E:备份相关的所有event scheduler
-R:备份所有存储过程和存储函数
--triggers:备份表相关触发器,默认启用,用--skip-triggers,不备份触发器
--master-data={1|2}:
1:所备份的数据之前加一条记录为CHANGE MASTER TO语句,非注释,不指定默认为1
2:记录为注释的CHANGE MASTER TO语句,注意:此选项会自动关闭--lock-tables功能,自动打开--lock-all-tables功能(除非开启--single-transaction)
-F:备份前滚动日志,锁定表完成后,执行flush logs命令,生成新的二进制日志文件,配合-A时,会导致刷新多次数据库,在同一时刻执行转储和日志刷新,
则应同时使用--flush-logs和-x,--master-data或-single-transaction,此时只刷新一次;建议:和-x,--master-data或 --single-transaction一起使用
--compact 去掉注释,适合调试,生产不使用
-d:只备份表结构
-t:只备份数据,不备份create table
-n:不备份create database,可被-A或-B覆盖
--flush-privileges:备份前刷新授权表,备份mysql库或相关时需要使用
-f:忽略SQL错误,继续执行
--hex-blob:使用十六进制符号转储二进制列(例如,“abc”变为0x616263),受影响的数据类型包括BINARY, VARBINARY,BLOB,BIT
-q:不缓存查询,直接输出,加快备份速度
InnoDB建议备份策略:
mysqldump –uroot –A –F –E –R --single-transaction --master-data=1 --flush-privileges --triggers --hex-blob >$BACKUP/fullbak_$BACKUP_TIME.sql
MyISAM建议备份策略:
mysqldump –uroot –A –F –E –R –x --master-data=1 --flush-privileges --triggers --hex-blob >$BACKUP/fullbak_$BACKUP_TIME.sql
补充
1、 null 和 空值有什么区别?
null 占用空间、空不占空间
在查询的时候:
count会忽略null的行数,但不会忽略空值
2、 约束条件限制了not null可以插入空值吗?
可以插入空值
不可以插入null
3、 null 和 空哪个查询效率更高
使用 is not null的时候可以过滤掉 null的值,但是空值过滤不掉
使用count会过滤掉null值,但不会过滤掉空值
MySQL其他和备份的更多相关文章
- 如何用SQL语句实现Mysql数据库的备份与还原
以前一直做android客户端的项目,根本没有开发asp.net mvc的开发,现阶段做了一个模块,参数设置,以及数据库的备份与还原.其需求如下: 参数设置 本项参数设置为对自动数据备份进行设置,管理 ...
- 通过innobackupex实现对MySQL的增量备份与还原
备份 增量备份是基于完整备份的,所以我们需要先做一次完整备份: innobackupex --password=test /backup/ 备注:test是我的MySQL服务的root用户的密码,/b ...
- mysql命令行备份数据库
MySQL数据库使用命令行备份|MySQL数据库备份命令 例如: 数据库地址:127.0.0.1 数据库用户名:root 数据库密码:pass 数据库名称:myweb 备份数据库到D盘跟目录 mysq ...
- mysqldump常用于MySQL数据库逻辑备份
mysqldump常用于MySQL数据库逻辑备份. 1.各种用法说明 A. 最简单的用法: mysqldump -uroot -pPassword [database name] > [dump ...
- 我的MYSQL学习心得 备份和恢复(详细)
备份 逻辑备份方法 使用MYSQLDUMP命令备份 MYSQLDUMP是MYSQL提供的一个非常有用的数据库备份工具.mysqldump命令执行时将数据库备份成一个文本文件, 该文件中实际上包含了多个 ...
- 从MySQL全库备份中恢复某个库和某张表【转】
从MySQL全库备份中恢复某个库和某张表 一.全库备份-A [root@mha2 backup]#mysqldump -uroot -p123456 --default-character-set=u ...
- MySQL二进制日志备份和恢复详解
原文链接:http://www.showerlee.com/archives/681 ****经实践,该教程ok,特在此分享**** 基本概念 定义: 二进制日志包含了所有更新了数据或者已经潜在更新了 ...
- MySQL的数据备份以及pymysql的使用
一.MySQL的数据备份 语法: # mysqldump -h 服务器 -u用户名 -p密码 数据库名 > 备份文件.sql #示例: #单库备份 mysqldump -uroot -p123 ...
- MYSQL数据库增量备份
MySQL数据库增量备份,在这之前修改我们的数据库配置文件/etc/my.cnf开启bin-log日志功能即可.接下来是我参考了下网上的一些方法,自己写的,主要还是要能学到他的一些思路和方法. #fu ...
- [知了堂学习笔记]_Java代码实现MySQL数据库的备份与还原
通常在MySQL数据库的备份和恢复的时候,多是采用在cmd中执行mysql命令来实现. 例如: mysqldump -h127.0.0.1 -uroot -ppass test > d:/tes ...
随机推荐
- JVM内核-原理、诊断与优化学习笔记(十一):JVM字节码执行
文章目录 javap javap 举个
- Altium Designer 精心总结(转)
https://blog.csdn.net/qq_29350001/article/details/52199356 设置铺铜间距规则,Electrical-Clearence_Poly设置如下,是铺 ...
- lasso数学解释
lasso:是L1正则化(绝对值) 注:坐标下降法即前向逐步线性回归 lasso算法:常用于特征选择 最小角算法,由于时间有限没有去好好研究(其实是有点复杂,尴尬)
- centos 7 设置IP地址
先说下安装方式:我是采用的最小化安装 虚拟机软件:vmware 设置IP有两种情况,动态IP和静态IP,下面分别说明两种IP地址的设置方法 1.动态IP 条件:路由设置了动态分配IP地址(一般默认是动 ...
- <面试题>学习面试
1.代码中要修改不可变数据会出现什么问题? 抛出什么异常? 代码不会正常运行,抛出 TypeError 异常. # 比如修改元祖.会报错 TypeError: 'tuple' object does ...
- element-ui表格合计不显示&被遮挡问题
step1:修改全局样式 .el-table{ overflow:visible !important; } .el-card__body { padding: 20px 20px 50px 20px ...
- moment 获取当前月日历
获取当前月日历 <template> <div id="calendar"> <div class="top">{{date ...
- 将sparkStreaming的结果保存到S3
将spark解析的结果保存到S3 这个和保存到本地的区别在于,你需要配置aws的key和密码,以及它的region,代码如下 package com.alo7.spark import java.ut ...
- JS对象 指定分隔符连接数组元素join() join()方法用于把数组中的所有元素放入一个字符串。元素是通过指定的分隔符进行分隔的。
指定分隔符连接数组元素join() join()方法用于把数组中的所有元素放入一个字符串.元素是通过指定的分隔符进行分隔的. 语法: arrayObject.join(分隔符) 参数说明: 注意:返回 ...
- css---6伪元素选择器
after :在内容后边 <!DOCTYPE html> <html lang="en"> <head> & ...