MySQL数据库再回首

前言:

数据库是程序员的数据源泉,加上近期 要开发DB可视化、性能分析的功能 重新回顾一下MySQL知识,以下是笔记;

 

 

MySQL架构

 

 

 

 

MySQL基础理论

 

1.什么是关系型数据库?

关系型数据库,这个关系怎么讲呢?简单来说关系就是 通过行、列组成一张二维表 把所有数据关联、表现出来;

列:从不同方面描述1类实体数据的属性;

行:1行=1条实体数据;

 

2.为什么要使用数据库管理系统(DBMS)?

 

如果我们的数据只是像/etc/password/这样大小的一个文件,我们使用文本文件存储数据是完全没有问题的;
但是使用文件的方式存储数据有下列缺陷:

数据冗余

无法简单描述数据之间的关联性(外键、多对多、1对1)在文件中实现起来困难

文本文件无法保存数值数据(浮点、整型)丢失精度、无法计算

最重要的是 当文件中数据每人剧增变得异常庞大的时候,我们从中查找符合条件的内容将会变得异常困难;

比如:/etc/password这个文件变成100G的时候,我们从中查找出 …^r的用户,怎么查找?。

也许你会想到使用grep/egrep命令去查找,是的我能找到没有任何问题;

但是在100G的文件中寻找符合条件的行会遇到以下问题:

grep/egrep也是程序 如果想要 查询 就需要把100G的文件载入内容,需要多大的内存?,即便有这么大的内存会产生多大IO?花销多大时间?

 

于以上内容使用一个简单的文件来存储数据,只能 在早期 满足1个简单数据模型的应用程序;

 

 

3.什么是搜素引擎?

如果1个python程序使用文件来保存数据,数据都存储在硬盘上,python和数据打交道的接口是什么?文件系统的系统调用接口;

文件存储在硬盘上,我们通过系统调用调用到的数据都是数据流(只不过通过文件系统抽象之后才表现为文件)如果和文件数据流打交道这就意味着你的python程序就需要维护文件句柄、内容指针(读到第几行了?)、何时关闭文件、关闭之前清理缓冲区....管理;

 

我们都知道文件系统把数据放在磁盘的某1个块上的,假如说这个python程序想要访问某1数据块,python也需要将这个文件的所有内容载入到内存中才能访问的;

为什么是所有文件内容?因程序本身无法界定符合条件的内容到底存储在 哪个数据块上?

于是在文件系统之上又封装了一层管理功能,这个管理工具向下可以和文件系统打交道,将N个文件系统的块 组织成1个更高级别的逻辑存储块。

划分出这些逻辑块之后,就可以知道那些数据存储在哪个数据块上并记录下来;所以比如当我们查询/etc/password的1-5行时就可以载入部分数据块了;因为现在已经知道了那些数据在哪个数据块上,无需在访问部分数据时加载全部文件的数据块了;

 

但是还有1个问题 如果 我们要查询 /etc/password 以^r开头的用户

那么就会出现1个问题即使你知道 某1行数据在哪1数据块?但也需要载入全部数据块(如果1个数据块对应1行数据)去每个块上找1下;

所以我们可以把一些搜素条件单独组合成搜素码,单独存储在1个数据块上,这样用户搜素的时候就可以只载入1个数据块而不是全部了!

如果 我们要查询 /etc/password 以^r开头的用户所有信息包含家目录、登录shell

所以我们不仅要把搜素码单独存储起来,还有存储它相关信息所在搜素块的映射关系;这就是索引

 

 

索引分级:

如果把所有搜素条件都做成搜素块(索引)那么数据库每次启动加载所有所有索引信息也是非常慢慢的,索引也需要分级;

 

数据库缓冲区:

加载索引 、经常访问的数据到内存加速用户访问速度;

 

搜素引擎:

以上内容 将数据从1个物理模型转换成数据库能理解的数据库模型、根据上层程序调用不加载全部数据块而非全部数据的 就是数据库引擎;

读锁:共享锁

写锁:独占锁

 

 

httpMPM

multi-processing  module  并发响应模型

http支持三种方式解决并发问题:

prefork:1个进程处理1个请求

worker:多个进程处理1个请求

event:1个线程处理多个请求(IO多路复用 + 协程)时间通知回调 协程切换

 

mysq并发:1个线程响应1个用户请求;

为啥不用1个线程处理多个数据库用户呢?1的用户的请求处理逻辑复杂开发难度比较大;

 

4.为什么要用mysql线程池?

因为mysql的线程比较重量级,在大并发的场景下线程的创建、释放、销毁都需要一定时间,所以为了最大限度复用线程就有了进程池,用户使用完线程之后清除该用户的数据但不销毁而是把该线程回收到线程池中,留个下1个用户继续使用;

还有1点就是可以限制并发的数量;

 

5.sql语句分类

DML:对数据库数据数据的操作Insert、Update、Delete、Select

DDL:对数据库对象(表、视图、索引、存储过程、存储函数)创建、删除、修改操作;Create Drop Al

Alter

DCL:Grant、Revoke 用户授权和回收权限

 

6.事物是什么?

一组DML就是一个事物,它具有以下特性:

原子性:一组DML(多条增、删、改、查的sql语句)要么都执行,要么都不执行;(当做1个整体来管理)

一致性:事物操作数据总量保存不变A向B转账100, A的账户少了100,B的账户就要加100,就这么简单;

隔离性:隔离多个事物,避免多个事物同时进行;

隔离级别

读未提交

读提交

可重读

可串行化

持久性:事物的数据一旦提交之后不能丢失,中间出现问题可以回滚;通过事物日志来保证;

 

 

7.Mysql的日志类型

错误日志

查询日志

慢查询日志

事物日志

二进制日志

中间日志

 

 

8.DBA职责

设计表结构、安全性和授权、保障数据库可用性、故障恢复、数据库调优

 

 

 

二、关系型数据库索引、数据库文件的组织方式

1.mysql的数据类型 CHAR(定长)和VARVHAR(变长)

CHAR数据类型的长度是固定的,VARCHAR数据类型的长度是可变、非固定的,

变长:VARCHAR(20)  存储root字符串占用数据库5字节空间, 优势:节省空间、其长度可变占用空间可扩展;应用在数据最大和最小长度相差太大的场景;

定长:CHAR(20)        存储root字符串占用数据库20字节空间,优势:方便搜素引擎存储、索引查找,数据最大和最小长度相差不太大的场景都要尽量使用CHAR类型;

 

2.数据库文件

数据文件:堆文件(组织无序)、有序文件(组织有序)、散列组织(hash函数+hash桶)

索引文件:有序索引文件、无序索引文件

日志文件:存储搜素引擎的操作记录,便于追溯、恢复数据;

 

3.数据库索引

聚簇索引

搜索引擎 把数据 存储在索引上所指向数据库块位置,如果索引本身有序,数据记录也是有序的,这种索引就是聚簇索引,按这种方式组织的数据库文件也叫有序数据、聚簇文件;(有序文件+有序索引文件+存储在一起)

 

非聚簇索引

与相反如果索引本身无序 于是数据记录就是无序的,或者索引有序、数据记录无序 这种索引就是非聚簇索引,按这种方式组织的数据库文件也叫无序数据、堆文件;

 

非聚簇索引包含散列(hash)索引

如果散列文件组织就使用hash算法去存储和查找;注意hash算法的时间复杂度=o(1),但不适合范围查找;因为即使数据会被hash算法随机分配到不同的hash桶里;

 

小结

索引和数据库文件结构关联性很大

 一般树状结构索引都是有序的称为聚簇索引,辅助索引、hansh索引无序称为非聚簇索引。

 

4. 两大引擎存储数据库、索引文件的特征

每张表都有3个文件;

MyISM: 数据文件=表名.MYD,索引文件=表名.MYI ,表定义文件=表名.frm

InnoDB:

每张表的所有数据都放在表空间中(ibdata),表空间可以被多个位于不同数据库的表共享;

定义文件在数据库目录中;

 

5.MySQL数据字典

保存数据库的元数据

关系的名字

张表中各列的名字

每列的数据类型和长度

每张表上的视图名称

 

授权用户的名字

用户授权和账户信息

以上信息存储在mysql库;

 

统计类数据

每个库中属性的个数

每个表中行的个数

每个关系的存储组织方法

infomation_schema存储统计类信息;

 

Mysql安装自带以下3个库就是用来存储数据字典信息的;

mysql库:账号授权

information_schema库:统计类信息

performance_schema 库:存储性能相关信息

总结:^_^ 有了以上自带的3个库仿佛看到了DB可视化功能的大门~~~~

import pymysql
db = pymysql.connect("172.17.10.112", "webproject", "xxxxxx1234","web")
cursor = db.cursor()
cursor.execute(" show variables like 'max_connections';") #查当前登录用户声明的变量
cursor.execute(" show global variables")                    #查当前全局声明的变量
cursor.execute("show status like '%Threads_connected%'") #查看MySQL运行状态 https://www.cnblogs.com/zuxing/articles/7761262.html
print(cursor.fetchall())
# 关闭数据库连接
db.close()
在线查看部分信息

 

三、安装MySQL 

主要描述基于centos7 64位系统源码安装MySQL5.6.19

为啥不使用 yum安装呢?因为下载MySQL源码编译时可以指定参数定制出适合自己企业数据库

 

1.MySQL官网下载源码

Archive 存档档案文件;档案室;如果想下载之前的版本;

 

 Community Server 社区版服务端下载 

 

 

 

Archives 存档  Generic通用 Community 共同体 社区  Poor me ....So I need to learning English and take notes.

 

四、编译安装MySQL源码

1.卸载原MySQL、准备C语言编译环境

确保本机没有安装Maria或者MySQL之后再安装

rpm -qa | grep mysq
rpm -e --nodeps xx
find / -name mysql
rm -rf 
yum -y install gcc gcc-c++ ncurses ncurses-devel bison cmake make

创建MySQL用户、组

useradd -M -s /sbin/nologin mysql

创建存放MySQL源码的目录

mkdir /opt/

 

2.创建MySQL的源目录、数据存储目录并赋予权限

mkdir /usr/local/mysql/         #/usr/local/mysql/
mkdir /usr/local/mysql/data     #/usr/local/mysql/data
mkdir /usr/local/boost          #/usr/local/boost
chown -R mysql:mysql /usr/local/mysql/*

 

3.编译安装

tar -zxvf mysql-5.6.19-linux-glibc2.5-x86_64 -C /opt/
cd /opt/mysql-5.6.19-linux-glibc2.5-x86_64/
 参数说明:
    -DCMAKE_INSTALL_PREFIX=/usr/local/mysql        -----   安装目录  这是MySQL的默认安装位置,而我选择的是/u01/mysql ,我觉得这样管理方便,清晰
    -DINSTALL_DATADIR=/usr/local/mysql/data        -----   数据库存放目录
    -DDEFAULT_CHARSET=utf8                      -----   使用utf8字符
    -DDEFAULT_COLLATION=utf8_general_ci            -----    校验字符
    -DEXTRA_CHARSETS=all                        -----    安装所有扩展字符集
    -DENABLED_LOCAL_INFILE=1                     -----    允许从本地导入数据
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/usr/local/mysql/data -DSYSCONFDIR=/etc -DWITH_MYISAM_STORAGE_ENGINE=1 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_MEMORY_STORAGE_ENGINE=1 -DWITH_READLINE=1 -DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock -DMYSQL_TCP_PORT=3306 -DENABLED_LOCAL_INFILE=1 -DWITH_PARTITION_STORAGE_ENGINE=1 -DEXTRA_CHARSETS=all -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci

编译成功之后就可以安装MySQL了;

make install  

在保证下载的是 MySQLSourceCode的情况下,哪里报错就去网上搜解决方案直到你的Linux具备编译、安装环境

 

数据库目录相关文件说明

[root@localhost data]# ls -lh
total 109M
-rw-rw----. 1 mysql mysql   56 Nov 29 17:17 auto.cnf
-rw-rw----. 1 mysql mysql  12M Nov 30 09:55 ibdata1          #innodb公共表空间文件:存储个表的数据内容和索引内容。
-rw-rw----. 1 mysql mysql  48M Nov 30 09:55 ib_logfile0      #事物日志
-rw-rw----. 1 mysql mysql  48M Nov 29 17:00 ib_logfile1      #事物日志
-rw-r-----. 1 mysql root  7.6K Nov 30 09:59 localhost.localdomain.err  #当前主机主机名+err结尾错误日志
-rw-rw----. 1 mysql mysql    7 Nov 30 09:55 localhost.localdomain.pid  #+err结尾错误日志
drwx------. 2 mysql mysql 4.0K Nov 29 17:00 mysql drwx------.  #MySQL有几个库就会有几个以数据库命名的文件

2 mysql mysql 4.0K Nov 29 17:02 performance_schema drwxr-xr-x.
2 mysql mysql 20 Nov 29 16:41 test

 

 

4.初始化数据库 启动MySQL服务

声明系统变量就可以 直接 使用mysql 命令进入数据了

export PATH=/usr/local/mysql/bin:$PATH
/etc/profile.d/mysql.sh
source /etc/profile.d/mysql.sh 
cd /usr/local/mysql
./scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data #初始化数据
[mysqld]
port=3306
basedir=/usr/local/mysql/
datadir=/usr/local/mysql/data
socket=/usr/local/mysql/mysql.sock

!includedir /etc/my.cnf.d
/etc/my.conf

 

删除匿名和其他无关用户

mysql> select user,host,password from user;
+----------+-----------------------+-------------------------------------------+
| user     | host                  | password                                  |
+----------+-----------------------+-------------------------------------------+
| root     | localhost             | *AC241830FFDDC8943AB31CBD47D758E79F7953EA |
| root     | localhost.localdomain |                                           |
| root     | 127.0.0.1             |                                           |
| root     | ::1                   |                                           |
| zhanggen | %.%.%.%               | *AC241830FFDDC8943AB31CBD47D758E79F7953EA |
| zhenggen | %.%.%.%               |                                           |
| zhanggen | %                     | *AC241830FFDDC8943AB31CBD47D758E79F7953EA |
| martin   | %                     | *AC241830FFDDC8943AB31CBD47D758E79F7953EA |
+----------+-----------------------+-------------------------------------------+
8 rows in set (0.01 sec)
mysql> delete from mysql.user where user='';
Query OK, 0 rows affected (0.03 sec)
mysql> drop user root@'::1';

 

 

启动MySQL

[root@localhost zhanggen]# /usr/local/mysql/support-files/mysql.server restart
Shutting down MySQL... SUCCESS! 
Starting MySQL... SUCCESS! 

 进入MySQL

[root@localhost /]# /usr/local/mysql/bin/mysql mysql

 

5.设置创建开发用户设置密码并授权

修改root密码

mysql> set password for root@localhost = password('123'); 
Query OK, 0 rows affected (0.00 sec)

增加开发用户并授权

mysql>  create user 'martin'@'%' identified by '123.com';
Query OK, 0 rows affected (0.00 sec)

mysql> grant all privileges  on *.* to 'martin'@'%';    
Query OK, 0 rows affected (0.01 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

 

6.MySQL忘记root密码怎么办?

在配置文件中追加2行参数:

skip-grant-tables   #运行本机无密码访问
skip-networking     #不允许通过scoket访问,注意一点要加上否则可以从外网无密码连接数据库;

 

7.python自动化批量源码安装脚本

需要稍加改造~

import paramiko
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh._policy = paramiko.AutoAddPolicy()
# print(host,port,username,password)
ssh.connect(hostname='192.168.226.139',port=22, username='root', password='123.com')
stdin,stdout,stderr = ssh.exec_command('rpm -qa | grep mysql')
result = stdout.read().decode('utf-8')

mysql_rpm_list=result.split('\n')
if mysql_rpm_list:
    for rpm in mysql_rpm_list:
        ssh.exec_command('rpm -e --nodeps %s' % (rpm))

stdin,stdout,stderr=ssh.exec_command('find / -name mysql')
result = stdout.read().decode('utf-8')
mysql_path_list=result.split('\n')
if mysql_path_list:
    for path in mysql_path_list:
        ssh.exec_command('rm -rf %s'%(path))

ssh.exec_command('yum -y install gcc gcc-c++ ncurses ncurses-devel bison cmake make')
ssh.exec_command('useradd -M -s /sbin/nologin mysql') # //创建用户mysql,不创建家目录,不允许登陆系统
ssh.exec_command('mkdir /opt/')
ssh.exec_command('mkdir /usr/local/mysql/ ') #/usr/local/mysql/
ssh.exec_command('mkdir /usr/local/mysql/data ')  #/usr/local/mysql/data
ssh.exec_command('mkdir /usr/local/boost')        #/usr/local/boost
ssh.exec_command('chown -R mysql:mysql /usr/local/mysql/*')
# transport = paramiko.Transport(('192.168.226.139', 22))
# transport.connect(username='root', password='123.com')
# sftp = paramiko.SFTPClient.from_transport(transport)
# sftp.put('/opt/mysql-5.6.19-linux-glibc2.5-x86_64', '/opt/mysql-5.6.19-linux-glibc2.5-x86_64')
ssh.exec_command('cd /opt/mysql-5.6.19-linux-glibc2.5-x86_64/')
make='cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/usr/local/mysql/data -DSYSCONFDIR=/etc -DWITH_MYISAM_STORAGE_ENGINE=1 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_MEMORY_STORAGE_ENGINE=1 -DWITH_READLINE=1 -DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock -DMYSQL_TCP_PORT=3306 -DENABLED_LOCAL_INFILE=1 -DWITH_PARTITION_STORAGE_ENGINE=1 -DEXTRA_CHARSETS=all -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci'
ssh.exec_command(make)
ssh.exec_command('make install')
ssh.exec_command('cd /usr/local/mysql')
ssh.exec_command('./scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data')
#vim /etc/my.conf  [mysqld]
'''
port=3306
basedir=/usr/local/mysql/
datadir=/usr/local/mysql/data
socket=/usr/local/mysql/mysql.sock

'''

#cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
#basedir='/usr/local/mysql/'  datadir='/usr/local/mysql/data'
#/etc/init.d/mysqld start
ssh.close()


import pymysql
db = pymysql.connect("192.168.226.139", "martin", "123.com","mysql")
cursor = db.cursor()
cursor.execute(" show variables like 'max_connections';") #查当前登录用户声明的变量
cursor.execute(" show global variables")                    #查当前全局声明的变量
cursor.execute("show status like '%Threads_connected%'") #查看MySQL运行状态 https://www.cnblogs.com/zuxing/articles/7761262.html
print(cursor.fetchall())
# 关闭数据库连接
db.close()
python源码安装mysql

 

 

五、MySQL的变量

 不管是show variables 还是 show status 都区分全局还是会话级别;

session级别:会话级别的所有设置仅仅对当前会话生效,该会话结束会复原;

mysql> set default_storage_engine=myisam;
Query OK, 0 rows affected (0.08 sec)

mysql> show global variables like '%engin%';
+----------------------------+--------+
| Variable_name              | Value  |
+----------------------------+--------+
| default_storage_engine     | InnoDB |
| default_tmp_storage_engine | InnoDB |
| storage_engine             | InnoDB |
+----------------------------+--------+
3 rows in set (0.01 sec)

mysql> show variables like '%engin%';
+----------------------------+--------+
| Variable_name              | Value  |
+----------------------------+--------+
| default_storage_engine     | MyISAM |
| default_tmp_storage_engine | InnoDB |
| storage_engine             | MyISAM |
+----------------------------+--------+

 

global级别:全局级别所有设置对所有会话生效,但是需要有root权限、对当前会话无效,退出该会话才能生效,MySQL重启之后复原;

mysql> set global default_storage_engine=innodb;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%engin%';
+----------------------------+--------+
| Variable_name              | Value  |
+----------------------------+--------+
| default_storage_engine     | MyISAM |
| default_tmp_storage_engine | InnoDB |
| storage_engine             | MyISAM |
+----------------------------+--------+
3 rows in set (0.00 sec)

 

 

 查看

mysql> show variables like '%variables_name%';
mysql> select @@variables_name;

设置

set variables_name=value;
set global variables_name=value

 

 

1. 系统变量 show variables

MySQL内部声明了443个系统变量,通过show variables;查看 通过set 这些变量对MySQL的性能进行优化;

innodb_adaptive_flushing={ON|OFF}

设定是否允许MySQL服务器根据工作负载动态调整刷写InnoDB buffer pool中的脏页的速率。动态调整刷写速率的目的在于避免出现IO活动尖峰。默认值为ON。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_adaptive_hash_index={ON|OFF}
设定是否启用InnoDB的自适应hash索引。基准测试结果显示,自适应hash索引并非对所有工作负载都有益,因此需要根据实际应用场景的测试结果选择更合适的值。此特性默认已启用,可以通过命令行选项--skip-innodb_adaptive_hash_index将其禁用。作用范围是全局,可用于选项文件,属动态变量。
 
innodb_additional_mem_pool_size={2097152 .. 4294967295}
设定innodb存储引擎为了存储数据字典和其它内部数据结构的内在池大小,单位是字节。表的个数越多,此参数的值就应该设定的越大;当InnoDB用完此内存池的空间,它就会向操作系统申请内存空间,并将向错误日志记录警告信息。默认大小是8MB。作用范围为全局,可用于选项文件,属非动态变量。
 
innodb_autoextend_increment={1 .. 1000}
当共享表空间没有多余的存储空间时,如果其允许自动增长,此变量可用于设定其单次增长的空间大小,单位是MB,默认值是8。设置了变量innodb_file_per_table的值为1时InnoDB会为每张表使用一个单独的表空间文件,而innodb_autoextend_increment变量不会对此种表空间产生影响。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_autoinc_lock_mode={0|1|2}
设定用于生成“自动增长(auto_increment字段)”值的锁模型。其可接受的值有0、1和2,分别用于表示"traditional"、"consecutive"和"interleaved"锁模型。默认值为1。作用范围为全局,可用于选项文件,属非动态变量。
 
innodb_buffer_pool_instances=#
设定将InnoDB的buffer pool分隔为多少个区域。对于有着数GB空间的buffer pool来说,将其分隔为多个区域可以降低不同的线程对缓存页面的读写操作时资源争用系数,进行增强其并发能力。在buffer pool中,读取或存入页面时所选择的区域是基于hash算法随机进行的。每个buffer pool管理自己的空闲列表、列表刷写、LRU以及其它跟buffer pool相关的数据结构,并通过各自的互斥锁进行保护。
此变量仅在变量innodb_buffer_pool_size的值大于1G时才能发挥功用,缓冲池的整体空间将由各buffer pool实例分割使用。出于最佳效用的目的,建议配合使用innodb_buffer_pool_instances和innodb_buffer_pool_size变量以使得每个buffer pool实例的都至少有1G的空间。作用范围为全局,可用于选项文件,属非动态变量。
 
innodb_buffer_pool_size=#
设定InnoDB缓存表数据和索引的内存缓冲区大小,单位是字节。其默认值为128MB,最大值依赖于CPU架构。在一个较繁忙的服务器上,当缓冲池(buffer pool)大于1G时,设定innodb_buffer_pool_instances的值大于1可提其升伸缩能力。innodb_buffer_pool_size变量的值越大,MySQL服务器完成数据访问时就需要越少的IO,因此,在一个有够较大内存且为MySQL服务专用的服务器上,可以将此值设置为物理内存的80%。但如果出现如下情况,建议缩小此变量的值:(1)物理内存资源紧张导致内存页面换出;(2)InnoDB会为缓冲和控制结构(buffers and control structures)预留额外的内存,因此事实上其占用的内存空间可能会比指定的数值大10%左右,这不可能超出对内存资源分配的预估;(3)内存地址空间必须连续,这在基于DLL库使用特殊地址空间的Windows系统上可能会出现意外情况;(4)缓冲池的初始化所需要时长与为其指定的空间大小成正比,例如有10G缓冲池的x86_64的Linux系统上,初始化时间大约要6秒钟。作用范围为全局,可用于选项文件,属非动态变量。
 
innodb_change_buffering=#
当在表上执行INSERT、UPDATE或DELETE操作时,索引中尤其是第二索引中的数据未必按序存储,这就可能引发随机IO以完成第二索引的更新操作。此变量用来设定InnoDB是否启用修改缓冲(change buffering)以及使用何种类型的修改缓冲。修改缓冲是一种优化方式,它能够通过延迟写入操作至第二索引将IO操作转换为顺序模式。其接受的值有inserts(缓冲insert操作)、deletes(缓冲delete-marking操作)、changes(缓冲insert和delete-marking操作)、purges(缓冲purge操作)、all(缓冲insert、delete-marking和purge操作)和none(不缓冲任何操作)。默认值是all。MySQL 5.5.4之前的版本只接受inserts和none两种值。作用范围为全局,可用于选项文件,属动态变量。
 
innodb_checksums={ON|OFF}
InnoDB能够使用校验和(checksum)来验正从磁盘读取的所有页面数据的完整性,从而提高对硬件或数据文件损坏的容错能力。默认为启用,然而,在少数情况下或许需要禁用这种特性,这可以通过使用--skip-innodb-checksums命令行选项实现。作用范围为全局,可用于选项文件,属非动态变量。
 
innodb_commit_concurrency={0 .. 1000}
设定InnoDB可同时运行的“提交”操作线程的数量。0表示无限制。此变量不能在运行时将其从“零值”修改为“非零值”,但可以从一个“非零值”修改为其它值。作用范围为全局,可用于选项文件,属非动态变量。
 
innodb_concurrency_tickets=#
在一个线程进入(enter)InnoDB时,其将会获取一定数量的“自由卷轴”(free tickets)并凭这些卷轴自由出入InnoDB(即免检),直到其卷轴耗尽;而后的线程将被置于等待队列中,并可能需要再次接受并发上限限制检查。此变量则正是用于设定可同时进入InnoDB的线程并发数,即线程的“自由卷轴”数量。默认值是500。作用范围为全局,可用于选项文件,属动态变量。
 
innodb_data_file_path=IBDATA_FILE
指定InnoDB的各个数据文件及其大小,文件多于一个时彼此间用分号隔开。数据文件路径可以为相对路径,其相对于innodb_data_home_dir变量所指向的目录;而文件大小的表示可以以K(KB)、M(MB)、G(GB)为单位,但这些文件的大小之和至少要达到10MB。在没有显式设定innodb_data_file_path变量的情况下,MySQL服务器会在数据目录中自动创建一个可自动增长、初始大小为10MB的名为ibdata1的数据文件。单个数据文件的大小上限取决于操作系统,这意味着可以使用操作系统所支持的最大单个文件大小以为其数据文件的体积上限。InnoDB还支持使用裸设备作为数据文件。作用范围为全局,可用于选项文件,属非动态变量。
 
innodb_data_home_dir=/PATH/TO/DIR
InnoDB所有共享表空间数据文件的目录路径。默认值为MySQL的数据目录。可以将此变量的值设置为空,然后在innodb_data_file_path中为每个数据文件使用绝对路径。此变量不影响变量innodb_file_per_table启用状态下的每表表空间的数据文件。作用范围为全局,可用于选项文件,属非动态变量。
 
innodb_doublewirte={ON|OFF}
设定InnoDB是否使用双写缓冲。默认为启用。InnoDB在对页面进行部分写入的时候使用双写缓冲,以防止数据损坏。双写缓冲是表空间中一个特殊的保留区域,其大小足够在一个连续区间容纳100个页面。当InnoDB把页面从缓冲池刷写至磁盘时,它会先把这些页面刷到双写缓冲中,然后再保存至真正的目标位置。因此,双写缓冲本质上是最近写入页面的备份,其可确保每次写入的原子性和可持续性。在有些情况下双写缓冲是不必要的,例如在从服务器上就可以将之禁用;此外,一些文件系统(如ZFS)自身也会实现此功能,那么InnoDB就不用做重复的工作了。作用范围为全局,可用于选项文件,属非动态变量。
 
innodb_fast_shutdown={0|1|2}
设定InnoDB关闭模式。其可接受的值中,“0”表示慢速关闭,这意味着InnoDB关闭之前会完成完全清写(full purge)和修改缓冲合并(insert buffer merge)操作;“1”是默认值,它表示InnoDB在关闭时会跳过模式0中进行的这些操作,这也是其之所以称作“快速关闭”的原因;“2”表示InnoDB仅刷写日志信息并执行冷(cold)关闭,此时并没有事务丢失,只是下次启动MySQL服务时需要花费较长的时间进行故障恢复(crash recovery)。
执行慢速关闭时其过程可能会持续数分钟的时间,甚至在有些极端情况下,比如有着大量数据缓冲的场景,此过程时长会以小时来计。一般情况下仅在对MySQL进行主版本升级时才需要进行慢速关闭以使得数据文件能够为完全适应新版本而准备妥当。通常也只能遇到紧急状况或出于调试的目的才需要将此变量的值设定为2,以便让处于有可能损坏风险中的数据执行最快速度的关闭。作用范围为全局,可用于选项文件,属动态变量。
 
innodb_file_format={Antelope|Barracuda}
设定新建InnoDB表的文件格式。其可接受的参数有Antelope和Barracuda,但这仅对基于变量innodb_file_per_file的每表表空间文件有影响。某些InnoDB特性如表压缩功能仅有Barracuda文件格式支持。作用范围为全局,可用于选项文件,属动态变量。
 
innodb_file_format_check={ON|OFF}
用于设定InnoDB是否在MySQL服务器启动时检查共享表空间的文件格式标签。检查标签时如果其高于当前InnoDB版本所支持的能力,InnoDB就会产生错误并拒绝启动;否则,对MySQL 5.5.5 及后来的版本来说InnoDB则会设置变量innodb_file_format_max的值为共享表空间的文件格式标签,而对于MySQL 5.5.5之前的版本来说,InnoDB会将共享表空间的文件格式设置为变量innodb_file_format_check的值。作用范围为全局,可用于选项文件,属非动态变量。
 
innodb_file_format_max={Antelope|Barracuda}
在MySQL服务启动时,InnoDB会将变量innodb_file_format_max的值设置为共享表空间的文件格式标签(比如,Antelope或Barracuda)。如果MySQL服务器创建或打开了一个有着更高级格式的表,此变量的值则会被设置为那个更高级的格式。作用范围为全局,可用于选项文件,属动态变量。
 
innodb_file_per_table={ON|OFF}
设定InnoDB表是否使用每表表空间数据文件(以.ibd结尾)分别存储每个表的数据和索引。如果使用了每表表空间数据文件,其将不再使用系统表空间(即共享表空间)。InnoDB表的某些特性,如压缩表等仅对每表表空间生效。作用范围为全局,可用于选项文件,属动态变量。
 
innodb_flush_log_at_trx_commit={0|1|2}
设定InnoDB同步日志缓冲区(log buffer)数据至日志文件中的方式,以及刷写日志文件至磁盘的方式。其可接受的值中,“0”表示将日志缓冲区每秒一次地写入日志文件,并同时将日志文件刷写至磁盘中,但事务提交时不会采取任何动作;“1”是默认值,表示在有事务提交时将日志缓冲区写入日志文件,并同时将日志文件刷写至磁盘;“2”表示每事务提交或每秒一次将日志缓冲区写入日志文件,但不会同时执行日志文件的刷写操作。当然,由于操作系统进程调度的原因,每秒一次的日志写入或刷写操作并不能得到100%的保证。
完全兼容ACID的场景需要将此变量值设置为1,由于要执行每事务的日志刷写操作,其会阻止I/O调用,直到写操作完成,故其会显著降低InnoDB每秒钟可以提交的事务数。设置为“2”可获得比“1”更好的性能,而且仅在操作系统崩溃时才会丢失最后一秒钟的数据,因此数据安全性也有着不错的表现。设置为“0”则有可能会导致事务最后一秒钟的数据丢失,于是整个事务的数据安全性将无法保证,但其通常有着最好的性能。为了在最大程序上保证复制的InnoDB事务持久性和一致性,应该设置变量innodb_flush_log_at_trx_commit=1以及设置变量sync_binlog=1。
然而需要注意的是,有些磁盘自身也有缓存,这可能会给事务操作带来额外的潜在风险。可以使用hdparm工具或供应商的自有工具等禁用磁盘自身的缓存。当然,高性能事务的最佳配置是把此变量的值设置为1,并且将日志文件放在有备用电池的写入缓存的RAID上。作用范围为全局,可用于选项文件,属动态变量。
 
innodb_flush_method={O_DSYNC|O_DIRECT}
设定InnoDB实际与文件系统进行交互的方式。除了写操作之外,它还可以影响InnoDB如何读取数据。设置innodb_flush_method变量的值为O_DSYNC时,InnoDB使用O_SYNC标志来打开和刷写日志文件,而使用fsync()来刷写数据文件。O_SYNC会使得所有的写入操作都是同步的,即只有在数据被写入磁盘之后才会返回,但不会在操作系统层面禁止缓存,因此,它不会避免双缓冲,并且不会直接写入磁盘。fsync()会同时刷数据和元数据(而fdatasync()只刷写数据),它比fdatasync()产生更多的IO操作,而且操作系统会缓存一些数据在自己的缓存中(这将导致双缓冲)。如文件系统可以智能地处理I/O需求,双缓冲可能不是坏事儿,但如果MySQL设置了innodb_file_per_table变量的值为1,则会导致第个表空间文件都单独使用fsync()函数,其写入操作就不可能会被合并了。
设置innodb_flush_method变量的值为O_DIRECT时,InnoDB使用O_DIRECT标志打开数据文件,而使用fsync()刷写数据和日志文件。O_DIRECT标志会导致操作系统既不缓存数据,也不预读数据,它完全禁止了操作系统的缓存并且使所有的读写动作直接至存储设备,避免了双缓冲。然而,其不能禁止硬件层面(如RAID卡)的缓存和预读功能,而且启用硬件层面的缓存和预读功能也是保证InnoDB使用了O_DIRECT标志时仍能保持良好性能的惟一途径。
作用范围为全局,可用于选项文件,属非动态变量。
 
innodb_force_load_corrupted={ON|OFF}
设定InnoDB在启动时是否装载标记为“已损坏(corrupted)”的表。仅应该在troubleshooting的场景中启用该功能以修复无法访问的表,在troubleshooting任务完成后应该禁用此功能并重启MySQL服务。作用范围为全局,可用于选项文件,属非动态变量。
 
innodb_force_recovery={0|1|2|3|4|5|6}
设定InnoDB的故障恢复模式。InnoDB出现了“页面损坏(page corruption)”时,通常大部分数据仍然完好,于是可以通过SELECT...INTO OUTFILE命令备份出数据以降低损失程度。然而,某些“损坏”类的故障可能会导致SELECT * FROM tbl_name命令无法执行或InnoDB后台操作崩溃,甚至会导致InnoDB的前滚操作。这种情况下,就可以使用innodb_force_recovery变量强制InnoDB存储引擎在启动时不执行后台操作,以便能将数据备份出来。
innodb_force_recovery可接受的值中,“0”为默认值,表示执行正常启动,即不启用“强制修复”模式。而非零值中,某数值会包含比其小的所有数值的预防措施,然而其也较可能给B-tree索引及其它的数据结构带来更多的损坏。故此,在此变量值为非零值时,其会阻止用户使用INSERT、UPDATE或DELETE操作,但是会允许执行SELECT、CREATE TABLE或DROP TABLE类的操作。以下是关于其它非零值功能的说明:
1(SRV_FORCE_IGNORE_CORRUPT):即使出现了页面损坏也照常运行MySQL服务,其会在SELECT * FROM tbl_name语句执行时尝试跳过损坏的索引记录和页面。
2(SRV_FORCE_NO_BACKGROUND):禁止启动主线程(master thread),其会在执行清写(purge)操作时防止出现崩溃(crash)。
3(SRV_FORCE_NO_TRX_UNDO):在故障恢复(crash recovery)后不执行事务的回滚操作。
4(SRV_FORCE_NO_IBUF_MERGE):禁止执行修改缓冲(insert buffer)合并操作。
5(SRV_FORCE_NO_UNDO_LOG_SCAN):在启动数据库服务时不检查撤消日志(undo logs),这会导致InnoDB将未完成的事务视为已提交。
6(SRV_FORCE_NO_LOG_REDO):不执行重做日志(redo log)的前滚操作。此时,仅能执行不带WHERE、ORDER BY或其它子句的SELECT * FROM tbl_name操作,因为复杂查询在遇到损坏的数据结构时会中止并退出。
 
innodb_io_capacity=#
设定InnoDB后台任务(如从缓冲池刷写页面或合并修改缓冲中的数据等)可执行的I/O操作上限。其最小值为100,默认值为200,最大值取决于CPU架构。对于有着较大I/O负载的服务器来讲,应该为其指定更大的值以便能够更好更快的执行后台维护任务。然而,在实践中,此变量的值应该尽可能接近MySQL服务器每秒钟执行的I/O操作数量(即IOPS),甚至于让其低至以不影响后台任务执行为目标的最低限度。因为,如果此值过高的话,数据会被频繁地从缓冲中移入移出,这会降低缓存池的在系统性能提升方面的效用。单个5400RPM或7200RPM磁盘仅能完成大约100个IOPS,因此,此种情况下应该将此变量值降低至100;而对于有着多块磁盘或更强性能的存储设备(如固态磁盘)的应用场景,可以按需提高此变量的值。作用范围为全局,可用于选项文件,属动态变量。
 
innodb_large_prefix={ON|OFF}
设定对于使用了DYNAMIC或COMPRESSED行格式的InnoDB表来说,是否能够使用大于767字节长度的索引前缀。然而,创建此种类型的表还需要设定innodb_file_format的值为barracuda,以及innodb_file_per_table的值为ture。同时,此设定对使用了REDUNDANT和COMPACT行格式的表的索引长度限定来说是不起作用的。作用范围为全局,可用于选项文件,属动态变量。
 
innodb_lock_wait_timeout={1 .. 1073741824}
设定InnoDB中某事务试图访问一个由其它InnoDB事务加锁的行时其最长的等待时间,单位为秒钟,默认值为50。在超时情况发生时,InnoDB会返回一个1205类型的错误信息,并对当前语句(非整个事务)执行回滚操作;如果需要在此种情况下对整个事务进行回滚,则需要在MySQL服务启动时使用--innodb_rollback_on_timeout选项。
对于OLTP系统或有着较多交互式应用的程序来说,应该降低此变量值以使得用户较快地获取到反馈信息,或使得系统较块地将此更新操作提交到队列中以便延后处理。对于批处理应用较多的场景来说,如数据仓库,应该增加此变量的值以等待其它较大的插入或更新操作完成。
此变量仅对InnoDB的行锁产生作用,MySQL的表锁并非在InnoDB中实现,所以此超时时长对表锁没有影响。而且,由于InnoDB会能立即探测到死锁的发生并会对其中的一修整务执行回滚操作,因此此超时时长也不应用于死锁。作用范围为全局或会话级别,可用于选项文件,属动态变量。
 
innodb_locks_unsafe_for_binlog={ON|OFF}
设定InnnoDB是否在搜索和索引扫描中使用间隙锁(gap locking)。InnoDB使用行级锁(row-level locking),通常情况下,InnoDB在搜索或扫描索引的行锁机制中使用“下一键锁定(next-key locking)”算法来锁定某索引记录及其前部的间隙(gap),以阻塞其它用户紧跟在该索引记录之前插入其它索引记录。站在这个角度来说,行级锁也叫索引记录锁(index-record lock)。
默认情况下,此变量的值为OFF,意为禁止使用非安全锁,也即启用间隙锁功能。将其设定为ON表示禁止锁定索引记录前的间隙,也即禁用间隙锁,InnoDB仅使用索引记录锁(index-record lock)进行索引搜索或扫描,不过,这并不禁止InnoDB在执行外键约束检查或重复键检查时使用间隙锁。
启用innodb_locks_unsafe_for_binlog的效果类似于将MySQL的事务隔离级别设定为READ-COMMITTED,但二者并不完全等同:innodb_locks_unsafe_for_binlog是全局级别的设定且只能在服务启动时设定,而事务隔离级别可全局设定并由会话级别继承,然而会话级别也以按需在运行时对其进行调整。类似READ-COMMITTED事务隔离级别,启用innodb_locks_unsafe_for_binlog也会带来“幻影问题(phantom problem)”,但除此之外,它还能带来如下特性:
(1)对UPDATE或DELETE语句来说,InnoDB仅锁定需要更新或删除的行,对不能够被WHERE条件匹配的行施加的锁会在条件检查后予以释放。这可以有效地降低死锁出现的概率;
(2)执行UPDATE语句时,如果某行已经被其它语句锁定,InnoDB会启动一个“半一致性(semi-consistent)”读操作从MySQL最近一次提交版本中获得此行,并以之判定其是否能够并当前UPDATE的WHERE条件所匹配。如果能够匹配,MySQL会再次对其进行锁定,而如果仍有其它锁存在,则需要先等待它们退出。
 
innodb_log_buffer_size={262144 .. 4294967295}
设定InnoDB用于辅助完成日志文件写操作的日志缓冲区大小,单位是字节,默认为8MB。较大的事务可以借助于更大的日志缓冲区来避免在事务完成之前将日志缓冲区的数据写入日志文件,以减少I/O操作进而提升系统性能。因此,在有着较大事务的应用场景中,建议为此变量设定一个更大的值。作用范围为全局级别,可用于选项文件,属非动态变量。
 
innodb_log_file_size={108576 .. 4294967295}
设定日志组中每个日志文件的大小,单位是字节,默认值是5MB。较为明智的取值范围是从1MB到缓存池体积的1/n,其中n表示日志组中日志文件的个数。日志文件越大,在缓存池中需要执行的检查点刷写操作就越少,这意味着所需的I/O操作也就越少,然而这也会导致较慢的故障恢复速度。作用范围为全局级别,可用于选项文件,属非动态变量。
 
innodb_log_files_in_group={2 .. 100}
设定日志组中日志文件的个数。InnoDB以循环的方式使用这些日志文件。默认值为2。作用范围为全局级别,可用于选项文件,属非动态变量。
 
innodb_log_group_home_dir=/PATH/TO/DIR
设定InnoDB重做日志文件的存储目录。在缺省使用InnoDB日志相关的所有变量时,其默认会在数据目录中创建两个大小为5MB的名为ib_logfile0和ib_logfile1的日志文件。作用范围为全局级别,可用于选项文件,属非动态变量。
 
innodb_max_dirty_pages_pct={0 .. 99}
设定InnoDB的缓冲池中脏页比例的上限,默认为75。当缓存池中的脏页比例接近或达到此变量定义的比值时,InnoDB的主线程会将刷写部分脏页中的数据至对应的文件中。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_max_purge_lag={0 .. 4294967295}
InnoDB事务系统会维持一个有索引记录被添加了删除标记(delete-marked)的事务的列表,此列表的长度即为清写延迟(purge_lag)。此变量用于设定当发生清写延迟时,其队列长度达到多大时开始延迟INSERT、UPDATE或DELETE操作。当puge_lag超过innodb_max_purge_lag时,将延迟这些操作((purge_lag/innodb_max_purge_lag)*10)-5毫秒。默认值为0,表示从不延迟这些操作。需要进行操作延迟与否是在purge操作刚开始时计算的,并且每隔10秒钟会重新计算一次。基于历史地原因,purge操作无法启动时是不会有任何操作延迟的情况发生。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_mirrored_log_groups=#
设定日志组镜像的个数。其值应该为1。
 
innodb_old_blocks_pct={5 .. 95}
InnoDB以“列表”结构管理缓存池,并使用修改版的LRU算法对其执行维护操作。当需要空间以保存新块(new block)时,InnoDB会清理最近最少使用的块并将新块加入到列表中。“中点插入策略(midpoint insertion policy)”将整个列表看作两个子列表:在列表首部是那些最近被访问过的新块(new/young block)子列表,尾部是那些最近较少被访问到的旧块(lod block)子列表。而LRU算法和中点插入策略用于保证将最近经常被访问到的块置于新块子列表,InnoDB新读入的块将被置于旧块子列表的前头,并根据需要将旧块子列表中的块移除。而某个被再次访问到的旧块则会被移至新块子列表的首部。表扫描操作可能会一次性地向缓存池中读入大量的数据块并可能导致一大批旧块被移出。
此变量正是用于设置被视作旧块子列表的长度所占据整个列表长度的比例,默认值是37,即缓存池的八分之三。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_old_blocks_time=#
用于设定缓冲池中旧块子列表中的某旧块在其第一次又被访问到时,其至少需要在旧块子列表中再呆上多长时间(单位为毫秒)才会被转移至新块子列表。默认值是0,表示立即转移至新块子列表,哪怕其刚刚被转移至旧块子列表。而非零值则明确定义旧块列表中的块在其第一次被访问到时至少需要在旧块子列表中等待转移的时长。此变量通常要结合innodb_old_blocks_pct使用。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_open_files=#
设定MySQL可同时打开的.ibd表空间文件的数量上限。此变量仅在使用多表空间文件时生效,其最小值为10,默认值为300。此变量的限定仅应用于InnoDB表的.ibd文件,跟MySQL服务器选项--open-files-limit没有关系,更不会影响表缓存的操作。作用范围为全局级别,可用于选项文件,属非动态变量。
 
innodb_purge_batch_size={1 .. 5000}
清写(purge)是指将缓存池中的脏页同步至持久性存储设备中的操作,以重做日志的记录为单位。此变量则用于定义清写操作的粒度,即多少个重做日志记录组合起来可以触发一次清写操作,默认值为20。此变量通常用于跟innodb_purge_threads=1一起对进行性能调优,但一般场景中都不需要修改它。作用范围为全局级别,可用于选项文件,属非动态变量。
 
innodb_purge_threads={0|1}
设定InnoDB执行清写操作的线程数量。默认值为0,表示清写操作由InnoDB的主线程自己完成,这可以降低内部资源竞争发生的概率,进而增强MySQL服务伸缩能力。不过,随着InnoDB内部各式各样的竞争越来越多,这种设置带来的性能优势已几乎不值一提。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_read_ahead_threshold={0 .. 64}
设定InnoDB预读页面至缓冲池时的线性预读敏感度,也即InnoDB的读操作至少从一个盘区(extent,包含64个页面)中读取多个页面时才会为读取整个盘区中后续的页面初始化一个异步读操作。默认值为56。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_read_io_threads={1 .. 64}
设定InnoDB为读操作启动的I/O线程数量,默认为4个。作用范围为全局级别,可用于选项文件,属非动态变量。
 
innodb_replication_delay={0 .. 4294967295}
设定在从服务器(slave)上运行的线程数达到innodb_thread_concurrency变量定义的并发上限时复制线程需要延迟的时长。默认为0,表示不延迟。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_rollback_on_timeout={ON|OFF}
设定事务执行过程超时时事务回滚的方式。在MySQL 5.5中,默认为OFF,表示仅回滚事务中的最后一个语句。如果设置为ON,则表示中止事务执行并回滚整个事务。作用范围为全局级别,可用于选项文件,属非动态变量。
 
innodb_rollback_segments={1 .. 128}
设定InnoDB在系统表空间中为每个事务使用多少个回滚段(rollback segment),默认为128个。如果较少的回滚段可以提升系统性能,则应该降低此变量的值。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_spin_wait_delay={0 .. 4294967295}
自旋(spin)是一种通过不间断地测试来查看一个资源是否变为可用状态的等待操作,用于仅需要等待很短的时间等待所需资源的场景。使用自旋这种“空闲循环(busy-loop)”来完成资源等待的方式要比通过上下文切换使线程转入睡眠状态的方式要高效得多。但如果自旋了一个很短的时间后其依然无法获取资源,则仍然会转入前述第二种资源等待方式。此变量则正是用于定义InnoDB自旋操作的空闲循环转数,默认为6转。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_stats_method={nulls_equal|nulls_unequal|null_ignored}
设定MySQL为InnoDB表收集分布的索引值的统计数据时如何处理NULL类型的数据。其可接受的值有三个,null_equals意指将所有的NULL值视为相同,并为之创建一个值组(value group)以保存NULL类值的个数;nulls_unequal意指将所有的NULL值视为不同,并为每个NULL单独创建一个大小为1的值组;nulls_ignored表示所有的NULL值都被忽略。这些用于生成表统计数据的方法会影响到优化器为执行查询如何选择选择索引。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_stats_on_metadata={OFF|ON}
设定使用SHOW TABLE STATUS或者SHOW INDEX这两个元数据语句时,或访问INFORMATION_SCHEMA中的TABLES或STATISTICS表时,InnoDB是否更新统计数据。默认为更新。禁用此功能可以加速访问有着大量的表或索引的数据库,也可能提升InnoDB表上查询操作执行计划(execution plan)的稳定性。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_strict_mod={ON|OFF}
为防止无视SQL语句书写或语法中的错误或无视操作模式与SQL语句各种组合中的无心之过,InnoDB提供了所谓的严格模式。严格模式中,前述的问题一旦出现将会导致InnoDB产生一个错误,而非警告和一系列特定的处理操作。此参数则正是用于定义是否启用InnoDB的严格模式,默认为OFF。
 
innodb_support_xa={TRUE|FLASE}
存储引擎事务在存储引擎内部被赋予了ACID属性,分布式(XA)事务是一种高层次的事务,它利用“准备”然后“提交”(prepare-then-commit)两段式的方式将ACID属性扩展到存储引擎外部,甚至是数据库外部。然而,“准备”阶段会导致额外的磁盘刷写操作。XA需要事务协调员,它会通知所有的参与者准备提交事务(阶段1)。当协调员从所有参与者那里收到“就绪”信息时,它会指示所有参与者进行真正的“提交”操作。
此变量正是用于定义InnoDB是否支持两段式提交的分布式事务,默认为启用。事实上,所有启用了二进制日志的并支持多个线程同时向二进制日志写入数据的MySQL服务器都需要启用分布式事务,否则,多个线程对二进制日志的写入操作可能会以与原始次序不同的方式完成,这将会在基于二进制日志的恢复操作中或者是从服务器上创建出不同原始数据的结果。因此,除了仅有一个线程可以改变数据以外的其它应用场景都不应该禁用此功能。而在仅有一个线程可以修改数据的应用中,禁用此功能是安全的并可以提升InnoDB表的性能。作用范围为全局和会话级别,可用于选项文件,属动态变量。
 
innodb_sync_spin_loops={0 .. 4294967295}
设定一个线程在等待InnoDB释放某个互斥量(mutex)之前自旋的转数,当自旋操作达到这个转数但互斥量仍未被释放时此线程将被挂起。默认值为30。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_table_locks={ON|OFF}
InnoDB在存储引擎级别支持行级锁,而MySQL在服务器级别还支持使用表级锁。此变量则正是用来定义InnoDB是否在其内部支持使用MySQL表级锁。默认值为1或ON,表示如果autocommit变量的值为0(即禁止自动提交),在InnoDB表上显式使用LOCK TABLES语句将使得InnoDB在存储引擎内部锁定此表。使用0或OFF值,则意味着显式使用LOCKS TABLE...WRITE语句不会在存储引擎级别产生影响,但对其它显式使用的LOCK TABLES...WRITE或LOCK TABLES...READ语句依然会有影响。作用范围为全局和会话级别,可用于选项文件,属动态变量。
 
innodb_thread_concurrency={0...1000}
设定InnoDB可在其内部并发运行的操作系统线程数量上限。多出的线程将被放置于FIFO队列进行等待,且不被计入并发运行线程数量。对于不用的应用场景来说,其理想的取值取决于硬件环境和工作负载,一般推荐为CPU个数的2倍加上磁盘的个数。默认值为0,表示无上限(不检查并发数量),这意味着InnoDB可以按需要使用任意数量的并发线程,并会禁用SHOW ENGINE INNODB STATUS中的queries inside InnoDB和queries in queue counters两个计数器。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_thread_sleep_delay=#
设定InnoDB线程在加入InnoDB队列之前的睡眠时长,单位是毫秒,默认值为10000。0值表示禁止睡眠而直接加入队列。作用范围为全局级别,可用于选项文件,属动态变量。
 
innodb_use_native_aio={ON|OFF}
设定InnoDB是否使用Linux的异步I/O子系统,因此,其仅应用于Linux系统平台,且MySQL启动后不能更改其值。InnoDB默认会启用此功能,而InnoDB如果因为Linux的异步I/O子系统的问题而无法正常启动,可以在选项文件中将此变量设置为OFF并重新启动之。事实上,就算变量值为ON,如果MySQL服务启动探测到了潜在的问题如联合的临时目录路径、tmpfs文件系统以及Linux内核不支持在tmpfs上使用AIO机制时也会自动关闭此变量。作用范围为全局级别,可用于选项文件,属非动态变量。
 
innodb_use_sys_malloc={ON|OFF}
设定InnoDB使用操作系统的(ON)还是自有的(OFF)内存分配器。默认值为ON。
 
innodb_version=STRING
InnoDB存储引擎的版本号,只读变量。
 
innodb_write_io_threads={1 .. 64}
设定InnoDB用于完成写操作的I/O线程数量,默认为4个。
 
 
附:InnoDB的数据字典指的是跟踪InnoDB相关的对象如表、索引或表中的字段等的元数据信息,这些元数据存储在InnoDB的系统表空间中(system tablespace)。历史地原因,它跟.frm文件中的某些数据有重叠的地方。
常见变量说明

如果想查看MySQL相关的某些属性可以使用 like ''%属性% ''进行模糊匹配;

mysql> show variables like '%属性名称%';
mysql> show variables like '%data%';
+-------------------------------+------------------------+
| Variable_name                 | Value                  |
+-------------------------------+------------------------+
| character_set_database        | utf8                   |
| collation_database            | utf8_general_ci        |
| datadir                       | /usr/local/mysql/data/ |
| innodb_data_file_path         | ibdata1:12M:autoextend |
| innodb_data_home_dir          |                        |
| innodb_stats_on_metadata      | OFF                    |
| max_length_for_sort_data      | 1024                   |
| metadata_locks_cache_size     | 1024                   |
| metadata_locks_hash_instances | 8                      |
| myisam_data_pointer_size      | 6                      |
| skip_show_database            | OFF                    |
| updatable_views_with_limit    | YES                    |
+-------------------------------+------------------------+
12 rows in set (0.00 sec)
data相关
mysql> show variables like '%engin%';
+----------------------------+--------+
| Variable_name              | Value  |
+----------------------------+--------+
| default_storage_engine     | InnoDB |
| default_tmp_storage_engine | InnoDB |
| storage_engine             | InnoDB |
+----------------------------+--------+
3 rows in set (0.00 sec)
数据库引擎相关

 

 

 2.运行状态变量show status

 可以通过show status,查看MySQL的运行状态的相关变量来了解MySQL的相关状态,作为开发人员我们可以把这些数据分析展示给DBA;

 

 六、MySQL日志

MySQL的日志分为以下几类:

错误日志:记录错误信息(运维关心)

查询日志:记录用户执行的SQL语句

慢查询日志:记录执行速度慢的SQL的

事物日志

二进制日志

中继日志

 

1.查询日志

查询日志是记录用户输入SQL,不仅可以记录到文件,还可以输出到表中,知道怎么跑路了吗?小伙?

开启查询日志功能

mysql> set global general_log=on;      #开启查询日志功能
Query OK, 0 rows affected (0.08 sec)

mysql> set global log_output='table'; #设置查询日志输出到表中

只有你开启了查询日志功能并指定了日志的输出MySQL就会把数据输出到表(MySQL库中的general_log表)或配置的log文件中

mysql> select * from general_log;

 

 2.慢查询日志

在你设置一个慢查时长之后,如果SQL从开始<---->结束执行所花费的时间大于该时间,那么慢日志记录该SQL;

这些慢日志对于DBA来说非常有价值,它们就是基于这些做SQL优化的;

 

查看默认设置的慢日志时间阀值(10秒可以精确到微秒)

mysql> show global variables like '%long%';
+--------------------------------------------------------+-----------+
| Variable_name                                          | Value     |
+--------------------------------------------------------+-----------+
| long_query_time                                        | 10.000000 |
| performance_schema_events_stages_history_long_size     | 10000     |
| performance_schema_events_statements_history_long_size | 10000     |
| performance_schema_events_waits_history_long_size      | 10000     |
+--------------------------------------------------------+-----------+
4 rows in set (0.02 sec)
set global slow_query_log=on; #开启记录慢查询日志功能

 如果设置了log_output =TABLE,MySQL的慢查日志存在mysql库的slow_log表;

mysql> select * from slow_log;

 

 3.事物日志

MySQL的innodb搜素引擎才支持事物,需要注意:所有的事物操作都不会立即同步到数据库执行,而是先记录到事物日志文件;由于事物日志定期向数据库提交;

事物日志需要至少2文件记录提交事物,这两个文件是轮转的,1个写满写另一个;

mysql> show global variables like '%innodb_log%';
+-----------------------------+----------+
| Variable_name               | Value    |
+-----------------------------+----------+
| innodb_log_buffer_size      | 8388608  |  #
| innodb_log_compressed_pages | ON       | 
| innodb_log_file_size        | 50331648 |  #事物日志的大小
| innodb_log_files_in_group   | 2        |  #指定事物日志文件个个数
| innodb_log_group_home_dir   | ./       |  #innodb事物日志所在的目录 
+-----------------------------+----------+
5 rows in set (0.01 sec)

| innodb_flush_log_at_trx_commit #一旦事物提交同步到事物日志,1=每隔1秒钟同步1次,无论是否提交事物;2=只有事物提交才同步

 

4.二进制日志

4.1 什么是二进制日志文件?

记录修改数据或者有可能引起数据修改的SQL语句,所以select语句是不会记录进来的;

 

4.2 什么是主从复制?

那么S数据库不断得读取并执行M数据库产生的二进制个文件,导致S数据库=M数据库,这种技术手段就是主从复制;

 

4.3 MySQL二进制的格式有哪些?

如果 Master执行SQL包含获取当前时间的函数,Save再去通过二进制日志执行中间的时差势必会导致数据库不一致,所以仅记录SQL语句是不能完成主从复制的;还需要记录数据;

 

二进制日志格式有以下3种

SQL语句:statement

行数据:row

 混合:mixed

 

4.4 开启二进制日志

log-bin=mysql-bin               #开启二进制日志
server-id = 1                   #主数据库id为1,不能相同。
replicate_wild_do_table=web.%  #只同步test库下的表
/etc/my.conf
mysql> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | ON    |
+---------------+-------+
1 row in set (0.07 sec)

 

 4.5 查看当前MySQL的二进制日志

mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       120 |
+------------------+-----------+

 查看主

mysql> show master logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       120 |
+------------------+-----------+
1 row in set (0.01 sec)

 

执行flush logs操作会生成一个新的binlog文件

mysql> flush logs;
Query OK, 0 rows affected (0.03 sec)

 

 

查看当前使用的二进制日志

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      120 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)

 

 

查看二进制日志事件

mysql> show binlog events in 'mysql-bin.000001';
+------------------+-----+-------------+-----------+-------------+-----------------------------------------------------------------------------------+
| Log_name         | Pos | Event_type  | Server_id | End_log_pos | Info                                                                              |
+------------------+-----+-------------+-----------+-------------+-----------------------------------------------------------------------------------+
| mysql-bin.000001 |   4 | Format_desc |         1 |         120 | Server ver: 5.6.19-log, Binlog ver: 4                                             |
| mysql-bin.000001 | 120 | Query       |         1 |         241 | create database python default charset=utf8                                       |
| mysql-bin.000001 | 241 | Query       |         1 |         386 | use `python`; create table t5 (id int auto_increment primary key,name varchar(9)) |
| mysql-bin.000001 | 386 | Query       |         1 |         469 | BEGIN                                                                             |
| mysql-bin.000001 | 469 | Query       |         1 |         591 | use `python`; insert into t5(id,name) values(1,"zhanggen")                        |
| mysql-bin.000001 | 591 | Xid         |         1 |         622 | COMMIT /* xid=22 */                                                               |
+------------------+-----+-------------+-----------+-------------+-----------------------------------------------------------------------------------+
6 rows in set (0.00 sec)

 

 

 4.6 通过sql_log_bin控制会话级别临时开启关闭记录二进制功能;

在数据库恢复的时候 临时关闭二进制文件记录功能,是为了排除恢复过程中产生的SQL写入二进制文件;

mysql> set sql_log_bin='OFF';
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%sql_log_bin%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_log_bin   | OFF   |
+---------------+-------+
1 row in set (0.00 sec)

mysql> set sql_log_bin='on';
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%sql_log_bin%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_log_bin   | ON    |
+---------------+-------+
1 row in set (0.00 sec)

 

4.7 mysqlbinlog 

mysqlbinlog 是mysql自带的二进制日志管理工具,利用它的截取功能可以基于完全备份的数据+二进制日志,做完全备份时间节点之后任意时间的数据恢复工作了;

 

使用mysqlbinlog 截取 某段时间内(2018-12-01 16:50:00----2018-12-04 16:55:00)产生的二进制日志文件内容;

stdin,stdout,stderr = ssh.exec_command('mysqlbinlog --start-date="2018-12-01 16:50:00" --stop-date="2018-12-04 16:55:00" /usr/local/mysql/data/mysql-bin.00000*')
data=stdout.read().decode('utf-8')
for i in data.split('/n'):
    print(i)

 

使用mysqlbinlog 截取 某个时间节点之前(2018-12-04 16:55:00)产生的二进制日志文件内容;

stdin,stdout,stderr = ssh.exec_command('mysqlbinlog --stop-date="2018-12-04 16:55:00" /usr/local/mysql/data/mysql-bin.00000*')

 

 使用截取的二进制日志文件 数据恢复

[root@localhost zhanggen]# mysql -umartin -p123.com < /tmp/first.sql 
Warning: Using a password on the command line interface can be insecure.

 

 

 

 

 

5.中继日志

主从架构的MySQL, 从MySQL通过远程不断从 主MySQL同步二进制日志 存储在中继日志,从读取中继日志并执行达到主从同步的效果;

(中继日志 = 主服务器上的二进制日志)

 

 

七、MySQL备份

数据库就像企业的心脏,产生数据(血液)输送到各个业务线处理之后回流到心脏,循环往复,所依对它的备份、灾难情况下可以还原至关重要;

磁盘阵列(Redundant Arrays of Independent Drives,RAID)只能在硬件层面保证1块硬盘损坏之后数据不丢失,RAID无法保证用户层面的逻辑操作(自己删个库);

 

1.为什么要做数据备份?

灾难恢复:数据丢失的情况下快速恢复数据;(最常见场景)

需求改变:数据回滚到某1时间节点;

测试:可以复制数据还原到测试环境,以便测试;

 

2.备份需要考虑的问题?

可容忍丢失多长时间的数据?

恢复是是否需要暂停业务?

恢复在多长时间内完成?

 

3.备份类型

3.1:根据是否需要数据库离线的标准划分

冷备:MySQL服务库暂停,读写请求均不允许;

温备:MySQL服务在线,备份时仅支持读请求,不支持写请求;

热备:备份同时MySQL服务、读请求、写请求不受影响(MyISAM存储引擎不支持热备,innoDB存储引擎支持)

 

3.2:根据每次备份的数据量 划分

完全备份(Full Backup):没次备份整个数据量;

 

增量备份(Icreamental Backup):自上1次完全备份、增加备份之后 增加的数据量;

PS:如果每天都做完全备份,数据恢复的时候方便,但是备份效率低下,所以增量备份需要依赖完全备份,是完全备份的辅助策略;

备份策略:

Sunday完全备份

+ Monday增量备份 + Tuesday增量备份 +Wednesday增量备份 +Thursday增量备份 +Thursday增量备份 + Thursday增量备份

 

 

恢复策略:

哈哈...如果按以上的备份策略,周六出现紧急状况,需要恢复数据,难度就比较大了,你需要拿着 Last Sunday + Monday+.....Fridy

 

差异备份(Difference Backup):

差异备份就是做1次完全备份之后,然后每天产出的增量数据 汇聚到同一个地方备份;

差异备份比较容易恢复:因为只有2个数据集;

 

 PS:如果我周1 0点做了1次完全备份,往后一周时间内每天0点做1次增量备份,那周六晚上18点服务器宕机了(等于周六的增量备份失败了),那我怎么恢复呢?

当然是二进制日志啦!所以你在每次备份之后一定要flush logs;一下产生1个新的二进制日志文件标记一下;

2个增量备份时间节点中间出现了岔子,才可以利用上二进制日志;

 

总结:

到底使用增量备份还是差异备份根据自己的业务场景,都需要依赖完全备份,

 其实增量备份 差异备份 只是把增量数据 放在1起存储  还是不放到一起存的不同;

无论使用增量备份还是差异备份策略都需要 用得二进制日志;

恢复   =   完全备份 + 增量1 +增量1 ....  + 二进制日志

 恢复   =  完全备份     +         差异备份   + 二进制日志

 

3.3:根据备份的数据类型不同分为

物理备份:备份数据文件

优:

备份恢复都比较简单、快速

劣:

不能做热备

 

逻辑备份:备份表中的数据+代码

优:

恢复简单

备份结果为ASCII文件,可编辑

与存储引擎引擎无关

可以通过网络备份和恢复

 

劣: 

备份和恢复都需要MySQL进程参与,不能暂停MySQL服务

备份结果占据更多磁盘空间

浮动数丢失精度

还原之后索引需要重建

 

4.备份对象

数据:库、表、索引

配置:MySQL配置文件、OS相关的配置文件、主从复制相关的配置

SQL代码:存储过程、函数、触发器...

日志:二进制日志、查询日志、慢查询日志

 

5.备份工具介绍

5.1 mysqldump

MySQLdump是一款 传统、经典的逻辑备份工具,innodb存储引擎支持热备、myisam存储引擎支持温备,备份和恢复较慢;

 

备份整个MySQL服务(所有数据库)

[root@localhost /]# mysqldump -umartin -p123.com --master-data=2 -a --lock-all-tables > /tmp/all_database.sql
ps: -a 参备份所以数据库

 

部分数据库

[root@svnnew ~]# mysqldump -uwebproject -pweb --master-data=2 --databases web mysql --lock-all-tables > /tmp/web_and_mysl.sql
#记录二进制日志位置 #备份的所有数 #施加读锁
ps:--single-transaction 参数可以实现innodb的热备,不需要
--lock-all-tables
[root@localhost /]# less /tmp/mysql.sql 

部分表

表中的某些行

存储过程

存储函数

触发器

自动记录二进制文件以及相应positon

 

-e,  --events:   同时备份事件调度器代码
-r,  --routines: 同时备份存储过程和存储函数
-d,  --no-data: 只备份表结构不备份数据
--opt

 

 

 

 

5.2 mysqldumper

mysqldum的加强版,多线程备份工具; 

 

5.3 select 表备份功能

逻辑备份工具,通常用于备份单表;

select into outfile

select * from cmdb_userinfo where id >7 into outfile '/tmp/lg7_users';    #注意mysql用户一点要对备份的目录有写入权限

load data infile 

mysql> load data infile '/tmp/lg7_users' into table cmdb_userinfo;

 

 

5.4 lvm-snapshot (LVM 快照)

一款接近热备的备份工具,备份时需要施加读锁;

 

5.5 xtrabackup

xtrabackuo是ibbackup的开源版本,物理备份工具,支持innodb热备,对于MyISAM仅支持温备,备份速度快;

 

 

 

 

5.6 mysqlhotcopy

mysql自带 冷备工具

 

 

6.数据备份之后恢复步骤

停止MySQL服务(如果冷备)

记录MySQL服务的配置和文件权限

复制备份文件至数据目录

启动服务

装置逻辑备份

测试数据还原完成

已完全权限重启MySQL了

 

八、percona-toolkit工具

percona-toolkit工具包同percona-xtrabackup一样都是用Perl写的工具包,percona-toolkit工具包是一组高级的管理mysql的工具包集,本地、远程分析日志;

可以用它采集的数据做MySQL性能分析;

 

1.安装

[root@db ~]# ldconfig -p | grep mysql

那就添加一下:
[root@db ~]# echo '/usr/local/mysql/lib' > /etc/ld.so.conf.d/mysql.conf
[root@db ~]# ldconfig
[root@db ~]# ldconfig -p | grep mysql
出现install_driver(mysql) failed: Attempt to reload DBD/mysql.pm aborted报错

 

2.使用 

分析日志并产生报告

pt-query-digest mysql-bin.00000*

 

分析最近12小时之内的二进制日志 

 

 

 

mysql配置和status进行汇总

pt-mysql-summary  --user=webproject --password='xxxxxx1234'  --port=3306  --host=172.17.10.112

 

 分析参数,并提出建议

pt-variable-advisor --user=webproject --password=xxxxxx1234  172.17.10.112

 

查找和显示指定的Master 有多少个Slave

pt-slave-find --user=webproject --password=xxxxxx1234  --port=3306  --host=172.17.10.112

 

查询重复索引

 pt-duplicate-key-checker  --user=webproject --password='xxxxxx1234'  --port=3306  --host=172.17.10.112

 

性能相关

 

把查询结果输出到数据库

 pt-query-digest --user='martin' --password='123.com' --review  h=127.0.0.1,D=test,t=query_review--create-review-table mysql-bin.00000*

 

 

九、python操作Oracle

import cx_Oracle
orcle_db = cx_Oracle.connect('sys','oracle123','10.102.6.38:1521/historydb',cx_Oracle.SYSDBA)
cursor = orcle_db.cursor()
cursor.execute('select sysdate from dual')
data=cursor.fetchall()
print(data)
cx_Oracle API

虽然Oracle提供了pythonAPI但是,必须要求API的版本和数据库的版本一致。

import paramiko,time
ssh = paramiko.SSHClient()
ssh._policy = paramiko.AutoAddPolicy()
ssh.connect(hostname='10.102.6.38',port=22, username='oracle',password='oracle')
# ssh.connect(hostname='10.102.6.38',port=22, username='root',password='EC_history&LINGzhi')
# ssh.exec_command('source /home/oracle/.bash_profile')
sql="echo 'show parameter;'| /u01/app/oracle/product/11.2.0/dbhome_1/bin/sqlplus sys/oracle123 as sysdba"
# ssh.exec_command('export ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1')

sql1="echo 'select sysdate from dual;'| /u01/app/oracle/product/11.2.0/dbhome_1/bin/sqlplus scott/tiger@172.16.22.25/pimdb"
#
# ssh.exec_command('export ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1')
stdin,stdout,stderr=ssh.exec_command('. ./.bash_profile;%s'%(sql))

data=stdout.read().decode('utf-8').split('\n')[11:-3]
for row in data:
    print(row)
通过paramiko自定义Oracle API
#操作 Oracle、MySQL、Redis的shell和API
class DB_API(object):
    def __init__(self,db_obj):
        self.host = db_obj.db.host
        self.user = db_obj.db_user.username
        self.pwd = db_obj.db_user.password
        self.port = db_obj.db.port
        self.type = db_obj.db.get_database_type_display()
        self.sid=db_obj.db_user.sid

    def call_api(self,sql):
        print('输入%s的sql语句,返回执行结果,redis返回连接对象...'% (self.type))
        self.sql=sql
        db_engin = getattr(self,self.type)
        return db_engin()

    def Redis(self):
        conn_pool = redis.ConnectionPool(host=self.host, port=self.port, db=2, password=self.pwd)
        conn = redis.Redis(connection_pool=conn_pool)
        return conn

    def MySQL(self):
        db = pymysql.connect(self.host, self.user, self.pwd, 'mysql')
        cursor = db.cursor()
        cursor.execute(self.sql)
        data = cursor.fetchall()
        return data

    def Oracle(self):
        import cx_Oracle
        #orcle_db = cx_Oracle.connect('sys','oracle123','10.102.6.38:1521/historydb',cx_Oracle.SYSDBA)
        orcle_db = cx_Oracle.connect(self.user,self.pwd ,self.host+':'+self.port+'/'+self.sid,cx_Oracle.SYSDBA)
        cursor = orcle_db.cursor()
        cursor.execute(self.sql)
        data=cursor.fetchall()
        return data

    def generate_shell_cmd(self,sql):
        shell_cmd_dict = {
            'Redis': "echo '{sql}'| redis-cli -h {host} -p {port} -a {pwd}{user}",
            'MySQL': 'mysql -h{host} -u{user} -p{pwd} -Dmysql -e"{sql}"',
            'Oracle': [
                        ". ./.bash_profile; echo -e 'set pagesize 0\n {sql}'| /u01/app/oracle/product/11.2.0/dbhome_1/bin/sqlplus -S {user}/{pwd}@{host}/" +self.sid+" as sysdba",
                         ". ./.bash_profile; echo -e 'set pagesize 0\n {sql}'| /u01/app/oracle/product/11.2.0/dbhome_1/bin/sqlplus -S {user}/{pwd}@{host}/" + self.sid,
                       ]
        }
        if self.type=='Oracle' and self.user=='sys':
            shell_cmd =shell_cmd_dict.get(self.type)[0].format(user=self.user,pwd=self.pwd, sql=sql, host=self.host, port=self.port)
        elif self.type=='Oracle' and self.user!='sys':
            shell_cmd = shell_cmd_dict.get(self.type)[1].format(user=self.user, pwd=self.pwd, sql=sql, host=self.host, port=self.port)
        else:
            shell_cmd = shell_cmd_dict.get(self.type).format(user=self.user,pwd=self.pwd,sql=sql,host=self.host, port=self.port)
        print(shell_cmd)
        return shell_cmd

    def call_shell(self,sql):
        cmd_str = self.generate_shell_cmd(sql)
        if sys.platform == 'linux' and self.type != 'Oracle':
            task_obj = subprocess.Popen(cmd_str, stdout=subprocess.PIPE, shell=True, stderr=subprocess.PIPE)
            ret = task_obj.stdout.read().decode('utf-8') or task_obj.stderr.read().decode('utf-8')
            return ret
        else:
            ssh = paramiko.SSHClient()
            ssh._policy = paramiko.AutoAddPolicy()
            if self.type == 'Oracle':
                ssh.connect(hostname='10.102.6.38', port=22, username='oracle', password='oracle')
            else:
                ssh.connect(hostname='172.17.10.112', port=22, username='root', password='xxxxxx1234')
            stdin, stdout, stderr = ssh.exec_command(cmd_str)
            ret = stdout.read().decode('utf-8') or stderr.read().decode('utf-8')
            return ret

    def get_info(self):
        data = '获取失败!!'
        if self.type == 'Oracle':
            data = self.call_shell('show parameter;')
        elif self.type == 'MySQL':
            data = self.call_shell('show variables;')
        elif self.type== 'Redis':
            data = self.call_shell('info')
        return data
操作 Oracle、MySQL、Redis的shell的统一API

 

我想做  1个 可以统一调用所有DB的API, 以前的思路是 在1台服务器 上通过paramiko 执行 mysql -h、 sqlplus -S、redis-cli -h.....连接客户端连接上DB执行SQL,其实这不是最佳方案,因为SQL执行后 还要对返回结果做数据处理;

from sqlalchemy import create_engine

mysql_con=create_engine('mysql+pymysql://webproject:xxxxxx1234@172.17.10.112:3306/web')
oracle_conn=create_engine('oracle+cx_oracle://scott:tiger@172.16.22.16:1521/ecdb')

for i in mysql_con.execute('show databases'):
    print(i)

for i in oracle_conn.execute('select * from v$version'):
    print(i)
sqlalchemy 版

 

 

 https://www.cnblogs.com/mengfanrong/p/5367748.html

 

 

 

 

 

 

参考博客:http://blog.51cto.com/mageedu/1062628

 

转载于:https://www.cnblogs.com/sss4/p/9989563.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值