oracle数据库迁移到MySQL的三种方法

本文主要总结了oracle数据库迁移到MySQL的方法,方法包括手动方式导入导出、使用工具Navicat 进行导入、使用工具DBMover 的OracleToMySQL 进行导入和使用工具intelligent-converters 的 oracle-to-mysql 进行导入,需要的朋友可以参考下。

之前搭建了一个ExtJS + spring + Oracle 的这样一个报表系统的框架。 因为其他部门的要求, 也需要这个Framework 进行一些特殊的定制。

但是有一个问题是 Oracle 的数据库是需要收费的, 个人使用倒没什么问题, 公司使用的话就会有侵权的问题了。
而MySQL 则是完全免费的。

所以使用 ExtJS + Spring + MySQL 这样的组合应该就没什么问题了。

理论上来说, MySQL 已经被Oracle 收购, 这两者之间的Migrate 应该比较容易, 但实际的迁移还是有一些问题, 以下就说一说一些实现的方式和问题。

方式一: 手动方式导入导出

手动的方式导入, 就是操作步骤会比较繁琐一些。

对Table 的结构和数据:

1、 使用 SQL Developer 把 oracle 的 table 的schema 和 Data(.sql 和 .xls) 导出

2、 使用 MySQL 的 WorkBench 创建 Table 和导入数据。

这里语法上会稍微有一些不同, 所以需要略微做一些调整。

对于View 来说, 特别是复杂的有子查询的Oracle View 说, 要导入到MySQL 看起来就不是那么容易了。

方式二: 使用工具Navicat 进行导入

1、 新建数据库的连接,建立需要迁移的Oracle 和 MySQL 的数据库连接。

另外, 建立Oracle 连接的时候还需要下载一个oci.dll 的文件。

下载地址:http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html

下载之后, 解压到某个目录:

在 Navicat 的 工具 –> 选项 下做类似如下设置:

未分类

细部可以参见:http://wiki.navicat.com/wiki/index.php/Instant_client_required

完成设置后, 重启 navicat

2、 设置过连接之后,接下来就可以进行表和数据的migrate了

点击: 工具 –》 数据传输

在 “常规” 的标签页中设置需要 migrate 的连接

在 “高级” 的标签页中 ,设置需要 migrate 哪些具体的内容:

配置完成之后,点 “开始” 就可以了。

基本上:对于Table的结构和数据的迁移的话,基本上没什么问题。

但是对于View的导入,因为MySQL的View的语法不能有子查询语句。

在Navite上,可以看到从Oracle导入到MySQL的时候,View 的Checkbox 不能选取。

方式三:使用工具DBMover的OracleToMySQL进行导入

DBMover这个网站也提供了Oracle到MySQL 迁移的工具。

下载地址是:http://dbmover.com/download/oracletomysql_cn.zip

这也是一个收费的软件,试用版的限制是:允许迁移的记录条数累计为10万条。

下载安装,启动后会先要求输入数据库连接的信息,一直配置完成之后这里就只能看到table 了。

和Navicat比较起来,感觉这个显得简单,只能migrate table,而且使用上也不是很方便。

下一次Migrate又得重头到尾输入一次,没办法记住之前配置的连接。

MySQL高性能表设计规范

良好的逻辑设计和物理设计是高性能的基石, 应该根据系统将要执行的查询语句来设计schema, 这往往需要权衡各种因素。

一、选择优化的数据类型

MySQL支持的数据类型非常多, 选择正确的数据类型对于获得高性能至关重要。

更小的通常更好

更小的数据类型通常更快, 因为它们占用更少的磁盘、 内存和CPU缓存, 并且处理时需要的CPU周期也更少。

简单就好

简单数据类型的操作通常需要更少的CPU周期。 例如, 整型比字符操作代价更低, 因为字符集和校对规则(排序规则 )使字符比较比整型比较更复杂。

尽量避免NULL

如果查询中包含可为NULL 的列, 对MySQL来说更难优化, 因为可为NULL 的列使得索引、 索引统计和值比较都更复杂。 可为NULL的列会使用更多的存储空间, 在MySQL里也需要特殊处理。 当可为NULL的列被索引时, 每个索引记录需要一个额外的字节, 在MyISAM里甚至还可能导致固定大小的索引(例如只有一个整数列的索引)变成可变大小的索引。
当然也有例外, 例如InnoDB 使用单独的位 (bit) 存储NULL值, 所以对于稀疏数据有很好的空间效率。

1. 整数类型

有两种类型的数字:整数 (whole number) 和实数 (real number) 。 如果存储整数, 可以使用这几种整数类型:TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT。分别使用8,16, 24, 32, 64位存储空间。

整数类型有可选的 **UNSIGNED ** 属性,表示不允许负值,这大致可以使正数的上限提高一倍。 例如 TINYINT. UNSIGNED 可以存储的范围是 0 – 255, 而 TINYINT 的存储范围是 -128 -127 。

有符号和无符号类型使用相同的存储空间,并具有相同的性能 , 因此可以根据实际情况选择合适的类型。

你的选择决定 MySQL 是怎么在内存和磁盘中保存数据的。 然而, 整数计算一般使用64 位的 BIGINT 整数, 即使在 32 位环境也是如此。( 一些聚合函数是例外, 它们使用DECIMAL 或 DOUBLE 进行计算)。

MySQL 可以为整数类型指定宽度, 例如 INT(11), 对大多数应用这是没有意义的:它不会限制值的合法范围,只是规定了MySQL 的一些交互工具(例如 MySQL 命令行客户端)用来显示字符的个数。 对于存储和计算来说, INT(1) 和 INT(20) 是相同的。

2. 实数类型

实数是带有小数部分的数字。 然而, 它们不只是为了存储小数部分,也可以使用DECIMAL 存储比 BIGINT 还大的整数。

FLOAT和DOUBLE类型支持使用标准的浮点运算进行近似计算。
DECIMAL类型用于存储精确的小数。
浮点和DECIMAL类型都可以指定精度。 对于DECIMAL列, 可以指定小数点前后所允许的最大位数。这会影响列的空间消耗。

有多种方法可以指定浮点列所需要的精度, 这会使得MySQL选择不同的数据类型,或者在存储时对值进行取舍。 这些精度定义是非标准的,所以我们建议只指定数据类型,不指定精度。

浮点类型在存储同样范围的值时, 通常比DECIMAL使用更少的空间。FLOAT使用4个字节存储。DOUBLE占用8个字节,相比FLOAT有更高的精度和更大的范围。和整数类型一样, 能选择的只是存储类型; MySQL使用DOUBLE作为内部浮点计算的类型。

因为需要额外的空间和计算开销,所以应该尽量只在对小数进行精确计算时才使用DECIMAL。但在数据最比较大的时候, 可以考虑使用BIGINT代替DECIMAL, 将需要存储的货币单位根据小数的位数乘以相应的倍数即可。

3. 字符串类型

VARCHAR

用于存储可变⻓字符串,长度支持到65535
需要使用1或2个额外字节记录字符串的长度
适合:字符串的最大⻓度比平均⻓度⼤很多;更新很少

CHAR

定⻓,⻓度范围是1~255
适合:存储很短的字符串,或者所有值接近同一个长度;经常变更

慷慨是不明智的

使用VARCHAR(5)和VARCHAR(200)存储’hello’的空间开销是一样的。 那么使用更短的列有什么优势吗?

事实证明有很大的优势。 更长的列会消耗更多的内存, 因为MySQL通常会分配固定大小的内存块来保存内部值。 尤其是使用内存临时表进行排序或操作时会特别糟糕。 在利用磁盘临时表进行排序时也同样糟糕。

所以最好的策略是只分配真正需要的空间。

4. BLOB和TEXT类型

BLOB和 TEXT都是为存储很大的数据而设计的字符串数据类型, 分别采用 二进制和字符方式存储 。

与其他类型不同, MySQL把每个BLOB和TEXT值当作一个独立的对象处理。 存储引擎在存储时通常会做特殊处理。 当BLOB和TEXT值太大时,InnoDB会使用专门的 “外部“存储区域来进行存储, 此时每个值在行内需要1 – 4个字节存储 存储区域存储实际的值。

BLOB 和 TEXT 之间仅有的不同是 BLOB 类型存储的是二进制数据, 没有排序规则或字符集, 而 TEXT类型有字符集和排序规则

5. 日期和时间类型

大部分时间类型都没有替代品, 因此没有什么是最佳选择的问题。 唯一的问题是保存日期和时间的时候需要做什么。 MySQL提供两种相似的日期类型: DATE TIME和 TIMESTAMP。

但是目前我们更建议存储时间戳的方式,因此该处不再对 DATE TIME和 TIMESTAMP做过多说明。

6. 其他类型

6.1选择标识符

在可以满足值的范围的需求, 井且预留未来增长空间的前提下, 应该选择最小的数据类型。

整数类型

整数通常是标识列最好的选择, 因为它们很快并且可以使用AUTO_INCREMENT。

ENUM和SET类型

对于标识列来说,EMUM和SET类型通常是一个糟糕的选择, 尽管对某些只包含固定状态或者类型的静态 ”定义表” 来说可能是没有问题的。ENUM和SET列适合存储固定信息, 例如有序的状态、 产品类型、 人的性别。

字符串类型

如果可能, 应该避免使用字符串类型作为标识列, 因为它们很消耗空间, 并且通常比数字类型慢。

对于完全 “随机” 的字符串也需要多加注意, 例如 MDS() 、 SHAl() 或者 UUID() 产生的字符串。 这些函数生成的新值会任意分布在很大的空间内, 这会导致 INSERT 以及一些SELECT语句变得很慢。如果存储 UUID 值, 则应该移除 “-“符号。

6.2特殊类型数据

某些类型的数据井不直接与内置类型一致。 低千秒级精度的时间戳就是一个例子,另一个例子是以个1Pv4地址,人们经常使用VARCHAR(15)列来存储IP地址,然而, 它们实际上是32位无符号整数, 不是字符串。用小数点将地址分成四段的表示方法只是为了让人们阅读容易。所以应该用无符号整数存储IP地址。MySQL提供INET_ATON()和INET_NTOA()函数在这两种表示方法之间转换。

二、表结构设计

1. 范式和反范式

对于任何给定的数据通常都有很多种表示方法, 从完全的范式化到完全的反范式化, 以及两者的折中。 在范式化的数据库中, 每个事实数据会出现并且只出现一次。 相反, 在反范式化的数据库中, 信息是冗余的, 可能会存储在多个地方。

范式的优点和缺点

为性能提升考虑时,经常会被建议对 schema 进行范式化设计,尤其是写密集的场景。

  • 范式化的更新操作通常比反范式化要快。
  • 当数据较好地范式化时,就只有很少或者没有重复数据,所以只需要修改更少的数据。
  • 范式化的表通常更小,可以更好地放在内存里,所以执行操作会更快。
  • 很少有多余的数据意味着检索列表数据时更少需要 DISTINCT 或者 GROUP BY语句。

反范式的优点和缺点

不需要关联表,则对大部分查询最差的情况——即使表没有使用索引——是全表扫描。 当数据比内存大时这可能比关联要快得多,因为这样避免了随机I/0。

单独的表也能使用更有效的索引策略。

混用范式化和反范式化

在实际应用中经常需要混用,可能使用部分范式化的 schema 、 缓存表,以及其他技巧。
表适当增加冗余字段,如性能优先,但会增加复杂度。可避免表关联查询。

简单熟悉数据库范式

第一范式(1NF):字段值具有原子性,不能再分(所有关系型数据库系统都满足第一范式);
例如:姓名字段,其中姓和名是一个整体,如果区分姓和名那么必须设立两个独立字段;

第二范式(2NF):一个表必须有主键,即每行数据都能被唯一的区分;
备注:必须先满足第一范式;

第三范式(3NF):一个表中不能包涵其他相关表中非关键字段的信息,即数据表不能有沉余字段;
备注:必须先满足第二范式;

2. 表字段少⽽精

  • I/O高效
  • 字段分开维护简单
  • 单表1G体积 500W⾏行评估
  • 单⾏行不超过200Byte
  • 单表不超过50个INT字段
  • 单表不超过20个CHAR(10)字段
  • 建议单表字段数控制在20个以内
  • 拆分TEXT/BLOB,TEXT类型处理性能远低于VARCHAR,强制生成硬盘临时表浪费更多空间。

参考资料:

高性能mysql第三版

通过三个维度分析processlist 高效追溯MySQL活跃连接数飙升根因

一、引言

在运维MySQL时,经常遇到的一个问题就是活跃连接数飙升。一旦遇到这样的问题,都根据后台保存的processlist信息,或者连上MySQL环境,分析MySQL的连接情况。处理类似的故障多了,就萌生了一种想法,做个小工具,每次接到这种报警的时候,能够快速地从各个维度去分析和统计当前MySQL中的连接状态。比如当前连接的分布情况、活跃情况等等。

另外,真实故障处理时,光知道连接分布情况往往还不够,我们需要知道当前MySQL的正在忙于做什么,也就是正在执行一些什么样的SQL。而且,有时候即使我们知道了当前执行的SQL情况,也很难找到根因,因为如果活跃连接一旦飙升,这是的CPU基本上是处于被打满的状态,IO的负载也非常高,即使平时很快的SQL也变成了慢SQL,更不用说本身就很慢的SQL了。那我们怎么去甄别这些SQL里,哪些是导致问题的罪魁祸首,哪些仅仅是受害者呢?

带着这些需求和问题,本文逐渐展开并一一做分析和解答,展示我们这个小工具的功能。

二、连接分析

想知道当前MySQL的连接信息,最直观的方法是看MySQL的processlist,如果希望看到完整的SQL,可以执行show full processlist,或者直接查information_schema中的processlist这个表。当MySQL中连接数比较少的时候,还能够人肉分析出来,可是如果连接数比较多,那就很难考肉眼看processlist去分析问题了。

最开始,我们的做法是写个脚本,用MySQL客户端在命令行登录MySQL,并执行show full processlist,然后将输出作为一个文本分析。本来这种实现方式在MySQL5.5和MariaDB上运行得很好,可是,当在MySQL5.6环境上运行时,出现了问题,在控制台输出中会多出一行Warning: Using a password on the commandline interface can be insecure,相信很多运行orzdba的同学也遇到过这种情况。这个是MySQL5.6本身的安全提示,输入明文密码时,没有办法避免,阿里的同学还分享过他们为此做过源码改造,因为他们很多任务都依赖于命令行执行MySQL命令并捕获结果。

还有另外一种方式规避这个问题就是用mysql_config_editor这个工具,但是这个需要做额外的一些配置,同时也有安全上的隐患。我们没有能力改造源码,但是也不想使用mysql_config_editor,所以我们使用了另外的方式,不从命令行登录,而是用information_schema的表processlist作为数据源,在上面做查询,得到processlist的信息。还有另外一张表performance_schema.threads,也包含了同样的结果,甚至更丰富的后台线程信息,而且相比information_schema.processlist,在查询的时候不用申请mutex,对系统系能影响小,不过这要求打开perfomance schema,感兴趣的同学可以自己尝试。

确定了连接信息来源,下面就开始分析信息统计维度。查看processlist这个表,表结构如下(以MySQL5.6为例,MariaDB可能有额外的信息):

  • ID:线程ID,这个信息对统计来说没有太大作用
  • USER:连接使用的账号,这个是一个统计维度,用于统计来自每个账号的连接数
  • HOST:连接客户端的IP/hostname+网络端口号,这也是一个统计维度,用于确定发起连接的客户端
  • DB:连接使用的default database,DB通常对应具体服务,可以用于判断服务的连接分布,这算一个统计维度
  • COMMAND:连接的动作,实际上是说连接处于哪个阶段,常见的有Sleep、Query、Connect、Statistics等,这也是一个统计维度,主要用于判断连接是否处于空闲状态
  • TIME:连接处于当前状态的时间,单位是s,这个在后面进行分析,暂不算在连接状态的统计维度中
  • STATE:连接的状态,表示当前MySQl连接正在做什么操作,这算一个统计维度,可能的值也比较多,详细可以查阅官方文档
  • INFO:连接正在执行的SQL,这个在下一节分析,暂不算在连接状态的统计维度中

通过上面的分析,总结出了5个连接的统计维度:user、host、- – db、command和state。有了这5个统计维度,我们就可以开始着手写小工具了。

最基本的功能需求就是,查询information_schema.processlist这个表,然后按刚才总结的5个统计维度,对MySQL中的连接进行分组统计,按照统计个数排序。processlist这个表的host字段需要做一些细节上的处理,因为它的值实际上是IP/hostname+网络端口号的组合,我们需要把端口号裁剪掉,这样才能按照客户端进行统计,否则每个客户端连接的端口号都是不一样的,没法进行分组统计。

最后的输出如下:

有了最基本的功能,能满足最基本的统计需求。可是在实际排查和处理线上问题时,可能并不关心所有的统计维度,只需要按照上述5个维度中的部分进行统计;另外,可能希望host出现在user的前面,优先按照客户端的IP或者是hostname进行统计。所以,这就要求这个工具具有增加灵活地添加或者删除统计维度的功能,而且能够对统计维度的出现顺序进行动态调整。

最后的示例输出如下:

最开始说了,我们造这个工具的初衷是分析活跃连接,可是统计出来的结果中,包含了空闲连接,那么需要将空闲连接从统计结果中排除出去。当然,除了空闲连接,可能还有一些MySQL本身的一些连接,例如slave线程,binlog dump线程等,也希望从结果排除出去。这就要求有个按照任意统计维度进行排除的功能。既然有了排除功能,那同样也可以增加包含功能,即按照任意统计维度进行过滤,包含固定条件的连接才能出现在统计结果之中。

有了这个连接统计信息,我们就清楚当前MySQL内部的连接状态,大致判断出是哪个业务或者模块有问题。

三、SQL分析

分析到业务或者模块的粒度还不够,到底是哪个接口或者是哪个功能有问题呢?根据上面的连接状态信息,还没有办法准确地回答这个问题。我们继续深入,分析processlist中的SQL,回去看到上节中被我们暂时忽略的information_schema.processlist这个表的INFO字段,里面就保存了每个活跃连接上正在执行的SQL信息。通过分析和统计SQL,我们才真正清晰地掌握MySQL当前的内部活动,活跃连接都在干些什么事。通过这种方式,我们可以协助RD同学快速地定位问题,找到有问题的接口或者是功能模块。

其实,要统计SQL并不容易,因为SQL千变万化,每一条SQL都不是一样的,即使是统一功能模块的SQL,参数也可能不一样。那这种情况下,如何统计SQL呢?这里借鉴了pt-toolkit中的设计思想。在pt-query-digest的分析结果中,有一个fingerprint的字段,它其实是一个hash值,这个hash值代表了一类SQL,这类SQL除了参数不一样之外,其它的SQL结构都是完全一致的。所以我们把这种思路引入到具体实现中,通过正则,将SQL中的具体条件都去掉,然后将正则之后的SQL结构相同的SQL都算作同一条SQL,然后就可以进行分组统计了。举个例子,比如现在应用里有2条SQL,分别如下:

未分类

这2条SQL除了最后where条件中ucid字段的值不一样之外,其他的SQL结构是完全一致的。通过正则匹配之后,将ucid的值和limit的行数去掉,在最终的统计结果中,这2条SQL都变成了下面的SQL:

未分类

这样,就实现了SQL的分组统计。

示例输出如下:

当然,还可以根据需要,添加一些附加信息,便于定位和分析问题,例如user、Host等。

四、事务分析

有了SQL分析和统计,在某些场景下,基本能定位到问题所在,比如高频的执行计划良好的SQL。可是如果是由于慢SQL导致整个系统响应变慢的场景,上面单纯的SQL统计是否还能够有效地快速定位出问题呢?肯定不能,因为此时,单纯地从统计结果,无法分辨出哪些是导致系统响应变慢的慢SQL,哪些是被影响的SQL。当然,统计结果中,次数多的SQL可能会是慢SQL,但是也可能本身就是一些高频的接口调用,因为系统响应变慢,导致请求堆积。所以,最好的办法就是能够加入一些其它的辅助信息,帮助判断哪些请求可能是慢查询。那加入哪些辅助信息呢?有两种选择。

首先,我们回去看第一节被我们忽略的information_schema.processlist这个表的Time字段,可以用于大概判断连接的上SQL的执行,和实际时长的差异取决于SQL执行时每个阶段所消耗的时间。其次,因为线上表都是InnoDB表,所以可以和InnoDB的事务统计信息进行关联。InnoDB的事务分为只读事务和读写事务,信息都保存在information_schema.INNODB_TRX这张表里。对于某些大事务的场景下,一个事务包含多个操作,这种方式得出的结果会有偏差。如果是非InnoDB的引擎,这种方式不适用。

此处分析时,以只读事务,也就是select语句为例。在实现上,我们将问题简化,通过processlist中time字段的值或者事务的执行时间,去预估一条SQL的执行时间,进而判断在processlist中,积压的大量连接中,哪些请求本身就是慢查询,哪些是受影响变慢的查询。利用事务判断时,将processlist中ID字段和information_schema.INNODB_TRX中trx_MySQl_thread_id字段做关联,具体的SQL为select p.*, now() – t.trx_started as runtime frominformation_schema.processlist p, information_schema.INNODB_TRX t where p.id =t.trx_MySQl_thread_id。最后,统计正则之后每一类SQL总的执行时间,以及平均执行时间。执行时间越长的,我们更倾向于认为是导致问题的罪魁祸首。

示例输出如下:

  • RT:这一类SQL截止当前,总的执行时间,单位是S(秒)
  • AVGRT:这一类SQL截止当前,每个事务平均执行时间,单位是S(秒)

加入user、Host等附加信息之后,输出如下:

五、结语

通过上面的3个维度,把MySQL的processlist中的可用信息基本上都挖掘得差不多了。我们在实际问题排查和处理时,也经常使用这个工具,经过实践检验,问题定位效率还是比较高效的。

但是,也还存在很多改进的地方。比如SQL语句分析中,limit值不同的,严格来说其实应该算不同的SQL,因为执行时间可能相差非常大。另外,SQL执行时间分析中,对于单条select语句的只读事务分析结果非常准确,但是对于读写事务,怎么减少结果的误差,因为读写事务相比只读事务会更复杂,因为可能涉及锁等待等一些额外的情况。所有的这些已经在我们的改进计划中,如果大家有好的思路或者是想法,欢迎交流。

我们自己做这些事情,其实日常运维经验的积累和沉淀,如果刚好某位同学的思路和实现有雷同,实属必然。

GitHub里的MySQL基础架构自动化测试

译者注:MySQL对于GitHub的重要性不言而喻,本文作者从MySQL的备份、自动测试能否成功从备份恢复数据、模拟各种 master 可能挂掉的情况、自动测试 failover 是否正常、自动测试 schema 迁移等几个方面说明了为何会相信MySQL自动化。以下为译文。

对于GitHub来说,MySQL的基础架构是非常重要的组件。MySQL给GitHub.com、GitHub的API、身份验证等提供服务。每个git请求都或多或少会接触到MySQL。我们的任务是保持数据的可用性和完整性。即使MySQL集群服务出现意外了,也需要能够执行一些任务,比如繁重的清理工作、临时更新、在线模式迁移、集群拓扑重构、池化和负载平衡等等。我们有基础设施来自动化这些操作。在本文将分享一些例子,说明如何通过持续测试来建立我们对基础设施的信任。

备份

对数据进行备份是非常重要的。如果还没有进行备份,那么这就是一个潜在的问题。Percona Xtrabackup是用来为MySQL数据库提供完整备份的工具。如果有一些已经确定需要保存的数据,也有一个专门备份数据的服务器。

除了完整的二进制备份之外,每天还运行几次逻辑备份。这些备份使工程师能够获得最新的数据。有时,他们希望从表中获得一组完整的数据,这样他们就可以在跟生产数据量一样的表上测试索引的更改是否有效,或者从某个时间点查看数据。Hubot允许恢复一张备份的表,当表已经导入好以后,它就会ping给我们。

未分类

数据被加载到非生产数据库,该数据库可供那些提出恢复数据要求的工程师们访问。

最后一种进行数据备份的方法是使用延时复制。与其说是一种备份,倒不如说是对数据的一种保障。对于每个生产集群,有一个延迟4小时复制的主机。假如某个查询没有运行,我们会在chatops(即一种会话驱动型开发的做法)上运行mysql panic。这将导致所有的延迟复制立即停止复制,然后“呼叫”数据库管理员。
这样就可以使用延迟复制来验证是否存在问题,然后将二进制日志快速转发到发生错误之前的位置。然后,我们可以将那个点之前的数据恢复到主服务器。

虽然说备份这个功能设计的很棒,但是如果一些未知或未捕获的错误导致备份没有成功,它们就会变得毫无价值。使用脚本恢复备份的好处就是它允许我们通过cron(是一个linux下的定时执行工具,可以在无需人工干预的情况下运行作业)自动验证备份文件是否有效。我们为每个集群都设置了一台专用主机,这台主机就是用来恢复最新的备份数据。这样可以确保备份正常运行,并且我们能够从备份中检索数据。

根据数据集大小会选择每天进行几次恢复。恢复后的服务器会按照预期加入到复制流中,并能够赶上复制。这种做法不仅仅是在测试备份文件是否可恢复,而且还可以测试需要识别的时间点是否准确。如果恢复过程中出现问题,我们会收到通知。

还追踪恢复的时间,所以我们很清楚在紧急情况下建立新的副本或恢复需要多长时间。

以下是自动恢复过程中Hubot编写的一些输出信息。

未分类

使用备份是为了给现有的MySQL服务器集添加一个新的副本。我们将构建一个新的服务器,一旦被告知它已经准备好,我们就可以开始恢复该特定集群的最新备份。有一个脚本可以运行所有的恢复命令,否则我们将不得不手工操作备份。我们的自动恢复系统实际上使用了相同的脚本。这大大简化了系统的构建过程,并允许我们使用聊天命令行的模式来启动和运行主机。下面显示的是在运行聊天命令行模式的数据恢复方法:

未分类

备份失败

使用Orchestrator (使你能够在工作环境中自动创建、监视和部署资源)为使用者执行自动化故障切换。期望Orchestrator可以正确检测master是否出现故障,然后可以指定副本进行升级,在所指定的副本下修复拓扑以后再升级。希望VIPs能够改变,池可以改变,客户端可以重新连接,puppet可以运行必要的组件等等。故障切换是一个复杂的任务,涉及到基础架构的许多方面。

为了建立对故障切换的信任,建立了一个类生产的测试集群,然后让它不断的崩溃以观察故障切换功能。

类生产环境与生产环境在很多方面的设置是完全相同的:硬件类型,操作系统,MySQL版本,网络环境,VIP,puppet配置,haproxy设置等。唯一不同之处在于测试集群不发送/接收生产流量。

在测试集群上模拟写入负载,同时避免复制延迟。写入负载不会超荷,但是有一些查询,这些查询是有意在相同的数据集中写入的。这在正常的时期作用并不明显,但事实证明是有用的,我们将会简要描述。

测试集群有三个数据中心的代表服务器。希望故障转移可以在同一数据中心内的服务器能够在对方时效时自动接替彼此的工作。希望能够在这样的约束下尽可能多地抢救出尽可能多的复制品,这些复制品能够尽可能的适用。orchestrator对拓扑结构没有先前的假设,它只能对出故障时的状态做出反应。

然而,我们有兴趣为故障转移创建复杂而多变的场景。我们的故障转移测试脚本为故障转移准备了理由:

  • 它识别现有的master;

  • 它重构了拓扑结构,使所有三个数据中心的代表成为主控。不同的DC具有不同的网络延迟,并且预期会在不同的时间对主机的崩溃做出反应;

  • 它选择一个解决崩溃方法。 我们选择杀掉master(kill -9)或网络划分它:iptables -j REJECT(nice-ish)或iptables -j DROP(无响应)。

脚本继续通过选择的方法使master崩溃,并等待orchestrator可靠地检测到崩溃并执行故障转移。虽然我们期望检测和升级在30秒内完成,但脚本并不会如你所愿,它在查找故障切换结果之前浪费掉一段指定的时间。比如:

  • 检查一个新的(不同的)主人是否到位;

  • 集群中有大量的副本;

  • master是可改变的;

  • 对master的写入在副本上可见;

  • 更新内部服务发现条目(新主人的身份如预期;旧主人已删除);

  • 其他内部检查。

这些测试确认故障转移是成功的,不仅是MySQL-wisee,而且是在我们更大的基础架构范围内。人们已经假设了一个VIP;具体的服务已经开始;信息到达了应该去的地方。

该脚本进一步恢复了失败的服务器:

  • 从备份中恢复它,从而隐式地测试我们的备份/恢复过程
  • 验证服务器配置如预期的那样(服务器不再相信它是主服务器)
  • 将其返回到复制集群,期望找到在主服务器上写入的数据

考虑以下预定的可视化故障转移测试:从一个运行良好的集群,看到问题在一些副本,诊断主(7136)死了,选择一个服务器来促进(a79d),重构拓扑低于服务器,为促进它(故障转移成功),恢复死去的主人,将它们转化为集群。

未分类

测试失败看起来像什么呢

测试脚本使用了一种stop-the-world的方法。故障转移组件中不管哪个环节出现问题,在管理员解决问题之前,整个过程都是失败的,而且后面的自动化测试也是无法执行的。当然我们会收到提醒,然后检查状态和日志。

测试脚本在以下环节中可能会失败:出现了意外的检测;故障转移期间;在备份/恢复问题上;太多服务器出现宕机;在故障转移后的意外配置上等等。

我们需要确保orchestrator正确地连接到服务器。这就是之前说的写入负载会起作用的地方:如果设置不正确,复制很容易被破坏。我们会得到DUPLICATE KEY或其他错误,以表示出了问题。

这一点尤其重要,所以我们对orchestrator进行了改进,引入了新的行为,并允许我们在一个安全的环境中测试这些更改。

混沌测试即将到来

上面演示的测试过程能够捕获(并已捕获)基础架构的许多问题。但这就够了吗?

在生产环境中总会有各种各样的问题。关于这些特定的测试方法,它不适用于我们的生产集群。它们不共享相同的流量和流量操作,也没有相同的服务器集。失败的类型可能会有所不同。

正在为生产集群设计混沌测试。 混沌测试将会在我们的生产中,但是按照预期的时间表和充分控制的方式来破坏碎片。混沌测试引入了对恢复机制的更高级别的信任,并影响(因此测试)更大的基础架构和应用程序。

这是一项微妙的工作:尽管我们承认需要进行混沌测试,但我们也希望避免对服务造成不必要的影响。不同的测试在风险级别和影响方面会有所不同,我们将努力确保服务的可用性。

Schema迁移

我们使用gh-ost从而将生产的schema进行迁移。gh-ost非常稳定,但是现在正在增加或者计划增加一些新的主要的功能,因此现在也处于开发当中。

gh-ost通过将数据复制到ghost表中,将二进制日志所拦截的正在进行的更改应用到ghost表上,即使原始表被写入到这个表中,也可以将表移到表上。然后,它将ghost表替换为原来的表。在迁移完成时,GitHub将继续使用由gh-ost生成并填充的表。

这一次,几乎所有的GitHub MySQL数据都是由gh-ost重新创建的,而且大部分都是重复的。我们必须高度信任gh-ost,让它一次又一次地篡改我们的数据,即使是在开发过程中。下面是我们如何获得信任的方法。

gh-ost提供了一个测试生产能力。它支持在副本上运行一个迁移,就像它在主服务器上运行的方式一样:gh-ost将连接到副本,并将其视为主服务器。它将以与实际主迁移相同的方式解析它的二进制日志。但是,它将复制行并将binlog事件应用到副本中,并避免将写入写入到主服务器上。

我们在生产中运行了专门的专用副本。这些副本不服务于生产流量。每个这样的副本都检索当前的生产表列表,并以随机的顺序迭代它们。一个接一个地选择一个表,并在该表上执行一个复制迁移。迁移实际上并没有修改表结构,而是运行一个简单的引擎=InnoDB。即使在生产中使用表时,测试也会运行迁移,从而复制实际的生产数据,并在二进制日志中应用真正的生产流量。

这些迁移可以被审核。下面是我们如何从聊天中检查运行测试的状态:

未分类

当一个测试迁移完成了对表数据的复制时,它停止复制并执行剪切操作,替换原来的表,用ghost表替换原来的表,然后交换回来。我们对实际替换数据不感兴趣。取而代之的是原始表和ghost表,两者都应该是相同的。我们通过检查这两个表的整个表数据来验证这一点。

一个测试可以完成:

  • 成功:一切都很顺利,校验和也一样。我们希望看到这一点。
  • 失败:执行的问题。由于迁移过程被杀死、复制问题等等,这种情况有时会发生,而且通常与ghost本身无关。
  • 校验和失败:表数据不一致。对于经过测试的分支,这需要修复。对于正在进行的主分支测试,这将意味着立即停止生产迁移。我们没有得到后者。

测试结果被审计,发送到机器人聊天室,作为事件发送给我们的度量系统。下面的图中的每一条垂直线代表一个成功的迁移测试:

连续运行这些测试。如果出现故障,我们会收到警报通知。当然,我们也可以去机器人聊天室看看发生了什么。

新版本测试

我们一直在改善gh-ost,我们的开发流程都是基于git的分支,最后再通过pull请求进行合并。

提交的 gh-ost pull请求通过持续集成(CI)进行基本的编译和单元测试。从技术上讲,该公司在技术上有资格合并,但更有趣的是,它有资格通过天堂进行部署。作为我们基础架构中的敏感组件,我们需要在合并成主之前,将gh-ost分支部署到密集的测试中。

有些PRs是小的,不影响数据本身。对状态消息、交互命令等的更改对ghost应用程序的影响较小,其他一些则对迁移逻辑和操作造成了显著的变化。我们将严格地测试这些数据,在我们的生产表舰队中运行,直到满足这些更改不会造成数据损坏威胁。

结论

通过测试,我们就更想新机器的运作额。通过在生产中做这些自动化测试,我们可以不断的得到一切都如预期的那样运行的确认信息。随着基础架构的继续开发,我们也会通过调整测试从而满足最新的调整。

在没有测试的情况下,生产总是令人惊讶的。我们对生产环境的测试越多,我们对应用程序的期望和基础设施的能力就会得到更多的投入。

mysql(mariadb)启动报错数据恢复过程

一、启动mysql(mariadb)报错

(注:后文中mysql==mariadb):

未分类

二、查看mysql日志:

vim /var/log/mariadb/mariadb.log
InnoDB: End of page dump

160226 11:00:21  InnoDB: Page checksum 913642282 (32bit_calc: 472052024), prior-to-4.0.14-form checksum 2048873750
InnoDB: stored checksum 913642282, prior-to-4.0.14-form stored checksum 1622372148
InnoDB: Page lsn 0 142354744, low 4 bytes of lsn at page end 142348560
InnoDB: Page number (if stored to page already) 589,
InnoDB: space id (if created with >= MySQL-4.1.1 and stored already) 0
InnoDB: Page may be an update undo log page
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 589.
InnoDB: You may have to recover from a backup.
InnoDB: It is also possible that your operating
InnoDB: system has corrupted its own file cache
InnoDB: and rebooting your computer removes the
InnoDB: error.
InnoDB: If the corrupt page is an index page
InnoDB: you can also try to fix the corruption
InnoDB: by dumping, dropping, and reimporting
InnoDB: the corrupt table. You can use CHECK
InnoDB: TABLE to scan your table for corruption.
InnoDB: See also  http://dev.mysql.com/doc/refman/5.5/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
160226 11:00:21 [ERROR] mysqld got signal 6 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.

To report this bug, see  http://kb.askmonty.org/en/reporting-bugs

We will try our best to scrape up some info that will hopefully help
diagnose the problem, but since we have already crashed,
something is definitely wrong and this may fail.

Server version: 5.5.44-MariaDB
key_buffer_size=134217728
read_buffer_size=131072
max_used_connections=0
max_threads=153
thread_count=0
It is possible that mysqld could use up to
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 466713 K  bytes of memory
Hope that's ok; if not, decrease some variables in the equation.

Thread pointer: 0x0x0
Attempting backtrace. You can use the following information to find out
InnoDB: End of page dump
160226 11:00:30  InnoDB: Page checksum 913642282 (32bit_calc: 472052024), prior-to-4.0.14-form checksum 2048873750
InnoDB: stored checksum 913642282, prior-to-4.0.14-form stored checksum 1622372148
InnoDB: Page lsn 0 142354744, low 4 bytes of lsn at page end 142348560
InnoDB: Page number (if stored to page already) 589,
InnoDB: space id (if created with >= MySQL-4.1.1 and stored already) 0
InnoDB: Page may be an update undo log page
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 589.
InnoDB: You may have to recover from a backup.
InnoDB: It is also possible that your operating
InnoDB: system has corrupted its own file cache
InnoDB: and rebooting your computer removes the
InnoDB: error.
InnoDB: End of page dump
160226 11:00:30  InnoDB: Page checksum 913642282 (32bit_calc: 472052024), prior-to-4.0.14-form checksum 2048873750
InnoDB: stored checksum 913642282, prior-to-4.0.14-form stored checksum 1622372148
InnoDB: Page lsn 0 142354744, low 4 bytes of lsn at page end 142348560
InnoDB: Page number (if stored to page already) 589,
InnoDB: space id (if created with >= MySQL-4.1.1 and stored already) 0
InnoDB: Page may be an update undo log page
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 589.
InnoDB: You may have to recover from a backup.
InnoDB: It is also possible that your operating
InnoDB: system has corrupted its own file cache
InnoDB: and rebooting your computer removes the
InnoDB: error.
InnoDB: If the corrupt page is an index page
InnoDB: you can also try to fix the corruption
InnoDB: by dumping, dropping, and reimporting
InnoDB: the corrupt table. You can use CHECK
InnoDB: TABLE to scan your table for corruption.
InnoDB: See also  http://dev.mysql.com/doc/refman/5.5/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
InnoDB: Ending processing because of a corrupt database page.
160226 11:00:30  InnoDB: Assertion failure in thread 140329989404736 in file buf0buf.c line 4032
InnoDB: We intentionally generate a memory trap.
InnoDB: Submit a detailed bug report to  http://bugs.mysql.com.
InnoDB: If you get repeated assertion failures or crashes, even
InnoDB: immediately after the mysqld startup, there may be
InnoDB: corruption in the InnoDB tablespace. Please refer to
InnoDB:  http://dev.mysql.com/doc/refman/5.5/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
160226 11:00:30 [ERROR] mysqld got signal 6 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
160226 11:00:28  InnoDB: Page dump in ascii and hex (16384 bytes):
max_threads=153
thread_count=0 
It is possible that mysqld could use up to 
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 466713 K  bytes of memory
Hope that's ok; if not, decrease some variables in the equation.

Thread pointer: 0x0x0 
Attempting backtrace. You can use the following information to find out
160226 11:00:19  InnoDB: Page dump in ascii and hex (16384 bytes):
InnoDB: End of page dump
160226 11:00:21  InnoDB: Page checksum 913642282 (32bit_calc: 472052024), prior-to-4.0.14-form checksum 2048873750
InnoDB: stored checksum 913642282, prior-to-4.0.14-form stored checksum 1622372148
InnoDB: Page lsn 0 142354744, low 4 bytes of lsn at page end 142348560
InnoDB: Page number (if stored to page already) 589,
InnoDB: space id (if created with >= MySQL-4.1.1 and stored already) 0
InnoDB: Page may be an update undo log page
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 589.
InnoDB: You may have to recover from a backup.
InnoDB: It is also possible that your operating
InnoDB: system has corrupted its own file cache
InnoDB: and rebooting your computer removes the
InnoDB: error.
InnoDB: If the corrupt page is an index page
InnoDB: you can also try to fix the corruption
InnoDB: by dumping, dropping, and reimporting
InnoDB: the corrupt table. You can use CHECK
InnoDB: TABLE to scan your table for corruption.
InnoDB: See also  http://dev.mysql.com/doc/refman/5.5/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
InnoDB: Ending processing because of a corrupt database page.
160226 11:00:21  InnoDB: Assertion failure in thread 139871429470272 in file buf0buf.c line 4032
InnoDB: We intentionally generate a memory trap.
InnoDB: Submit a detailed bug report to  http://bugs.mysql.com.
InnoDB: If you get repeated assertion failures or crashes, even
InnoDB: immediately after the mysqld startup, there may be
InnoDB: corruption in the InnoDB tablespace. Please refer to
InnoDB: http://dev.mysql.com/doc/refman/5.5/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
160226 11:00:21 [ERROR] mysqld got signal 6 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.

To report this bug, see  http://kb.askmonty.org/en/reporting-bugs

We will try our best to scrape up some info that will hopefully help
diagnose the problem, but since we have already crashed,
something is definitely wrong and this may fail.

Server version: 5.5.44-MariaDB
key_buffer_size=134217728
read_buffer_size=131072
max_used_connections=0
max_threads=153
thread_count=0
It is possible that mysqld could use up to
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 466713 K  bytes of memory
Hope that's ok; if not, decrease some variables in the equation.

Thread pointer: 0x0x0
Attempting backtrace. You can use the following information to find out
InnoDB: End of page dump
160226 11:00:30  InnoDB: Page checksum 913642282 (32bit_calc: 472052024), prior-to-4.0.14-form checksum 2048873750
InnoDB: stored checksum 913642282, prior-to-4.0.14-form stored checksum 1622372148
InnoDB: Page lsn 0 142354744, low 4 bytes of lsn at page end 142348560
InnoDB: Page number (if stored to page already) 589,
InnoDB: space id (if created with >= MySQL-4.1.1 and stored already) 0
InnoDB: Page may be an update undo log page
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 589.
InnoDB: You may have to recover from a backup.
InnoDB: It is also possible that your operating
InnoDB: system has corrupted its own file cache
InnoDB: and rebooting your computer removes the
InnoDB: error.
InnoDB: If the corrupt page is an index page
InnoDB: you can also try to fix the corruption
InnoDB: by dumping, dropping, and reimporting
or misconfigured. This error can also be caused by malfunctioning hardware.

To report this bug, see  http://kb.askmonty.org/en/reporting-bugs

We will try our best to scrape up some info that will hopefully help
diagnose the problem, but since we have already crashed,
something is definitely wrong and this may fail.

Server version: 5.5.44-MariaDB
key_buffer_size=134217728
read_buffer_size=131072
max_used_connections=0
max_threads=153
thread_count=0
It is possible that mysqld could use up to
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 466713 K  bytes of memory
Hope that's ok; if not, decrease some variables in the equation.

Thread pointer: 0x0x0
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = 0x0 thread_stack 0x48000
/usr/libexec/mysqld(my_print_stacktrace+0x3d)[0x7fa11fb574ed]
/usr/libexec/mysqld(handle_fatal_signal+0x515)[0x7fa11f76d385]
/lib64/libpthread.so.0(+0xf100)[0x7fa11ee9d100]
/lib64/libc.so.6(gsignal+0x37)[0x7fa11d6515f7]
/lib64/libc.so.6(abort+0x148)[0x7fa11d652ce8]
/usr/libexec/mysqld(+0x6971a2)[0x7fa11f9651a2]
/usr/libexec/mysqld(+0x6a8b17)[0x7fa11f976b17]
/usr/libexec/mysqld(+0x6919ee)[0x7fa11f95f9ee]
/usr/libexec/mysqld(+0x66313a)[0x7fa11f93113a]
/usr/libexec/mysqld(+0x655f93)[0x7fa11f923f93]
/usr/libexec/mysqld(+0x656dfc)[0x7fa11f924dfc]
/usr/libexec/mysqld(+0x65954e)[0x7fa11f92754e]
/usr/libexec/mysqld(+0x64290e)[0x7fa11f91090e]
/usr/libexec/mysqld(+0x5fbb9c)[0x7fa11f8c9b9c]
/usr/libexec/mysqld(_Z24ha_initialize_handlertonP13st_plugin_int+0x48)[0x7fa11f76f408]
/usr/libexec/mysqld(+0x37bff5)[0x7fa11f649ff5]
/usr/libexec/mysqld(_Z11plugin_initPiPPci+0x551)[0x7fa11f64fa61]
/usr/libexec/mysqld(+0x2ee4ba)[0x7fa11f5bc4ba]
/usr/libexec/mysqld(_Z11mysqld_mainiPPc+0x546)[0x7fa11f5bf5d6]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7fa11d63db15]
/usr/libexec/mysqld(+0x2e869d)[0x7fa11f5b669d]
The manual page at  http://dev.mysql.com/doc/mysql/en/crashing.html contains
information that should help you find out what is causing the crash.
160226 11:00:30 mysqld_safe mysqld from pid file /var/run/mariadb/mariadb.pid ended

三、接下来使用官方推荐的恢复数据方法:

1、设置恢复模式启动mysql(http://dev.mysql.com/doc/refman/5.5/en/forcing-innodb-recovery.html)

vim /etc/my.cnf

添加配置项:

innodb_force_recovery = 1

其中后面的值设置为1、如果1不想再逐步增加为2/3/4等。直到能启动mysql为止!!!

未分类

2、使用恢复模式重启mysql

systemctl restart mariadb

未分类

重启成功!!!!
测试数据库连接:mysql -uroot -p123456;

未分类

正常!!!

3、备份全部数据库表:

mysqldump -uroot -p123456 --all-databases  > all_mysql_backup.sql

未分类

4、清除mysql数据(清除之前务必先stop mysql服务):

未分类

systemctl stop mariadb
cp -r  /var/lib/mysql/ /var/lib/mysql.bak
rm -rf /var/lib/mysql/*

重启mysql服务:

未分类

正常模式在启动mysql:

vim /etc/my.cnf

注释配置项:

#innodb_force_recovery = 1

再重启:

systemctl restart mariadb

5、数据库恢复为以前密码123456:

mysqladmin -u root password 123456

未分类

6、使用之间备份的sql文件恢复数据:

mysql -uroot -p123456 -e "source /root/all_mysql_backup.sql"

未分类

查看恢复好的数据:

未分类

实验完成!!!

mysql(mariadb)新建用户及用户授权管理

仅新建一个newuser用户

方法一:

MariaDB [(none)]> create user newuser@localhost identified by '123456';
Query OK, 0 rows affected (0.22 sec)

MariaDB [(none)]> select user from mysql.user;
+---------+
| user    |
+---------+
| aa      |
| root    |
| root    |
|         |
| aa      |
| bb      |
| lcz     |
| my      |
| mytest  |
| newuser |
| nome    |
| root    |
|         |
| root    |
+---------+
14 rows in set (0.00 sec)

MariaDB [(none)]> 

方法二:

MariaDB [(none)]> insert into mysql.user(user,host,password) values('ggo','localhost',password('1234'));
Query OK, 1 row affected, 4 warnings (0.24 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.25 sec)

效果

[root@localhost ~]# mysql -uggo -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or g.
Your MariaDB connection id is 4
Server version: 5.5.52-MariaDB MariaDB Server

Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.

MariaDB [(none)]> 

新建一个my用户并且授权全部操作权限

MariaDB [(none)]> grant all privileges on *.* to my@localhost identified by '123456';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> select user from mysql.user;
+--------+
| user   |
+--------+
| aa     |
| root   |
| root   |
|        |
| aa     |
| bb     |
| lcz    |
| my     |
| mytest |
| nome   |
| root   |
|        |
| root   |
+--------+
13 rows in set (0.14 sec)

MariaDB [(none)]>

查看用户权限

MariaDB [(none)]> show grants for my@localhost;
+--------------------------------------------------------------------------------------------------------------------+
| Grants for my@localhost                                                                                            |
+--------------------------------------------------------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'my'@'localhost' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' |
+--------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

MariaDB [(none)]> 

指定部分授权

grant insert,update,delete,select on *.* to mytest@localhost;

python使用sqlalchemy连接mysql数据库

sqlalchemy是python当中比较出名的orm程序。

什么是orm?

orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的,为了保证一致的使用习惯,通过orm将编程语言的对象模型和数据库的关系模型建立映射关系,这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型进行操作就可以了,而不用直接使用sql语言。

什么是sqlalchemy?

sqlalchemy是python的orm程序,在整个python界当中相当出名。

安装sqlalchemy

在使用sqlalchemy之前要先给python安装mysql驱动,由于我使用的是python3原来的mysqldb不可用,所以这里推荐使用pymysql。
我们通过pip进行安装,在windows下使用pip安装包的时候要记得使用管理员身份运行cmd不然有些操作是无法进行的。

pip install pymysql

安装完以后安装再安装sqlalchemy

pip install sqlalchemy

如何使用sqlalchemy连接mysql?

通过import导入必要的包

from sqlalchemy import create_engine,Table,Column,Integer,String,MetaData,ForeignKey

创建一个连接引擎

engine=create_engine("mysql+pymysql://root:a5230411@localhost:3306/test",echo=True)

我们将连接引擎放到engine里面方便后面使用。
create_engine(“数据库类型+数据库驱动://数据库用户名:数据库密码@IP地址:端口/数据库”,其他参数)
上文当中echo=True是开启调试,这样当我们执行文件的时候会提示相应的文字。

创建元数据

什么是元数据?元数据就是描述数据的数据,举个简单的例子,小明身高170cm,体重50kg,性别男。其中身高,体重,性别就是元数据。当我们创建好连接引擎以后可以通过这个引擎抓取元数据。

metadata=MetaData(engine)

通过MetaData()方法创建了metadata实例,在这个方法里面带上engine的目的是绑定要连接引擎,当我们对这个metadata实例进行操作的时候就会直接连接到数据库。

添加表结构

设定好连接引擎和元数据,让我们向mysql里面创建表结构来进行测试。

user=Table('user',metadata,
    Column('id',Integer,primary_key=True),
    Column('name',String(20)),
    Column('fullname',String(40)),
    )
address_table = Table('address', metadata,
    Column('id', Integer, primary_key=True),
    Column('user_id', None, ForeignKey('user.id')),
    Column('email', String(128), nullable=False)
    )

其中Table()方法用来创建表,第一个参数为表明,第二是存入元数据,后面的参数使用Column()方法将数据库当中每一个字段的数据参数设置好。

执行创建

metadata.create_all()

因为已将将表结构存到了metadata里面,然后让metadata执行create_all()方法,这样就向数据库里创建了user和address表。

完成代码

from sqlalchemy import create_engine,Table,Column,Integer,String,MetaData,ForeignKey
engine=create_engine("mysql+pymysql://root:a5230411@localhost:3306/test",echo=True)
metadata=MetaData(engine)

user=Table('user',metadata,
    Column('id',Integer,primary_key=True),
    Column('name',String(20)),
    Column('fullname',String(40)),
    )
address_table = Table('address', metadata,
    Column('id', Integer, primary_key=True),
    Column('user_id', None, ForeignKey('user.id')),
    Column('email', String(128), nullable=False)
    )

metadata.create_all()

CentOS 7 rpm安装mysql 5.7.18

最近一直使用MySQL,mysql-Linux下安装写了使用其他方式安装mysql,这次主要采用rpm格式来安装,试了一下感觉这种安装模式比较简单。

卸载MariaDB

centos7默认安装MariaDB而不是mysql,可能MariaDB数据库和mysql会冲突,故先卸载MariaDB。

1、查看已安装MariaDB相关的包

rpm -qa | grep mariadb

2、查看已安装的MariaDB相关yum包,包需根据rpm命令的结果判断

yum list mariadb-libs

3、移除已安装的MariaDB相关的yum包,包名需根据yum list命令结果判断,此步骤需要root权限

yum remove mariadb-libs

下载mysql rpm包

下面是官网的下载地址:
https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.18-1.el7.x86_64.rpm-bundle.tar

使用rpm安装mysql

下面步骤需要root权限,各个包之间有依赖关系,故rpm命令必须按顺序执行。

mkdir mysql
tar -xv -f mysql-5.7.18-1.el7.x86_64.rpm-bundle.tar -C mysql
cd mysql
rpm -ivh mysql-community-common-5.7.18-1.el7.x86_64.rpm
rpm -ivh mysql-community-libs-5.7.18-1.el7.x86_64.rpm
rpm -ivh mysql-community-client-5.7.18-1.el7.x86_64.rpm
rpm -ivh mysql-community-server-5.7.18-1.el7.x86_64.rpm

出现的问题:

1、libaio.so.1()(64bit) is needed by MySQL-server

解决方案:

安装libaio-0.3.107-10.el6.x86_64.rpm

①下载地址:

http://mirror.centos.org/centos/6/os/x86_64/Packages/libaio-0.3.107-10.el6.x86_64.rpm

②执行:

rpm -ivh libaio-0.3.107-10.el6.x86_64.rpm

2、net-tools is needed

解决方案:

yum install net-tools

3、perl(Getopt::Long) 被 mysql-community-server-5.7.18-1.el7.x86_64 需要

解决方案:

yum install perl

安装成功后,删除安装文件和临时文件,也可以不删除。

登录mysql,修改初始密码

以下步骤需要root权限。
1、由于一开始并不知道密码,先修改配置文件/etc/my.cnf,让mysql跳过登录时的权限验证。加入一行:

vi /etc.my.cnf
skip-grant-tables 

未分类

2、更改MySQL数据库目录的所属用户及其所属组,然后启动mysql

chown -R mysql:mysql /var/lib/mysql/ 
systemctl start mysqld.service //启动mysql数据库服务 

3、登录

mysql -uroot -p

4、修改密码

use mysql; 
update user set authentication_string =password('你自己的密码') where host ='localhost' and user='mysql';
quit;

5、使用密码重新登录

mysql -uroot -p

ubuntu mysql远程连接+phpmyadmin安装

一、如何让ubuntu上的mysql允许远程连接

进入MySQL,执行如下命令:

use mysql;

GRANT ALL PRIVILEGES ON *.* TO 'username'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;

flush privileges; //刷新

select host,user from user; //查看是否成功

退出mysql;

  • 打开sudo vim /etc/mysql/my.cnf(可能不是此路径,也可能是my。conf,在该目录下找一下)
  • 将bind-address = 127.0.0.1
  • 设置成bind-address = 0.0.0.0(设备地址)

重新启动(命令如下):

sudo /etc/init.d/mysql restart

这样就可以远程连接了!

二、ubuntu如何安装phpmyadmin

方法一:

在phpmyadmin官网(https://www.phpmyadmin.net/)上下载压缩包,解压至你apache根目录下(默认/var/www/html),重命名为phpmyadmin;

sudo apt-get install php-mbstring php-gettext

然后修改PHP配置文件:

sudo vim /etc/php/7.0/apache/php/ini
display_errors = On(都改为On)
extension=php_mbstring.dll (去掉前面的;)

重启apache:

sudo /etc/init.d/apache2 restart

可以用http://localhost/phpmyadmin访问了!

方法二:

sudo apt-get install phpmyadmin

建立/var/www/html 下的软连接:

sudo ln -s /usr/share/phpmyadmin /var/www/html/phpmyadmin

安装php-mbstring和php.ini配置同方法一。

mysql5.7 phpMyAdmin Access denied for user ‘root’@’localhost’

遇到这种报错,先检查MySQL版本,如果是5.7的话,那默认是不允许phpmyadmin使用root登录的。
解决办法是,建立一个phpmyadmin专用账户,流程如下:

1. 进入mysql命令行

sudo mysql --user=root mysql

2. 创建phpmyadmin用户

CREATE USER 'phpmyadmin'@'localhost' IDENTIFIED BY '你的密码';
GRANT ALL PRIVILEGES ON *.* TO 'phpmyadmin'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;

3. 用刚才创建的用户登录即可

方法来自:https://askubuntu.com/questions/763336/cannot-enter-phpmyadmin-as-root-mysql-5-7