分类 数据库 下的文章

数据库备份

mysqldump这个命令相信大家都知道,但是实际使用过的人可能不多,再加上繁多的参数设置更是让人望而止步,除了项目负责人要对数据负责。
这里就简单记录一下他的常用方式:


//最直接的用法 -h连接地址 -u用户名 -p 密码 -P端口 -B 指定导出数据库 > 数据库备份名称-前面可以加上路径
mysqldump -hlocalhost -uusername -ppassword -P3306 -B database > backup_database.sql
//其他常用参数
   --all-databases ,-A 导出全部数据库。
   --allow-keywords 允许创建是关键词的列名字
   --tables 指定备份表名
   --single-transaction 导出数据之前提交一个BEGIN SQL语句,BEGIN 不会阻塞任何应用程序且能保证导出时数据库的一致性状态。

不出意外的话,mysql5.6以后的版本在执行以上命令的时候系统会有如下提示

mysqldump: [Warning] Using a password on the command line interface can be insecure.

大致意思是,在命令行直接使用明文密码是不安全的。虽然可以用后输入密码的方式解决,但是数据库备份正常是要放在定时脚本去执行,没法手动输入密码。最直接的解决方法是,在my.cnf文件里加入以下配置

[mysqldump]
user=username
password=password

然后mysqldump 命令后面就不需要再加上 -u -p参数了。

mysqldump -hlocalhost  -P3306 -B database > backup_database.sql

定时脚本备份数据库,每日凌晨执行

vim backup.sh

#!/bin/sh    

# 数据库连接信息
DB_USER="user"
DB_PASS="pwd"
DB_HOST="host"
# 需备份数据库列表 多个按照空格分割
DB_NAME=("backup_test" "back_test2")
# mysqldump 路径、备份文件存储路径、日期
BIN_DIR="/usr/local/mysql/bin"  
BCK_DIR="/home/backup/mysql"
DATE=`date +%F`

for var in ${DB_NAME[@]};
do
  $BIN_DIR/mysqldump --opt --single-transaction --master-data=2 -u$DB_USER -p$DB_PASS -h$DB_HOST $DB_NAME > $BCK_DIR/db_$var$DATE.sql
done

#删除超过7天的备份文件
BACKUPDIR="/home/backup/mysql/data" #定义备份文件路径
KEEPTIME=7 #定义需要删除的文件距离当前的天数
DELFILE=`find $BACKUPDIR -type f -mtime +$KEEPTIME -exec ls {} \;` #找到天数大于7天的文件
for delfile in ${DELFILE} #循环删除满足天数大于七天的文件
do
 rm -rf $delfile
done

恢复数据库

mysql恢复数据库大致有两种方法
1、mysql命令行

mysql -uroot -ppass;登录数据库
 mysql> use backup_db;
 mysql> source backup_db.sql;  //可以加上路径

2、不需要登录mysql直接恢复数据库

mysql -uroot -ppass backup_db < backup_db.sql; //需要注意的是,这里的命令是mysql,而不是mysqldump

mysql用户权限管理相关表

mysql中存在4个用户及权限相关的表,分别为user、db、tables_priv、columns_priv。
user表存放用户账号以及全局权限信息。
db表存放用户数据库级别的权限,例如哪些主机哪些用户可以访问哪个数据库。
tables_priv表存放表级别的权限,例如哪些主机哪些用户可以访问数据库的哪个表。
columns_priv表存放列级别的权限,例如哪些主机哪些用户可以访问数据库表的哪些字段。

添加用户

//创建用户名为xuxd,密码为xuxd123的用户
create user xuxd identified by 'xuxd123';

授权用户

//将db1库的所有操作权限授权给用户xuxd
//若是要授权所有库的权限 db1.* 改为 *.*
//若是要限制某个ip才能访问 xuxd@'%'改为 xuxd@'ip地址',%代表允许所有的ip远程登录
grant all privileges on db1.* to xuxd@'%' identified by 'xuxd123';

查看所有用户情况

select * from mysql.user

修改密码

update mysql.user set authentication_string = password('xuxd123?') where user = 'xuxd' and host = '%';

删除用户

//删除用户以及对应的权限,执行命令后user表和db表的相应记录都会消失
drop user xuxd@''

更新权限

flush privileges;

事实上,直接用grant授权给某个用户的时候,如果该用户不存在,mysql会自动生成用户信息。


以上命令皆运行于5.7.14版本,其他版本未测试

现实中很多项目的瓶颈最终都会落在数据库上。
刨除缓存和服务器配置差异,同样的配置,好的数据库设计能比劣质设计性能高出n倍,视觉上也会更有美感。

不讨论过多的细节,对于数据库优化主要有一下几个要点:

1、数据库结构优化:分库、分表、分区

  • 分区是一种简单的水平拆分,只需要在表结构设计时加上分区参数,不需要代码管理。分区可以让单表的存储量更多,也可以提高检索的速度。
  • 分表就是把一张大表,按照不同的规则分成多张小表,通常有垂直拆分和水平拆分两种,适合各个表之间关联度不高的场景。
  • 分库就是把一个数据库按照不同的规则或者业务需求分成多个库,像游戏的不同服、saas平台的不同商家端。

2、表结构优化

  • 使用可存下数据的最小数据类型
  • 尽可能不用null,数组可以用0代替,字符串可以用''代替
  • 尽量少用text,非用不可时尽量放在分表
  • 单表不要有太多字段,建议20个以内
  • 确定长度的字段用固定长度表,检索速度更快
  • 同一模块的表尽可能使用相同的前缀,表名尽可能表达含义
  • 所有字段名称都用小写字母,多词用"_"连接

3、索引优化

  • 选择离散度大的列做索引
  • 索引字段越小越好
  • 适当建立联合索引,离散度大的列放在联合索引前面
  • 索引不是越多越好,建立索引要适当

4、sql语句优化

  • 查看慢查询日志
  • 用explain分析sql的执行计划
  • 减少大表之间的join
  • 避免用select *,列出需要的查询字段即可
  • 避免or连接词,可以的话用IN代替
  • 避免在sql语句中进行列运算
  • 避免使用左侧模糊查询

5、存储引擎优化

  • 无特别要求存储引擎都使用innodb
  • innodb为行锁插入性能更优
  • 如果事务操作里面有包含mysiam引擎的表,会使事务失

另外就是一些比较琐碎的优化项了,比如,尽量不在循环中进行数据库操作,尽量减少查询数据库的次数、添加数据库连接池、必要的时候使用中间件解决异表间的搜索排序问题。

下载安装文件

到mysql官网找到5.7的下载地址:https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.33-linux-glibc2.12-x86_64.tar.gz

    //下载mysql压缩包
    cd /usr/local/
    wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.33-linux-glibc2.12-x86_64.tar.gz

   //解压缩
   tar -xvzf mysql-5.7.33-linux-glibc2.12-x86_64.tar.gz

处理旧版mysql

//关闭mysql服务
service mysqld stop

//备份mysql5.6
mv /usr/local/mysql /usr/local/mysql5.6

安装mysql5.7

//修改目录名
mv /usr/local/mysql-5.7.33-linux-glibc2.12-x86_64 /usr/local/mysql

//创建data目录,mysql5.7.33默认没有这个文件
mkdir /usr/local/mysql/data

//安装mysql5.7
/usr/local/mysql/bin/mysqld --initalize --user=mysql --datadir=/usr/local/mysql/data --basedir=/usr/local/mysql

安装完mysql,注意看最后一行root密码
WX20211006-170928.png


//启动mysql
service mysqld start

修改密码

//登录mysql
mysql -uroot -ppwd

//修改密码
alter user 'root'@'localhost' identified by 'new passwd';
flush privileges;

自此mysql升级完成。


- 阅读剩余部分 -

数据库锁设计主要是用于处理并发问题,当出现并发访问的时候,数据库需要合理的控制资源的访问规则。

按照所的粒度划分

  1. 全局锁
    全局锁就是对整个数据库实例加锁,mysql提供了一个全局读加锁的方法,命令是:Flush tables with read lock 。当你需要让整个库出于只读状态的时候,可以使用这个命令,之后其他线程的语句会被阻塞,包括增、删、改,数据库结构的修改和更新类食物的提交。典型的使用场景是做全库逻辑备份。
  2. 表锁
    表锁是mysql锁中粒度最大的一种锁,表示当前的操作对整张表加锁,资源开销比行锁少,不会出现死锁的情况,但是发生锁冲突的概率很大。被大部分的mysql引擎支持。表锁的语法是 lock tables … read/write。可以用 unlock tables 主动释放锁,也可以在客户端断开的时候自动释放。
  3. 页锁
    页级锁是mysql中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。BDB支持页级锁。
  4. 行锁
    行级锁是mysql中锁定粒度最小的一种锁,只针对当前操作的行进行加锁,是在引擎层由各个引擎自己实现的,但并不是所有的存储引擎都支持,MyISAM就不支持,InnoDB支持。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。有可能会出现死锁的情况。

按照锁的使用方式划分

  1. 排他锁
    排他锁又称写锁,如果事务T对数据A加上排他锁,那么其他事务不能再对A加任何类型的操作,但是T既能读数据,也能修改数据。
  2. 共享锁
    共享锁又称读锁,是读取操作创建的锁。其他用户可以并发读取数据,但是不能进行修改,知道共享锁释放。

按照锁思想划分

  1. 悲观锁
    悲观锁是指对数据被外界修改保持保守态度,因此在整个数据处理过程,将数据出于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制。对目标记录进行修改前,先试着给它加上锁,如果加锁成功,那么在解锁前,任何其他操作都会抛出异常。
  2. 乐观锁
    乐观锁一般假定数据不会造成冲突,所以只有在数据提交更新的时候,才会正式对数据冲突与否进行检测,如果发现冲突了,则返回错误信息,让用户决定如何操作。