Rao's Blog

  • 首页

  • 标签

  • 分类

  • 归档

  • 搜索

Python

发表于 2019-10-22 | 更新于 2019-10-26 | 分类于 Python

目录

  • Python · 简介安装
  • Python · 数据类型
  • Python · 控制流
  • Python · 函数
  • Python · 模块和包
  • Python · 面向对象编程
  • Python · 异常
  • Pyhton · I/O 编程
  • Python · 进程与线程
  • Python · 正则表达式
  • Python · 网络编程
  • Python · 测试
  • Python · 开发规范

MySQL · 案例分析 · 磁盘空间不足

发表于 2019-10-21 | 更新于 2019-11-15 | 分类于 MySQL

问题现象

1
2
3
4
5
6
7
8
9
10
11
12
13
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos_cosmoim--zdyq05-root 100G 13G 87G 13% /
devtmpfs 63G 0 63G 0% /dev
tmpfs 63G 0 63G 0% /dev/shm
tmpfs 63G 130M 63G 1% /run
tmpfs 63G 0 63G 0% /sys/fs/cgroup
/dev/sda1 497M 172M 326M 35% /boot
/dev/mapper/centos_cosmoim--zdyq05-data 888G 581G 308G 66% /data
tmpfs 13G 12K 13G 1% /run/user/42
tmpfs 13G 0 13G 0% /run/user/1001
tmpfs 13G 0 13G 0% /run/user/1002
tmpfs 13G 0 13G 0% /run/user/0

原因分析

文件排序命令

1
2
3
4
5
6
7
8
9
10
11
12
13
$ du -sxh /dir/* | sort -rh | head -5

du
-s:仅显示总计
-x:以一开始的文件系统为准,忽略其他不同文件系统的目录
-h:以可读形式显示文件大小

sort
-r:倒序排序
-h:以可读数字进行比较

head
-n:打印文本的前n行

多次执行查找最大文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ du -sxh /data/* | sort -rh | head -5
339G /data/mysql
243G /data/backup
4.0K /data/backup.sh

$ du -sxh /data/mysql/* | sort -rh | head -5
267G /data/mysql/cosmo_im_1004
1.1G /data/mysql/mysql-binlog.000944
1.1G /data/mysql/mysql-binlog.000943
1.1G /data/mysql/mysql-binlog.000942
1.1G /data/mysql/mysql-binlog.000941

$ du -sxh /data/mysql/cosmo_im_1004/* | sort -rh | head -5
231G /data/mysql/cosmo_im_1004/bns_pm_pokayoke.ibd
3.8G /data/mysql/cosmo_im_1004/bns_pm_scanscehistory.ibd
3.5G /data/mysql/cosmo_im_1004/bns_pm_scanhistory_month.ibd
3.4G /data/mysql/cosmo_im_1004/bns_io_pm_pokayoke.ibd
3.0G /data/mysql/cosmo_im_1004/bns_pm_operation.ibd

最终,确定最大文件是 /data/mysql/cosmo_im_1004/bns_pm_pokayoke.ibd

CentOS 7 安装 Python pip

发表于 2019-10-21 | 更新于 2019-11-13 | 分类于 Linux

简介

CentOS 7.x 默认安装的版本为 python 2.7.5,默认是没有安装 pip

安装

yum 安装

1
2
$ yum -y install epel-release
$ yum -y install python-pip

脚本安装

1
2
$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
$ python get-pip.py

MySQL · 误操作场景下数据快速恢复

发表于 2019-10-21 | 更新于 2019-11-12 | 分类于 MySQL

背景

线上环境核心业务数据,delete/update 操作一张表,忘加 where 限制条件,如何快速恢复?

方案

  • 备份恢复:先用全量备份恢复实例,再利用增量 binlog 备份恢复到误操作之前的状态,费时费力!
  • 第三方工具:binlog2sql(支持 DML Delete/Update 等语句回滚,不支持 DDL Drop 等语句回滚)

binlog2sql 工具实战

支持

  • MySQL 5.6/5.7
  • Delete、Update

要求

  • MySQL 配置要求
1
2
3
4
5
[mysqld]
server_id = 1
log_bin = /data/mysql/mysql-bin.log
binlog_format = row
binlog_row_image = full
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
mysql> show variables like 'server_id';
+---------------+---------+
| Variable_name | Value |
+---------------+---------+
| server_id | 3306100 |
+---------------+---------+

mysql> show variables like 'log_bin%';
+---------------------------------+--------------------------------+
| Variable_name | Value |
+---------------------------------+--------------------------------+
| log_bin | ON |
| log_bin_basename | /data/mysql/mysql-binlog |
+---------------------------------+--------------------------------+

mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+

mysql> show variables like 'binlog_row_image';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| binlog_row_image | FULL |
+------------------+-------+
  • MySQL 权限要求:SELECT、REPLICATION SLAVE、REPLICATION CLIENT
1
2
3
4
mysql> show grants for 'cosmo_t'\G
*************************** 1. row ***************************
Grants for cosmo_t@%: GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'cosmo_t'@'%'
1 row in set (0.00 sec)
  • 申请特权账号,登录服务器

操作步骤

  • 安装 pip

  • 安装 binlog2sql

1
2
3
$ cd /usr/local/src
$ git clone https://github.com/danfengcao/binlog2sql.git && cd binlog2sql
$ pip install -r requirements.txt
  • 根据误操作时间,确定 binlog 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mysql> show master status;
+---------------------+-----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------------+-----------+--------------+------------------+-------------------+
| mysql-bin.000020 | 576640842 | | | |
+---------------------+-----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

$ ll /data/mysql | grep mysql-bin
-rw-r----- 1 mysql mysql 1.1G Oct 23 03:03 mysql-binlog.000224
-rw-r----- 1 mysql mysql 1.1G Oct 24 12:25 mysql-binlog.000225
-rw-r----- 1 mysql mysql 1.1G Oct 25 18:32 mysql-binlog.000226
-rw-r----- 1 mysql mysql 1.1G Oct 27 00:21 mysql-binlog.000227
-rw-r----- 1 mysql mysql 1.1G Oct 28 05:45 mysql-binlog.000228
-rw-r----- 1 mysql mysql 1.1G Oct 29 12:32 mysql-binlog.000229
-rw-r----- 1 mysql mysql 1.1G Oct 30 19:00 mysql-binlog.000230
-rw-r----- 1 mysql mysql 1.1G Nov 1 16:30 mysql-binlog.000231
-rw-r----- 1 mysql mysql 1.1G Nov 3 00:20 mysql-binlog.000232
-rw-r----- 1 mysql mysql 1.1G Nov 4 16:47 mysql-binlog.000233
-rw-r----- 1 mysql mysql 1.1G Nov 6 00:21 mysql-binlog.000234
-rw-r----- 1 mysql mysql 473M Nov 6 14:48 mysql-binlog.000235
-rw-r----- 1 mysql mysql 384 Nov 6 00:21 mysql-binlog.index
  • 定位误执行 SQL
1
2
3
4
5
6
7
$ python binlog2sql.py -h'x.x.x.x' -uroot -p'xx' -dtest -temployees --start-file='mysql-bin.000020' --sql-type=DELETE > result.sql

DELETE FROM `test`.`employees` WHERE `name`='xujinliang' AND `gmt_modified`='2019-09-24 17:13:00' AND `age`=32 AND `gmt_create`='2019-09-24 17:13:00' AND `address`='山东省青岛市' AND `id`=1 LIMIT 1; #start 66374969 end 66375406 time 2019-10-21 15:38:49
DELETE FROM `test`.`employees` WHERE `name`='maofang' AND `gmt_modified`='2019-09-24 17:40:49' AND `age`=32 AND `gmt_create`='2019-09-24 17:32:00' AND `address`='山东省青岛市' AND `id`=2 LIMIT 1; #start 66374969 end 66375406 time 2019-10-21 15:38:49
DELETE FROM `test`.`employees` WHERE `name`='raohui' AND `gmt_modified`='2019-09-24 17:39:28' AND `age`=29 AND `gmt_create`='2019-09-24 17:39:28' AND `address`='陕西省西安市' AND `id`=3 LIMIT 1; #start 66374969 end 66375406 time 2019-10-21 15:38:49
DELETE FROM `test`.`employees` WHERE `name`='yangnan' AND `gmt_modified`='2019-09-24 17:39:52' AND `age`=22 AND `gmt_create`='2019-09-24 17:39:52' AND `address` IS NULL AND `id`=4 LIMIT 1; #start 66374969 end 66375406 time 2019-10-21 15:38:49
DELETE FROM `test`.`employees` WHERE `name`='yuzhiqiang' AND `gmt_modified`='2019-09-24 17:40:03' AND `age`=29 AND `gmt_create`='2019-09-24 17:40:03' AND `address` IS NULL AND `id`=5 LIMIT 1; #start 66374969 end 66375406 time 2019-10-21 15:38:49
  • 解析出回滚 SQL,并检查回滚 SQL 是否正确
1
2
3
4
5
6
7
$ python binlog2sql.py -h127.0.0.1 -P3306 -uroot -p'xx' -dtest -temployees --start-file='mysql-bin.000020' --start-pos=66374969 --end-pos=66375406 -B > rollback.sql

INSERT INTO `test`.`employees`(`name`, `gmt_modified`, `age`, `gmt_create`, `address`, `id`) VALUES ('yuzhiqiang', '2019-09-24 17:40:03', 29, '2019-09-24 17:40:03', NULL, 5); #start 66374969 end 66375406 time 2019-10-21 15:38:49
INSERT INTO `test`.`employees`(`name`, `gmt_modified`, `age`, `gmt_create`, `address`, `id`) VALUES ('yangnan', '2019-09-24 17:39:52', 22, '2019-09-24 17:39:52', NULL, 4); #start 66374969 end 66375406 time 2019-10-21 15:38:49
INSERT INTO `test`.`employees`(`name`, `gmt_modified`, `age`, `gmt_create`, `address`, `id`) VALUES ('raohui', '2019-09-24 17:39:28', 29, '2019-09-24 17:39:28', '陕西省西安市', 3); #start 66374969 end 66375406 time 2019-10-21 15:38:49
INSERT INTO `test`.`employees`(`name`, `gmt_modified`, `age`, `gmt_create`, `address`, `id`) VALUES ('maofang', '2019-09-24 17:40:49', 32, '2019-09-24 17:32:00', '山东省青岛市', 2); #start 66374969 end 66375406 time 2019-10-21 15:38:49
INSERT INTO `test`.`employees`(`name`, `gmt_modified`, `age`, `gmt_create`, `address`, `id`) VALUES ('xujinliang', '2019-09-24 17:13:00', 32, '2019-09-24 17:13:00', '山东省青岛市', 1); #start 66374969 end 66375406 time 2019-10-21 15:38:49

Tips:回滚条数可以使用 %s/pattern/&/g 进行统计,pattern 是要搜索的关键字。

  • 确认回滚 SQL 正确,执行回滚语句
1
2
3
4
5
6
7
8
9
10
11
12
13
$ mysql -h127.0.0.1 -P3306 -uroot -p'xx' < rollback.sql

mysql> select * from employees;
+----+------------+--------------------+-----+---------------------+---------------------+
| id | name | address | age | gmt_create | gmt_modified |
+----+------------+--------------------+-----+---------------------+---------------------+
| 1 | xujinliang | 山东省青岛市 | 32 | 2019-09-24 17:13:00 | 2019-09-24 17:13:00 |
| 2 | maofang | 山东省青岛市 | 32 | 2019-09-24 17:32:00 | 2019-09-24 17:40:49 |
| 3 | raohui | 陕西省西安市 | 29 | 2019-09-24 17:39:28 | 2019-09-24 17:39:28 |
| 4 | yangnan | NULL | 22 | 2019-09-24 17:39:52 | 2019-09-24 17:39:52 |
| 5 | yuzhiqiang | NULL | 29 | 2019-09-24 17:40:03 | 2019-09-24 17:40:03 |
+----+------------+--------------------+-----+---------------------+---------------------+
5 rows in set (0.00 sec)

工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 连接配置
-h host; -P port; -u user; -p password

# 解析模式
-B, --flashback # 生成回滚SQL
--start-file # 起始解析文件
--start-position/--start-pos # 起始解析位置
--stop-file/--end-file # 终止解析文件
--stop-position/--end-pos # 终止解析位置
--start-datetime # 起始解析时间
--stop-datetime # 终止解析时间,格式'%Y-%m-%d %H:%M:%S'
-d, --databases # 只解析目标DB的SQL,多个库用空格隔开
-t, --tables # 只解析目标表的SQL,多张表用空格隔开
--only-dml # 只解析DML,忽略DDL
--sql-type # 只解析指定类型,支持INSERT, UPDATE, DELETE,多个类型用空格隔开

注意事项

  • 还是先恢复再去面壁思过吧!
  • 手工执行 delete、update 语句前,先执行 selete 语句。
  • drop 或者 truncate 语句造成的误操作,通过备份来恢复。

MySQL · 修改数据库名

发表于 2019-10-21 | 更新于 2019-12-02 | 分类于 MySQL

背景

需求:将数据库 hrtrqu 修改 hrtrzq

方案:MySQL 没有 rename database 命令,只能变相修改表到目标库里的表来实现。

实践

1. 导出库数据

1
$ mysqldump  --single-transaction -S /data/mysql3308/mysql.sock -usre -p'xx' hrtrqu > hrtrqu.sql

2. 创建新库 hrtrzq

1
CREATE DATABASE IF NOT EXISTS hrtrzq default charset utf8 COLLATE utf8_general_ci;

3. 导入数据到新库

1
$ mysql -S /data/mysql3308/mysql.sock -usre -p'sre@@p$i' hrtrzq < hrtrqu.sql

MySQL · 快速删除大表

发表于 2019-10-21 | 更新于 2019-10-22 | 分类于 MySQL

背景

生产环境有一张日志表 schedule_task_error_log ,数据量超过 5000w,想通过 drop 删除但是速度很慢。

1
2
-rw-rw----. 1 mysql mysql 5.1K Jan  8  2018 schedule_task_error_log.frm
-rw-rw----. 1 mysql mysql 36G May 16 18:14 schedule_task_error_log.ibd

原理

前提:MySQL 开启了独立表空间,MySQL 5.6.7 之后默认开启。

1
2
3
4
5
6
MariaDB> show variables like 'innodb_file_per_table';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | ON |
+-----------------------+-------+

MySQL 在删除大表的时候为什么慢?

  • Buffer Pool 页面清除过程(拥有 InnoDB 全局锁)
  • 删除 ibd 磁盘文件过程

方案:利用了 Linux 中 硬链接 减少 DDL 时间,加快锁释放,来进行快速删除。

实践

1. 建立硬连接

1
2
3
4
5
6
$ ln schedule_task_error_log.ibd schedule_task_error_log.ibd.hdlk
-rw-rw----. 1 mysql mysql 5.1K Jan 8 2018 schedule_task_error_log.frm
-rw-rw----. 2 mysql mysql 36G May 16 18:14 schedule_task_error_log.ibd
-rw-rw----. 2 mysql mysql 36G May 16 18:14 schedule_task_error_log.ibd.hdlk
-rw-rw----. 1 mysql mysql 5.8K Mar 14 2018 user_operation_syslog.frm
-rw-rw----. 1 mysql mysql 272K Feb 13 2019 user_operation_syslog.ibd

2. drop table

再看物理文件的引用数变为 1,然后我们可以另外找时间手动删除物理文件。

1
2
3
4
5
6
MariaDB> drop table schedule_task_error_log;
Query OK, 0 rows affected (0.78 sec)

-rw-rw----. 1 mysql mysql 36G May 16 18:14 schedule_task_error_log.ibd.hdlk
-rw-rw----. 1 mysql mysql 5.8K Mar 14 2018 user_operation_syslog.frm
-rw-rw----. 1 mysql mysql 272K Feb 13 2019 user_operation_syslog.ibd

3. 删除物理文件

1
$ rm -rf schedule_task_error_log.ibd.hdlk

Redis 开发与运维笔记

发表于 2019-10-20 | 更新于 2021-03-25 | 分类于 Redis

简介

Redis (Remote Dictionary Server)远程字典服务,是一个开源的、C语言编写的高性能的 key-value 缓存数据库。它可以减轻数据库的压力,提升读取效率。

  • 性能极高,读的速度是 110000次/s,写的速度是 81000次/s 。
  • 丰富的数据类型,支持 Strings、Lists、Hashes、Sets 及 Ordered Sets 数据类型。
  • 原子,所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。
  • 丰富的特性,支持 publish/subscribe、通知、key 过期等等特性。

安装

1
2
3
4
5
6
7
8
9
10
11
$ cd /usr/local/src
$ wget http://download.redis.io/releases/redis-5.0.5.tar.gz
$ tar xzf redis-5.0.5.tar.gz
$ cd redis-5.0.5
$ make
$ cd /usr/local/bin
$ redis-server /usr/local/src/redis-5.0.5/redis.conf

$ ps -ef | grep redis
root 112021 1 0 15:02 ? 00:00:00 ./redis-server *:6379
root 112563 82349 0 15:04 pts/0 00:00:00 grep --color=auto redis

redis.conf 是默认的配置文件,可以根据需要使用自定义配置文件。

1
2
3
4
5
$ redis-cli
redis> set foo bar
OK
redis> get foo
"bar"

运维

redis

Percona Toolkit · 用户权限显示工具 pt-show-grants

发表于 2019-10-19 | 更新于 2019-10-22 | 分类于 Percona Toolkit

功能

显示 mysql.user 所有用户及权限

原理

  • 先查找所有 user 和 host
  • 然后逐个执行 show grants

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
$ pt-show-grants -u 'xx' -p 'xx' -S /tmp/mysql.sock

-- Grants dumped by pt-show-grants
-- Dumped from server Localhost via UNIX socket, MySQL 5.7.23-log at 2019-10-18 15:56:29
-- Grants for 'hdm'@'%'
CREATE USER IF NOT EXISTS 'hdm'@'%';
ALTER USER 'hdm'@'%' IDENTIFIED WITH 'mysql_native_password' AS '*14533888C6CA3952B3957903FF7E69469C7E3A2B' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK;
GRANT PROCESS, REPLICATION CLIENT, REPLICATION SLAVE, SELECT, SHOW DATABASES ON *.* TO 'hdm'@'%';

-- Grants for 'monitor'@'10.138.228.%'
CREATE USER IF NOT EXISTS 'monitor'@'10.138.228.%';
ALTER USER 'monitor'@'10.138.228.%' IDENTIFIED WITH 'mysql_native_password' AS '*67C7E9852A88EE023433F77C5C63AF9DD730667B' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK;
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'monitor'@'10.138.228.%';

Percona Toolkit · 索引分析工具 pt-index-usage

发表于 2019-10-19 | 更新于 2019-10-22 | 分类于 Percona Toolkit

功能

从日志当中分析索引的使用情况,检测多余的索引

原理

通过 EXPLAIN 慢查询日志中的 SQL,然后用执行计划和数据库中的索引做对比,看哪些索引没有被利用

使用

1
$ pt-index-usage /data/mysql/slow.log  -u 'xx' -p 'xx' -S /tmp/mysql.sock

Percona Toolkit · 复制异常修复工具 pt-slave-restart

发表于 2019-10-19 | 更新于 2019-11-05 | 分类于 Percona Toolkit

功能

pt-slave-restart:是一个修复由于不同的错误而意外终止 slave 复制的工具,和配置参数 slave_skip_errors 功能类似。

Warning:除非知道跳过操作的影响或后果,否则不要自动跳过任何错误,会影响数据一致性。

原理

它以指数变化的睡眠时间定期巡视检查 slave 复制状态,初始默认 1s,并试图跳过导致错误的语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Usage: pt-slave-restart [OPTIONS] [DSN]
Options:

--always Start slaves even when there is no error(不建议使用此参数)
--ask-pass Prompt for a password when connecting to MySQL
--charset=s -A Default character set
--[no]check-relay-log Check the last relay log file and position before
checking for slave errors (default yes)
--config=A Read this comma-separated list of config files; if
specified, this must be the first option on the
command line
--daemonize Fork to the background and detach from the shell
--database=s -D Database to use
--defaults-file=s -F Only read mysql options from the given file
--error-length=i Max length of error message to print
--error-numbers=h Only restart this comma-separated list of errors
--error-text=s Only restart errors that match this pattern
--help Show help and exit
--host=s -h Connect to host
--log=s Print all output to this file when daemonized
--master-uuid=s When using GTID, an empty transaction should be
created in order to skip it
--max-sleep=f Maximum sleep seconds (default 64)
--min-sleep=f The minimum time pt-slave-restart will sleep before
polling the slave again (default 0.015625)
--monitor Whether to monitor the slave (default)
--password=s -p Password to use when connecting
--pid=s Create the given PID file
--port=i -P Port number to use for connection
--quiet -q Suppresses normal output (disables --verbose)
--recurse=i Watch slaves of the specified server, up to the
specified number of servers deep in the hierarchy (
default 0)

使用

1
2
3
./pt-slave-restart -uroot -p'xx' --error-numbers=1062
2019-05-04T00:59:09 P=3306,h=x.x.x.x,p=...,u=root relay-bin.000005 369 1032
2019-05-04T00:59:20 P=3306,h=x.x.x.x,p=...,u=root relay-bin.000005 726 1032
1…111213…18
Hui Rao

Hui Rao

最好的成长是分享
173 日志
19 分类
14 标签
GitHub E-Mail
© 2021 Hui Rao
由 Hexo 强力驱动 v3.9.0
|
主题 – NexT.Gemini v7.1.0
|