MySQL利用 INFORMATION_SCHEMA.PROFILING 分析SQL性能

MySQL5.7中有一个系统默认库 information_schema , 里面有些表如 PROFILING,、OPTIMIZER_TRACE、 PROCESSLIST、INNODB_TRX等,其中 PROFILE 对于我们分析sql有很大的帮助,在此以前我们需要使用 SHOW PROFILE 命令,不过此命令以后将被废弃。下面我们就介绍一下如何使用此表。

从 MySQL8.0开始, 这个表也开始被废弃了,以后分析性能问题直接使用另一个系统库 performance_schema 里的相关表(setup_actors)就可以了。到时候 show profiles 和show profile两个命令也不能用了。

1.在使用此表前,我们需要开户性能检测功能。

mysql> SELECT @@profiling;
+-------------+
| @@profiling |
+-------------+
|           0 |
+-------------+
1 row in set (0.00 sec)

mysql> SET profiling = 1;
Query OK, 0 rows affected (0.00 sec)

默认情况下是 OFF/0 状态。在我们分析完,最好关闭以减少服务器压力。

相关查询命令

show VARIABLES like 'profil%'
-------------------------------
profiling	ON
profiling_history_size	15

2. 了解 information_schema.profiling 表的常用字段

官方文档:https://dev.mysql.com/doc/refman/8.0/en/profiling-table.html

1QUERY_ID 查询ID, 用于标记不同的查询
2SEQ 一个查询内部执行的步骤 , 从2开始
3STATE 步骤的状态
4DURATION 持续时间
5CPU_USER 用户空间的cpu 使用量
6CPU_SYSTEM 内核空间的cpu 使用量
7CONTEXT_VOLUNTARY上下文主动切换
8CONTEXT_INVOLUNTARY上下文被动切换
9BLOCK_OPS_IN阻塞输入操作
10BLOCK_OPS_OUT阻塞输出操作
11MESSAGES_SENT消息发送
12MESSAGES_RECEIVED消息接受
13PAGE_FAULTS_MAJOR主分页错误
14PAGE_FAULTS_MINOR次分页错误
15SWAPS swap 发生的次数
16SOURCE_FUNCTIONMySQL源码执行函数
17SOURCE_FILE源码文件
18SOURCE_LINE源码行数

以下是我执行了一个join语句的输出,从结果中我们可以分析出哪个步骤执行的时间最长,进行相应的优化即可。

我们可以根据DURATION 列的值来分析哪一个模块消耗的时间多来进行相应的优化。

docker中将MySQL运行在容器中失败提示“ InnoDB : Error 22 with aio_write”的解决办法

今天利用docker容器创建mysql8.0的时候(window系统),指定了本地宿主机器的一个目录为容器mysql的datadir目录,发现创建失败了。

创建命令:

$ docker run -d --name mysql81 -v /e/container/mysql/mysql81/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -p 33081:3306 mysql

错误提示:

$ docker logs mysql81
2019-01-26T03:05:42.567230Z 0 [Warning] [MY-011070] [Server] 'Disabling symbolic links using --skip-symbolic-links (or equivalent) is the default. Consider not using this option as it' is deprecated and will be removed in a future release.
2019-01-26T03:05:42.567618Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.13) starting as process 1
2019-01-26T03:05:42.572006Z 0 [Warning] [MY-010159] [Server] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
2019-01-26T03:05:42.832344Z 1 [ERROR] [MY-012592] [InnoDB] Operating system error number 22 in a file operation.
2019-01-26T03:05:42.832473Z 1 [ERROR] [MY-012596] [InnoDB] Error number 22 means 'Invalid argument'
2019-01-26T03:05:42.832556Z 1 [ERROR] [MY-012646] [InnoDB] File ./#innodb_temp/temp_1.ibt: 'aio write' returned OS error 122. Cannot continue operation
2019-01-26T03:05:42.832609Z 1 [ERROR] [MY-012981] [InnoDB] Cannot continue operation.

解决办法:

docker run -u 1000:50 -d --name mysql81 -v /e/container/mysql/mysql81/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -p 33081:3306 mysql --innodb-use-native-aio=0

参数:

-u 表示运行实例的用户,这里的 1000:50 表示的是docker这个用户
–innodb-use-native-aio=0 为MySQL的参数,作用是启用异步操作功能,提高MySQL性能

注意:
上面使用了docker运行了mysql实例,则如果进入到容器内部进行一些其它需要高级权限的操作的话,如apt update则会提示权限不足的情况。

参考:https://github.com/docker-library/mysql/issues/371

docker build . 命令后面的.是什么意思

今天来公司自己构建了一个Dockerfile,放在一个经常用到的项目目录里,内容如下:

# This is a comment
FROM ubuntu:14.04
MAINTAINER Docker Newbee <newbee@docker.com>
RUN apt-get -qq update
RUN apt-get -qqy install ruby ruby-dev
RUN gem install sinatra

然后执行

sudo docker build -t "cfanbo/test:v2" .

发现在构建的时候发送给 docker daemon 竟然有4G多,超极大。首先的第一反映出问题了。一个ubuntu镜像也没有这么大呀,况且现在还没有开始从远程pull 镜像呢。

那到底什么情况了呢?搜索了一下,原来在docker build . 的时候,会将当前目录里的内容发送给 docker daemon。只需要加一个 .dockerignore 文件,将其它内容排除掉就可以了,类似于git中的.gitignore文件的作用。

后面就想通过docker build -h 命令查看一下相关的参数,发现对于Dockerfile 文件位置需要 -f 参数指定,并非上面命令后面的.符号。那就有些疑惑了,原来学习的时候一直把.当作当前目录指定的。难道.有其它的作用,后面查看了一些文件,发现一直对 docker build 命令的过程不太了解。通过查找了一些资料才发现它的真正作用。

Docker 在运行时分为 Docker引擎(服务端守护进程) 以及 客户端工具,我们日常使用各种 docker 命令,其实就是在使用客户端工具与 Docker 引擎 进行交互。

那么当我们使用 docker build 命令来构建镜像时,这个构建过程其实是在 Docker引擎 中完成的,而不是在本机环境。

那么如果在 Dockerfile 中使用了一些 COPY 等指令来操作文件,如何让 Docker引擎 获取到这些文件呢?

这里就有了一个镜像构建上下文的概念,当构建的时候,由用户指定构建镜像的上下文路径,而 docker build 会将这个路径下所有的文件都打包上传给 Docker 引擎,引擎内将这些内容展开后,就能获取到所有指定上下文中的文件了(参考下方docker架构图)。

比如说 dockerfile 中的 COPY ./package.json /project,其实拷贝的并不是本机目录下的 package.json 文件,而是 docker引擎中展开的构建上下文中的文件,所以如果拷贝的文件超出了构建上下文的范围,Docker引擎是找不到那些文件的。


Docker构架

所以 docker build . 最后的 . 号,其实是在指定镜像构建过程中的上下文环境的目录。

理解了上面的这些概念,就更方便的去理解 .dockerignore 文件的作用了。

为验证.的作用,我们可以创建一个空的目录,在目录里执行

docker build -f /home/tom/Dockerfile . 

会发现命令完全正常执行。

python中的@staticmethod和@classmethod区别(整理)

问题:Python中 @staticmethod@classmethod 两种装饰器装饰的函数有什么不同?
原地址http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python


Python其实有3类方法:

  • 静态方法(staticmethod)
  • 类方法(classmethod)
  • 实例方法(instance method)

看一下下面的示例代码:

def foo(x):
    print "executing foo(%s)" %(x)

class A(object):
    def foo(self,x):
        print "executing foo(%s,%s)" %(self,x)

    @classmethod
    def class_foo(cls,x):
        print "executing class_foo(%s,%s)" %(cls,x)

    @staticmethod
    def static_foo(x):
        print "executing static_foo(%s)" %x

a = A()

在示例代码中,先理解下函数里面的 self 和 cls。这个 self 和 cls 是对类或者实例的绑定,对于一般的函数来说我们可以这么调用foo(x),这个函数就是最常用的,它的工作和任何东西(类、实例)无关。对于实例方法,我们知道在类里每次定义方法的时候都需要绑定这个实例,就是foo(self,x),为什么要这么做呢?因为实例方法的调用离不开实例,我们需要把实例自己传给函数,调用的时候是这样的a.foo(x)(其实是foo(a,x))。类方法一样,只不过它传递的是类而不是实例, 如A.class_foo(x)。注意这里的 self 和 cls 可以替换别的参数,但是python的约定是这两个,尽量不要更改。

对于静态方法其实和普通的方法一样,不需要对谁进行绑定,唯一的区别是调用时候需要使用a.static_foo(x)A.static_foo()来调用。

\实例方法类方法静态方法
a = A()a.foo(x)a.class_foo(x)a.static_foo(x)
A不可用A.class_foo(x)A.static_foo(x)

那么对于类方法和静态方法都可以不实例对象来调用,那两者的区别又有哪些呢?

从它们的使用上来看

  • @staticmethod 不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。
  • @classmethod 也不需要self参数,但第一个参数需要是表示自身类的cls参数。

如果在@staticmethod中要调用到这个类的一些属性方法,只能直接 类名.属性名类名.方法名

而@classmethod因为持有 cls 参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码。

代码:

class A(object):
    bar = 1
    def foo(self):
        print 'foo'
 
    @staticmethod
    def static_foo():
        print 'static_foo'
        print A.bar
 
    @classmethod
    def class_foo(cls):
        print 'class_foo'
        print cls.bar
        cls().foo()
 
A.static_foo()
A.class_foo()
输出
static_foo
1

class_foo
1
foo

摘自:
https://www.cnblogs.com/taceywong/p/5813166.html
https://blog.csdn.net/handsomekang/article/details/9615239

windows下更新docker源(aliyun)

每个aliyun账号都有一个专属的镜像源 https://cr.console.aliyun.com/cn-hangzhou/mirrors

我这里安装的是 Docker Toolbox 软件,更新docker源有两种情况,一种是你还没有创建过Docker Machine,另一种是你已经创建过了Docker Machine。

一、未安装过

创建一台安装有Docker环境的Linux虚拟机,指定机器名称为default,同时配置Docker加速器地址。

$ docker-machine create –engine-registry-mirror=https://xxxx.mirror.aliyuncs.com -d virtualbox default

查看机器的环境配置,并配置到本地。然后通过Docker客户端访问Docker服务。

$ docker-machine env default
$ eval “$(docker-machine env default)”
$ docker info

这里 xxxx 是您的专有加速器地址


二、已安装过

登录已创建的Docker VM
$ docker-machine ssh default
$ sudo vi /var/lib/boot2docker/profile

在EXTRA_ARGS中添加

–registry-mirror=https://xxxx.mirror.aliyuncs.com

EXTRA_ARGS='
--label provider=virtualbox
--registry-mirror=https://fgxrbz510.mirror.aliyuncs.com
'
CACERT=/var/lib/boot2docker/ca.pem
DOCKER_HOST='-H tcp://0.0.0.0:2376'
DOCKER_STORAGE=aufs
DOCKER_TLS=auto
SERVERKEY=/var/lib/boot2docker/server-key.pem
SERVERCERT=/var/lib/boot2docker/server.pem

export "NO_PROXY=192.168.99.100"

重启Docker服务

$ sudo /etc/init.d/docker restart

有时候会提示以下错误,可以忽略。如果在连接终端执行 docker info 提示服务未启动的话,可以尝试将虚拟机手动重启一下基本可以解决,我这里用的是virtualbox

Stopping dockerd (3590)
warning: ‘aufs’ is not a supported storage driver for this boot2docker install — ignoring request!

Stopping dockerd (3590)
warning: ‘aufs’ is not a supported storage driver for this boot2docker install — ignoring request!
see https://github.com/boot2docker/boot2docker/issues/1326 for more details
Starting dockerd

另外对于windows上使用Docker Toolbox (VirtualBox)的用户需要注意,当创建一个容器的时候,并指定了端口映射的时候,在宿主本机没有办法通过端口访问容器实例的。因为参数 -p 33065:3306 中的33065指的是VirtualBox中的端口,而非当前宿主机器的端口,此时如果用netstat查看的话,是看不到33065端口的。想访问容器,需要在宿主机器与VirtualBox之间再映射一个端口 33065:33065

至于原因吗,很好理解的,docker运行需要使用Linux内核,于是windows使用VirtualBox 搞了一个linux 虚拟机器,所以对于docer run 命令指定端口的时候,其实指定的是 linux服务器与容器的端口映射关系。

MySQL中group_concat函数详解

函数语法:

group_concat( [DISTINCT]  要连接的字段   [Order BY 排序字段 ASC/DESC]   [Separator ‘分隔符’] )


下面举例说明:

select * from goods;  

+——+——+
| id| price|
+——+——+
|1 | 10|
|1 | 20|
|1 | 20|
|2 | 20|
|3 | 200 |
|3 | 500 |
+——+——+
6 rows in set (0.00 sec)


  1. 以id分组,把price字段的值在同一行打印出来,逗号分隔(默认)

select id, group_concat(price) from goods group by id;  

+——+——————–+
| id| group_concat(price) |
+——+——————–+
|1 | 10,20,20|
|2 | 20 |
|3 | 200,500|
+——+——————–+
3 rows in set (0.00 sec)


2. 以id分组,把price字段的值在一行打印出来,分号分隔 
select id,group_concat(price separator ‘;’) from goods group by id;  

+——+———————————-+
| id| group_concat(price separator ‘;’) |
+——+———————————-+
|1 | 10;20;20 |
|2 | 20|
|3 | 200;500 |
+——+———————————-+
3 rows in set (0.00 sec)


3. 以id分组,把去除重复冗余的price字段的值打印在一行,逗号分隔
select id,group_concat(distinct price) from goods group by id;  

+——+—————————–+
| id| group_concat(distinct price) |
+——+—————————–+
|1 | 10,20|
|2 | 20 |
|3 | 200,500 |
+——+—————————–+
3 rows in set (0.00 sec)


4. 以id分组,把price字段的值打印在一行,逗号分隔,按照price倒序排列
select id,group_concat(price order by price desc) from goods group by id;  

+——+—————————————+
| id| group_concat(price order by price desc) |
+——+—————————————+
|1 | 20,20,10 |
|2 | 20|
|3 | 500,200|
+——+—————————————+
3 rows in set (0.00 sec)

MySQL中order by 排序必知

在开发过程时,我们经常会遇到 order by 排序操作,那么你知道什么时候MySQL才会进行排序操作,什么时候不需要时间排序操作?,下面我们就从一个很小的例子中了解一下排序场景。

表结构如下:

CREATE TABLE t (
id int(11) unsigned NOT NULL AUTO_INCREMENT,
city varchar(16) NOT NULL,
name varchar(16) NOT NULL,
age int(11) NOT NULL,
addr varchar(128) DEFAULT NULL,
PRIMARY KEY (id),
KEY city (city) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

这里只有一个索引,我们执行一条SQL语句:

SELECT city, name  FROM t WHERE city=’杭州’ ORDER BY name LIMIT 1000;

通过Explain命令查看执行情况

发现Extra字段里有”Using filesort”,说明使用了排序,而排序必用到了sort_buffer, 这是由数据库为了专门进行排序操作而分配的一块内存。
这里的Using index conditon是指ICP特性,请参考:https://blog.haohtml.com/archives/18201

下面我们专门来看一下这条语句的执行流程是如何的?在此以前我们需要了解一个概念,就是索引的特性是有序的,系统搜索时,一旦找到最后一条满足条件的记录后就立即停止,后面的记录则不再进行扫描,这样就可以用来解决全表扫描的性能问题。

Continue reading

mac下安装python web框架django

前提

由于mac自带的python2.7(路径 /usr/bin/python)
后来手动又安装了python3.7(/usr/local/bin/python3)

两个版本共存。为了方便,直接在.zshrc文件里做了别名映射

alias python="/usr/local/bin/python3.7"

所以直接使用命令python实际上用的是3.7版本。

按照官方教程 https://docs.djangoproject.com/zh-hans/2.1/intro/install/ 安装django。发现在使用命令 pip install django 安装后发现检测不到django,很奇怪,后来发现了问题所在。

➜  ~ python
Python 3.7.1 (default, Nov  6 2018, 18:46:03)
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
Traceback (most recent call last):
  File "", line 1, in 
ModuleNotFoundError: No module named 'django'

原来python2对应一个是包安装命令是 pip,而python3对应的是一个叫做pip3的命令。所以使用新的命令

pip3 install django

安装成功。

➜  ~ python
Python 3.7.1 (default, Nov  6 2018, 18:46:03)
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> print(django.get_version())
2.1.3