linux技术--mysql 高级应用及 pymysql redis

# mysql 高级应用  及 pymysql redis   

* 复习  
* mysql分区  
* mysql 导入导出   
* mysql 优化    
* pymysql   
* redis    

## 复习  

```
更新  update 表名 set 字段名=值 where  
删除  delete from 表名 where 条件 
     truncate table 表名 
dcl  
    grant 权限 on 库.表 to 用户名@'ip地址' identified by '密码' with grant option;
    
    revoke
        revoke 权限 on 库.表 from 用户名@'IP地址';
如何减轻数据库的压力  
    方案:读写分离
    解决措施:主从复制  
    主:写  更新 插入  删除  
    从:读  查 
    
    binlog 日志  

    表复制 数据复制  
    视图 view 
    索引:普通索引  主键索引  唯一索引  全文索引  复合索引  
    alert table 表名 add index in_name(name,password);#创建了一个复合索引 
    select * from 表名 where name like '%zelinx%';

    rand()
    ceiling() 
    floor()
    sum()
    count()
    avg()
    
```

## mysql 时间戳 及时间格式化 

```
mysql> select unix_timestamp(now());
+-----------------------+
| unix_timestamp(now()) |
+-----------------------+
|            1536197428 |
+-----------------------+
1 row in set (0.00 sec)

mysql> select from_unixtime(1536197428);
+---------------------------+
| from_unixtime(1536197428) |
+---------------------------+
| 2018-09-06 09:30:28       |
+---------------------------+
1 row in set (0.00 sec)
```

## 使用 delete from 表名 后 自增的id 如何修复 

```
1.truncate table 表名
2.如果使用了  delete from 表名  接下来 alter table 表名 auto_increment=1; 恢复自增 即可   
```

## mysql 分区  

```
qq  100亿 条数据  
分表  将100亿条数据分成100张表  每张表 1亿条数据    
qq_01 
qq_100
10101
12345
10000
12334566
122222267
4334343434

ad1234566   字母加数字  分成36张表   截取第一位  
123adf
eewrewr78

1.除以100取余 
2.截取前几位   
3.转成hash值 然后截取前几位   
分表    

查找数据 :
1.判断位于哪张表中   
2.然后查找    

分区呢    
 1.用户还是当成一张表来操作  
 2.物理形态上分成了5个区 

```

## mysql  数据存储方式   

```
mysql 数据 以文件的形式存储在服务器上  
以 Ubuntu  apt-get 安装  mysql 为例子  

数据文件存放在  /var/lib/mysql  

不同的引擎 存放形式不一样  

myisam 引擎的数据表 存储形式 : 
1.  .frm  数据表的表结构 
2.  .myi  索引文件   
3.  .myd  数据文件   

innodb  引擎的存储形式  
 表名.frm  数据表结构文件
 表名.ibd  索引文件 和数据文件 共享一个表空间  


创建表的时候 进行分区  根据 id 字段进行分区  分成5个     hash分区  
mysql> create table t8(id int)engine=myisam default charset=utf8 partition by hash(id) partitions 5;
Query OK, 0 rows affected, 1 warning (0.13 sec)

mysql> create index in_id on t8(id);  #另外一种创建索引的方式  这个不能创建 主键索引 其它都可以  
Query OK, 0 rows affected, 1 warning (0.10 sec)
Records: 0  Duplicates: 0  Warnings: 1

mysql> insert into t8 values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
Query OK, 10 rows affected, 1 warning (0.01 sec)
Records: 10  Duplicates: 0  Warnings: 1

cd /var/lib/mysql/python1806 

watch -d -n 1 ls -lh

mysql> insert into t8 select * from t8; #倍增原理  


```

```
什么情况下添加索引?

 where 条件后的字段  

group by 字段名

order by   字段名  

经常使用条件查询   上面 where  group by  order by 后面的字段  要创建索引   

什么情况下 索引失效 ?

1. 使用 模糊查询   比如where name  like  ‘%haha%’; 
2. where  name like “ haha%”  只要保证左边没有 %  也可以让索引生效  
3. 最左原则   比如 我们给 a b c d 四个字段创建了索引   
   where a=1 and b=1 and c=1 and d=1; 索引生效 

       也就是 说 只要 where条件中 有 a 索引就生效  没有a 索引就失效  

1. or  条件   or前面字段 创建了 索引   or 后面字段也创建了索引   索引容易失效    

```

## mysql 导入导出

```
/usr/bin/mysqldump -u root -p test > /tmp/test.sql  #导出   
/usr/bin/mysql -u root -p test < /tmp/money.sql #导入  

cronteb -e 
0 3 * * * /usr/bin/mysqldump -u root -p test > /tmp/test.sql

service cron restart  

```

## mysql 只 备份 数据  导入数据

```
先登录到 mysql  
mysql -u root -p 

mysql> select * from money into outfile "/tmp/money.txt";
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
遇到这种情况  

mysql> show variables like "%secure%";
+--------------------------+-----------------------+
| Variable_name            | Value                 |
+--------------------------+-----------------------+
| require_secure_transport | OFF                   |
| secure_auth              | ON                    |
| secure_file_priv         | /var/lib/mysql-files/ |  官方默认允许 从这个目录/var/lib/mysql-files/导入导出 
+--------------------------+-----------------------+

 1· sudo  vim /etc/mysql/mysql.conf.d/mysqld.cnf
 2. 粘贴一行 secure_file_priv = /tmp   #允许将文件导出到 tmp目录下面  
 3.sudo service  mysql restart
 
 root@qulinx-virtual-machine:/tmp# cat money.txt 
1    泽林兄    3555524.75    辽宁    19    0
2    秋林兄    1999993.62    黑龙江    18    0
13    金星    123445.56    沈阳    40    1
4    刘强东    4000.00    江苏    40    1
5    抹茶妹妹    77777.66    浙江    30    1
6    范冰冰    1944432.75    山东    40    1
7    李晨    10666658.00    北京    30    0
8    魏缨络    233313.91    上海    29    1
9    薛之谦    3999965.25    上海    30    0
12    鹿晗    1223333.25    江苏    19    0
11    彭麻麻    99999.16    山东    50    1

 
 load data infile "/tmp/money.txt" into table money(也可以指定字段);

```

## 安装pymysql

```
第一种安装方式: pip install  pymysql;
第二种安装方式: sudo apt-get install git;
https://github.com/PyMySQL/PyMySQL 打开  
然后  git clone https://github.com/PyMySQL/PyMySQL.git

cd PyMySQL/

python setup.py install 
```

## mysql事务  

```
只有innodb 引擎才支持事务    

myisam  和 其它引擎是不支持事务的  


1.首先  关闭自动提交    
set autocommit=0 

delete from 表名;
rollback;


将表改为 innodb 引擎: 
    alter table 表名 engine=innodb;
```

### 连接数据库

```python
import pymysql # 引入 pymysql对象


'''
连接数据库 
参数1:数据库的ip地址 
参数2:用户名 
参数3:密码
参数4:连接的数据库名称
'''
db = pymysql.connect("127.0.0.1","root","123456","python1806")

#创建一个对象  cursor
cursor = db.cursor()
#准备sql语句
sql = "show tables"

#执行sql语句
cursor.execute(sql)

#获取返回的信息  

#data=cursor.fetchone()
data=cursor.fetchall()
print(data)

cursor.close()

db.close()

```

### 创建数据表

```python
import pymysql 

db = pymysql.connect("localhost","root","123456","python1806")
cursor = db.cursor()

#检测表是否存在  存在先删除  
sql1 = "drop table if exists haha"

cursor.execute(sql1)

sql2= "create table haha(id int(11) unsigned not null primary key auto_increment,username varchar(64) not null default 'shuaige')engine=myisam default charset=utf8"

cursor.execute(sql2)


cursor.close()
db.close()

```

### 插入数据

```python 
import pymysql # 引入 pymysql对象


'''
连接数据库 
参数1:数据库的ip地址 
参数2:用户名 
参数3:密码
参数4:连接的数据库名称
'''
db = pymysql.connect("127.0.0.1","root","123456","python1806")

#创建一个对象  cursor
cursor = db.cursor()
#准备sql语句
sql = "insert into haha(username) values('123'),('456'),('789')"

try:
    cursor.execute(sql)
    db.commit()
except:
    db.rollback()

cursor.close()

db.close()

```

### 更新数据

```python
import pymysql # 引入 pymysql对象


'''
连接数据库 
参数1:数据库的ip地址 
参数2:用户名 
参数3:密码
参数4:连接的数据库名称
'''
db = pymysql.connect("127.0.0.1","root","123456","python1806")

#创建一个对象  cursor
cursor = db.cursor()
#准备sql语句
#sql = "insert into haha(username) values('123'),('456'),('789')"
sql = "update haha set username='东方不败' where id=2"

try:
    cursor.execute(sql)
    db.commit()
except:
    db.rollback()

cursor.close()

db.close()
```

### 删除数据

```python
import pymysql # 引入 pymysql对象


'''
连接数据库 
参数1:数据库的ip地址 
参数2:用户名 
参数3:密码
参数4:连接的数据库名称
'''
db = pymysql.connect("127.0.0.1","root","123456","python1806")

#创建一个对象  cursor
cursor = db.cursor()
#准备sql语句
sql = "delete from haha where id=1"
try:
    cursor.execute(sql)
    db.commit()
except:
    db.rollback()

cursor.close()

db.close()

```

### 查询数据

```python
import pymysql # 引入 pymysql对象


'''
连接数据库 
参数1:数据库的ip地址 
参数2:用户名 
参数3:密码
参数4:连接的数据库名称
'''
db = pymysql.connect("127.0.0.1","root","123456","python1806")

#创建一个对象  cursor
cursor = db.cursor()
#准备sql语句
sql = "select * from haha"

try:
    cursor.execute(sql) #执行sql语句
    result = cursor.fetchall() #取出所有的结果
    for row in result:
        print("%d--%s" % (row[0],row[1]))

except:
    db.rollback()
cursor.close()

db.close()

```

### mysql三大范式 

| id   | 姓名   | 性别   | 联系方式                        |
| ---- | ---- | ---- | --------------------------- |
| 1    | 张三   | 男    | 13888888888 qq 1010101 山东青岛 |

| id   | 姓名   | 性别   | 手机   | qq   | 省    | 市    | 县    | 镇    |
| :--- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
|      |      |      |      |      |      |      |      |      |

第一个表格  因为 联系方式 可以继续拆分 所以不满足第一范式   

总结:第一范式  原子性 就是说   字段 不能再拆分 

第二范式 :  

​    首先满足 第一范式  消除字段之间的部分依赖  

| 学号   | 姓名   | 课程号  | 班级   |
| ---- | ---- | ---- | ---- |
|      |      |      |      |

| 学号   | 姓名   |
| ---- | ---- |
|      |      |

| 班级号  | 课程   |
| ---- | ---- |
|      |      |

| 学号   | 课程号  |
| ---- | ---- |
|      |      |

第三范式 

​    首先满足第二范式  消除字段之间的 传递依赖     

​    消除传递依赖 就是 每个字段 必须完全依赖于 主键      

## redis  nosql  也叫非关系型数据库  

> 常见的nosql :
>
> redis
>
> mongodb 
>
> couchdb 
>
> memcached  
>
> RabbitMQ 

只有key value  a=[1,2,3] a[0]

内存级数据库 特点: 

1.速度快 读的次数是 110000/次  写  81000次  

2.开源免费 

3.常用的 5种数据类型   

### nosql 应用

- 用来 和 mysql 结合使用  当缓存   提高访问速度  减轻mysql 负担  
- 好多产品 都在使用redis  处理  好友关系  秒杀      新浪微博  segmentfault   

## 安装 redis

> http://www.redis.cn/

```
wget -c http://download.redis.io/releases/redis-3.2.9.tar.gz
tar -zxvf redis-3.2.9.tar.gz
 sudo cp -r redis-3.2.9 /usr/local/redis
 
cd /usr/local/redis 

sudo make install 

```

### redis 常用的可执行文件   cd /usr/local/redis/src

| 文件              | 说明                         |
| --------------- | -------------------------- |
| redis-server    | redis 服务器  别的redis 客户端可以连接 |
| redis-cli       | redis 客户端   可以连接别的redis服务器 |
| redis-benchmark | redis 性能测试工具               |
| redis-check-aof | aof 修复工具                   |
| redis-check-rdb | rdb 修复工具                   |
| redis-sentinel  | redis 2.8以后 哨兵服务器          |

- src 存放常用的执行文件 
- utils 存放自定义启动脚本  比如 开机启动脚本       
- /usr/local/redis  redis 配置文件在 这里  

### redis 数据持久化机制

- aof
- rdb

## 启动redis

```
redis 默认端口号 6379  
redis 单个key的大小能达到512M 

cd /usr/local/redis/src 
sudo ./redis-server    

或者直接 sudo /usr/local/redis/src/redis-server 
ctrl+c  退出    
以上是前台启动 

cd /usr/local/redis  
sudo vim redis.conf  
第128 行  

将daemonize no 改为  yes 

sudo /usr/local/redis/src/redis-server /usr/local/redis/redis.conf  启动的时候以配置文件启动   

ps -aux | grep redis 查看是否启动   

grep --color=auto 像这样的是守护进程  不用管 
```

### 连接redis

```
在任何目录 都可以使用 redis-cli 
或者redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> ping 
PONG  #返回这个说明  执行成功 

exit 退出   
```

## 配置redis开机启动

```
cd /usr/local/redis/utils  

 sudo cp redis_init_script redis_init_script_6379 
 vim redis_init_script_6379   相当于自己写了一个脚本  通过执行redis 的执行文件 达到启动的目的 
 sudo vim redis_init_script_6379 

REDISPORT=6379  #指定端口号
EXEC=/usr/local/redis/src/redis-server  #redis 服务器脚本所在的路径  
CLIEXEC=/usr/local/redis/src/redis-cli  #redis 客户端所在的路径 

PIDFILE=/var/run/redis_${REDISPORT}.pid  #指定 redis 进程文件存放目录
CONF="/usr/local/redis/redis_${REDISPORT}.conf" #redis 以哪一个配置文件启动   

sudo /usr/local/redis/utils/redis_init_script_6379 start   接下来就可以以这种方式启动 
sudo /usr/local/redis/utils/redis_init_script_6379 stop|restart  
如果上面提示 
redis_6379.pid 已经存在  

cd /var/run  
sudo rm -rf redis_6379.pid 


/usr/local/redis/src/redis-server /usr/local/redis/redis.conf 可以不用这种方式启动了   


接下来 加入到开机启动  

sudo vim /etc/rc.local 

然后最后一行 写入  sudo /usr/local/redis/utils/redis_init_script_6379 start

```

## redis 5个数据类型  常用的这五种  不止这五种

- string  
- hash
- list 
- set 
- zset

### string

> redis 最基本的数据类型  key value   key 最大支持512M 二进制 安全性高   可以存储任何数据  图像  音频 视频 数字等  

#### 设置  就好比mysql中的 insert      set   mset 

```
set key  value  

127.0.0.1:6379> set name kangbazi 
OK 

setex key 时间(秒为单位) value
mset key value key value

```

#### 获取 好比mysql中的 select    get  mget 

```
get key 获取指定 key的值
127.0.0.1:6379> get name
"zelinx"
127.0.0.1:6379> get name
(nil)   #value值为空的意思  

mget key1 key2  #批量获取指定key中的内容 
127.0.0.1:6379> mget python python1
1) "1806"
2) "1807"

```

#### 运算 参与运算的value值必须是int 整型     incr  decr incrby  decrby  incrbyfloat

```
incr key #让制定key的值 自增1 
decr key #自减1
incrby key 制定数目  
127.0.0.1:6379> decr num   #当前值 99
(integer) 99
127.0.0.1:6379> incrby num 1000  #当前值增加 指定值1000  最后结果 1099
(integer) 1099
127.0.0.1:6379> decrby num 500  #自减指定的值   
(integer) 599
127.0.0.1:6379> incrbyfloat num 100.123  #自增指定的值为 float 类型 
"699.123"

```

#### 追加内容   append 

```
append key value  #往指定的key中追加内容  
127.0.0.1:6379> set names hello
OK  #代表存入成功
127.0.0.1:6379> APPEND names world
(integer) 10
127.0.0.1:6379> get names 
"helloworld"

```

#### 获取指定key的value值得长度 

```
strlen key 
```

#### 关于key的操作  

```
127.0.0.1:6379> exists kangbazi   #exists key    1代表存在  0代表 不存在 
(integer) 1  

type  key #查看key 对应的Value的数据类型   redis常用的五种数据类型

127.0.0.1:6379> type kangbazi
string

127.0.0.1:6379> del kangbazi  #del key 删除key 
(integer) 1  #1 代表删除成功 

expire key 时间  秒为单位    #设置key的过期时间   
expire key -1 表示永不过期

ttl key  查看key在内存中的剩余时间 


127.0.0.1:6379> expire names 20
(integer) 1
127.0.0.1:6379> ttl names
(integer) 11
127.0.0.1:6379> get names
(nil)  表示过期了 

```

### hash  一般用来存储对象  redis 做缓存 用的就是 hash类型    一般 一张数据表  是 一个hash   

```
var box = {
    name:'kangbazi',
    run:function(){
        
    }
}
```

#### 设置  hset 

```
hset key 字段名 字段值 #hset person name zelinx 
127.0.0.1:6379> hmset user name zhangsan age 18 sex 0 height 181cm  weight 100kg  设置多个
OK
```

#### 获取

```
127.0.0.1:6379> hget key  字段名
"zelinx"  值字段值 

127.0.0.1:6379> hmget user name age sex height weight  获取多个属性的值  
1) "zhangsan"
2) "18"
3) "0"
4) "181cm"
5) "100kg"

获取多个属性和值  
127.0.0.1:6379> hgetall user
 1) "name"
 2) "zhangsan"
 3) "age"
 4) "18"
 5) "sex"
 6) "0"
 7) "height"
 8) "181cm"
 9) "weight"
10) "100kg"

获取多个属性  
127.0.0.1:6379> hkeys user
1) "name"
2) "age"
3) "sex"
4) "height"
5) "weight"


获取多个 value值  
127.0.0.1:6379> hvals user
1) "zhangsan"
2) "18"
3) "0"
4) "181cm"
5) "100kg"

获取数据 个数  

127.0.0.1:6379> hlen user
(integer) 5

```

#### 判断 属性是否存在

```
hexists key 字段名  1 存在 0 不存在 
127.0.0.1:6379> hexists user name
(integer) 1
127.0.0.1:6379> hexists user sex
(integer) 1
127.0.0.1:6379> hexists user talk

```

#### 删除属性和值

```
hdel key 字段名
127.0.0.1:6379> hdel user name 
(integer) 1
127.0.0.1:6379> hkeys user
1) "age"
2) "sex"
3) "height"
4) "weight"

```

#### 查看 属性值得长度  也就是查看key 对应的值得长度 

```
127.0.0.1:6379> hstrlen user height
(integer) 5

```

### list

### set

### zset

猜你喜欢

转载自blog.csdn.net/qq_42336700/article/details/82561622
今日推荐