OTPUB知识课堂:​Oracle RDA工具简介

OT学习平台 发表了文章 0 个评论 2827 次浏览 2017-09-15 15:46 来自相关话题

Oracle RDA英文全称叫做“Oracle Remote Diagnostic Agent”。它是Oracle用来收集、分析数据库信息的工具,它是用perl编写的,包含非常丰富的诊断脚本,使用它科技非常便捷的采集到Oracle数据库服务器系统配置和数据库的 ...查看全部
Oracle RDA英文全称叫做“Oracle Remote Diagnostic Agent”。它是Oracle用来收集、分析数据库信息的工具,它是用perl编写的,包含非常丰富的诊断脚本,使用它科技非常便捷的采集到Oracle数据库服务器系统配置和数据库的详细信息,运行该工具不会改变系统的任何参数。
RDA收集的相关数据非常全面,可以简化我们日常监控、分析数据库的工作。Oracle Support也建议我们在反馈相关问题时,提供RDA收集的数据,这样可以为快速解决问题提供一个有力的保证。
Oracle作为目前行业最成熟的商业数据库管理系统软件,Oracle开发出很多有助于系统调试和运维的工具。借助这些优秀的免费工具,可以大大方便我们日常运维和管理工作。
无论是作为专业DBA,还是第三方支持人员,数据库巡检都是日常工作中不可缺少的工作内容。巡检项目通常是设置好的项目内容,有时候我们还会准备一些脚本或者命令作为手机手段。
巡检项目类型也会包括从操作系统,硬性文件系统,到数据库内存配置等广泛的内容,可能大多人员都会借助于AWR报告,同时,我们还可以借助Oracle提供的RDA来完成。
RDA全称Oracle Remote Diagnostic Agent(RDA)-RDA文档索引,RDA是Oracle用来收集,分析数据库的工具,运行该工具不会改变系统的任何参数,RDA收集的相关数据非常全面,这个Oracle诊断工具是用perl编写的,包含非常丰富的诊断脚本,使用它可以分成便利的采集到oracle数据库服务器系统配置和数据库的详细信息。可以简化我们的日常监控、分析数据库的工作。一般Oracle原厂的巡检也是使用RDA工具,不过一般国内的DBA巡检时很少使用这个工具,一般都是通过AWR或者自己整几个脚本跑一下,分析一下就OK了。
通过RDA可以快速的了解系统的状况,将会大大的缩短问题处理的周期,避免信息的反复采集。RDA不会更改数据库服务器的任何配置,仅仅是采集信息。
想要更详细的了解Oracle RDA工具的使用方法,请进入OTPUB技术课堂:http://www.otpub.com/Course/detail/index/id/210.html

MySQL主从同步那点事儿

Rock 发表了文章 0 个评论 2916 次浏览 2017-09-10 22:06 来自相关话题

一、前言​ 关于mysql主从同步,相信大家都不陌生,随着系统应用访问量逐渐增大,单台数据库读写访问压力也随之增大,当读写访问达到一定瓶颈时,将数据库的读写效率骤然下降,甚至不可用;为了解决此类问题,通常会采用mysql集群,当主库宕机后,集群会自 ...查看全部
一、前言​
关于mysql主从同步,相信大家都不陌生,随着系统应用访问量逐渐增大,单台数据库读写访问压力也随之增大,当读写访问达到一定瓶颈时,将数据库的读写效率骤然下降,甚至不可用;为了解决此类问题,通常会采用mysql集群,当主库宕机后,集群会自动将一个从库升级为主库,继续对外提供服务;那么主库和从库之间的数据是如何同步的呢?本文针对MySQL 5.7版本进行下面的分析,下面随笔者一起探究一下mysql主从是如何同步的。
 
二、MySQL主从复制原理
为了减轻主库的压力,应该在系统应用层面做读写分离,写操作走主库,读操作走从库,下图为MySQL官网给出的主从复制的原理图,从图中可以简单的了解读写分离及主从同步的过程,分散了数据库的访问压力,提升整个系统的性能和可用性,降低了大访问量引发数据库宕机的故障率。
mysqlrep.png

 
三、binlog简介
MySQL主从同步是基于binlog文件主从复制实现,为了更好的理解主从同步过程,这里简单介绍一下binlog日志文件。

binlog日志用于记录所有更新了数据或者已经潜在更新了数据(例如,没有匹配任何行的一个DELETE)的所有语句。语句以“事件”的形式保存,它描述数据更改,它是以二进制的形式保存在磁盘中。我们可以通过mysql提供的查看工具mysqlbinlog查看文件中的内容,例如 mysqlbinlog mysql-bin.00001 | more,这里注意一下binlog文件的后缀名00001,binlog文件大小和个数会不断的增加,当MySQL停止或重启时,会产生一个新的binlog文件,后缀名会按序号递增,例如mysql-bin.00002、mysql-bin.00003,并且当binlog文件大小超过 max_binlog_size系统变量配置时也会产生新的binlog文件。
 
(一)binlog日志格式
(1) statement : 记录每一条更改数据的sql;
  • 优点:binlog文件较小,节约I/O,性能较高。
  • 缺点:不是所有的数据更改都会写入binlog文件中,尤其是使用MySQL中的一些特殊函数(如LOAD_FILE()、UUID()等)和一些不确定的语句操作,从而导致主从数据无法复制的问题。
 (2) row : 不记录sql,只记录每行数据的更改细节
  • 优点:详细的记录了每一行数据的更改细节,这也意味着不会由于使用一些特殊函数或其他情况导致不能复制的问题。
  • 缺点:由于row格式记录了每一行数据的更改细节,会产生大量的binlog日志内容,性能不佳,并且会增大主从同步延迟出现的几率。
 (3) mixed:一般的语句修改使用statment格式保存binlog,如一些函数,statement无法完成主从复制的操作,则采用row格式保存binlog,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种。 (二)binlog日志内容
binlog.png
 (三)binlog事件类型MySQL binlog记录的所有操作实际上都有对应的事件类型的,譬如STATEMENT格式中的DML操作对应的是QUERY_EVENT类型,ROW格式下的DML操作对应的是ROWS_EVENT类型,如果想了解更多请参考官方文档,有关binlog日志内容不在这里过多赘述,简单介绍一下是为了更好的理解主从复制的细节,下面我们进入正题。  四、MySQL主从复制原理mysql主从复制需要三个线程,master(binlog dump thread)、slave(I/O thread 、SQL thread)。  Master(1)binlog dump线程:当主库中有数据更新时,那么主库就会根据按照设置的binlog格式,将此次更新的事件类型写入到主库的binlog文件中,此时主库会创建log dump线程通知slave有数据更新,当I/O线程请求日志内容时,会将此时的binlog名称和当前更新的位置同时传给slave的I/O线程。 Slave(2)I/O线程:该线程会连接到master,向log dump线程请求一份指定binlog文件位置的副本,并将请求回来的binlog存到本地的relay log中,relay log和binlog日志一样也是记录了数据更新的事件,它也是按照递增后缀名的方式,产生多个relay log( host_name-relay-bin.000001)文件,slave会使用一个index文件( host_name-relay-bin.index)来追踪当前正在使用的relay log文件。 (3)SQL线程:该线程检测到relay log有更新后,会读取并在本地做redo操作,将发生在主库的事件在本地重新执行一遍,来保证主从数据同步。此外,如果一个relay log文件中的全部事件都执行完毕,那么SQL线程会自动将该relay log 文件删除掉。 下面是整个复制过程的原理图:
mysqlab.png
 四、主从同步延迟mysql的主从复制都是单线程的操作,主库对所有DDL和DML产生binlog,binlog是顺序写,所以效率很高,slave的I/O线程到主库取日志,效率也比较高,但是,slave的SQL线程将主库的DDL和DML操作在slave实施。DML和DDL的IO操作是随即的,不是顺序的,成本高很多,还可能存在slave上的其他查询产生lock争用的情况,由于SQL也是单线程的,所以一个DDL卡住了,需要执行很长一段事件,后续的DDL线程会等待这个DDL执行完毕之后才执行,这就导致了延时。当主库的TPS并发较高时,产生的DDL数量超过slave一个sql线程所能承受的范围,延时就产生了,除此之外,还有可能与slave的大型query语句产生了锁等待导致。 由于主从同步延迟是客观存在的,我们只能从我们自己的架构上进行设计, 尽量让主库的DDL快速执行。下面列出几种常见的解决方案:[list=1]
  • 业务的持久化层的实现采用分库架构,mysql服务可平行扩展,分散压力。
  • 服务的基础架构在业务和mysql之间加入memcache或者Redis的cache层。降低mysql的读压力;
  • 使用比主库更好的硬件设备作为slave;
  • sync_binlog在slave端设置为0;
  • –logs-slave-updates 从服务器从主服务器接收到的更新不记入它的二进制日志。
  • 禁用slave的binlog

  •  
    五、参考资料
    https://dev.mysql.com/doc/refman/5.7/en/replication.html  
    http://www.linuxidc.com/Linux/2014-05/101450.htm  
    http://blog.csdn.net/xiongping_/article/details/49907095  
    http://www.cnblogs.com/martinzhang/p/3454358.html  
    “本文转载自 linkedkeeper.com (文/张松然)”地址:http://www.linkedkeeper.com/detail/blog.action?bid=1028  

    MYSQL开发实践8问8答

    chris 发表了文章 1 个评论 2652 次浏览 2017-08-20 13:59 来自相关话题

    最近研发的项目对 DB 依赖比较重,梳理了这段时间使用MySQL遇到的8个比较具有代表性的问题,答案也比较偏自己的开发实践,没有 DBA专业和深入,有出入的请使劲拍砖!   一、MySQL读写性能是多少,有哪些性能相关的重 ...查看全部
    最近研发的项目对 DB 依赖比较重,梳理了这段时间使用MySQL遇到的8个比较具有代表性的问题,答案也比较偏自己的开发实践,没有 DBA专业和深入,有出入的请使劲拍砖!
     


    一、MySQL读写性能是多少,有哪些性能相关的重要参数?​


    这里做了几个简单压测实验,结果如下:
    机器:8核CPU,8G内存
    表结构(尽量模拟业务):12个字段(1个bigint(20)为自增primary key,5个int(11),5个varchar(512),1个timestamp),InnoDB存储引擎。
    实验1(写):insert => 6000/s
    前提:连接数100,每次insert单条记录
    分析:CPU跑了50%,这时磁盘为顺序写,故性能较高
    实验2(写):update(where条件命中索引) => 200/s
    前提:连接数100,10w条记录,每次update单条记录的4个字段(2个int(11),2个varchar(512))
    分析:CPU跑2%,瓶颈明显在IO的随机写
    实验3(读):select(where条件命中索引) => 5000/s
    前提:连接数100,10w条记录,每次select单条记录的4个字段(2个int(11),2个varchar(512))
    分析:CPU跑6%,瓶颈在IO,和db的cache大小相关
    实验4(读):select(where条件没命中索引) => 60/s
    前提:连接数100,10w条记录,每次select单条记录的4个字段(2个int(11),2个varchar(512))
    分析:CPU跑到80%,每次select都需遍历所有记录,看来索引的效果非常明显!
    几个重要的配置参数,可根据实际的机器和业务特点调整
    max_connecttions:最大连接数

    table_cache:缓存打开表的数量

    key_buffer_size:索引缓存大小

    query_cache_size:查询缓存大小

    sort_buffer_size:排序缓存大小(会将排序完的数据缓存起来)

    read_buffer_size:顺序读缓存大小

    read_rnd_buffer_size:某种特定顺序读缓存大小(如order by子句的查询)
    PS:查看配置方法:show variables like '%max_connecttions%';
     


    二、MySQL负载高时,如何找到是由哪些SQL引起的?


    方法:慢查询日志分析(MySQLdumpslow)
     
    慢查询日志例子,可看到每个慢查询SQL的耗时:
    # User@Host: edu_online[edu_online] @  [10.139.10.167]
    # Query_time: 1.958000 Lock_time: 0.000021 Rows_sent: 254786 Rows_examined: 254786
    SET timestamp=1410883292;
    select * from t_online_group_records;
    日志显示该查询用了1.958秒,返回254786行记录,一共遍历了254786行记录。及具体的时间戳和SQL语句。

    使用MySQLdumpslow进行慢查询日志分析:

    MySQLdumpslow -s t -t 5 slow_log_20140819.txt
    输出查询耗时最多的Top5条SQL语句
     
    -s:排序方法,t表示按时间 (此外,c为按次数,r为按返回记录数等)
    -t:去Top多少条,-t 5表示取前5条
     
    执行完分析结果如下:
    Count: 1076100  Time=0.09s (99065s)  Lock=0.00s (76s)  Rows=408.9 (440058825), edu_online[edu_online]@28hosts
    select * from t_online_group_records where UNIX_TIMESTAMP(gre_updatetime) > N
    Count: 1076099 Time=0.05s (52340s) Lock=0.00s (91s) Rows=62.6 (67324907), edu_online[edu_online]@28hosts
    select * from t_online_course where UNIX_TIMESTAMP(c_updatetime) > N
    Count: 63889 Time=0.78s (49607s) Lock=0.00s (3s) Rows=0.0 (18), edu_online[edu_online]@[10x.213.1xx.1xx]
    select f_uin from t_online_student_contact where f_modify_time > N
    Count: 1076097 Time=0.02s (16903s) Lock=0.00s (72s) Rows=52.2 (56187090), edu_online[edu_online]@28hosts
    select * from t_online_video_info where UNIX_TIMESTAMP(v_update_time) > N
    Count: 330046 Time=0.02s (6822s) Lock=0.00s (45s) Rows=0.0 (2302), edu_online[edu_online]@4hosts
    select uin,cid,is_canceled,unix_timestamp(end_time) as endtime,unix_timestamp(update_time) as updatetime
    from t_kick_log where unix_timestamp(update_time) > N
    以第1条为例,表示这类SQL(N可以取很多值,这里MySQLdumpslow会归并起来)在8月19号的慢查询日志内出现了1076100次,总耗时99065秒,总返回440058825行记录,有28个客户端IP用到。

    通过慢查询日志分析,就可以找到最耗时的SQL,然后进行具体的SQL分析

    慢查询相关的配置参数:
    log_slow_queries:是否打开慢查询日志,得先确保=ON后面才有得分析

    long_query_time:查询时间大于多少秒的SQL被当做是慢查询,一般设为1S

    log_queries_not_using_indexes:是否将没有使用索引的记录写入慢查询日志

    slow_query_log_file:慢查询日志存放路径


    三、如何针对具体的SQL做优化?


    使用Explain分析SQL语句执行计划
    MySQL> explain select * from t_online_group_records where UNIX_TIMESTAMP(gre_updatetime) > 123456789;
    +----+-------------+------------------------+------+---------------+------+---------+------+------+-------------+
    | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
    +----+-------------+------------------------+------+---------------+------+---------+------+------+-------------+
    | 1 | SIMPLE | t_online_group_records | ALL | NULL | NULL | NULL | NULL | 47 | Using where |
    +----+-------------+------------------------+------+---------------+------+---------+------+------+-------------+
    1 row in set (0.00 sec)
    如上面例子所示,重点关注下type,rows和Extra:

    type:使用类别,有无使用到索引。结果值从好到坏:... > range(使用到索引) > index > ALL(全表扫描),一般查询应达到range级别

    rows:SQL执行检查的记录数

    Extra:SQL执行的附加信息,如"Using index"表示查询只用到索引列,不需要去读表等

    使用Profiles分析SQL语句执行时间和消耗资源:
    MySQL> set profiling=1; (启动profiles,默认是没开启的)
    MySQL> select count(1) from t_online_group_records where UNIX_TIMESTAMP(gre_updatetime) > 123456789; (执行要分析的SQL语句)
    MySQL> show profiles;
    +----------+------------+----------------------------------------------------------------------------------------------+
    | Query_ID | Duration | Query |
    +----------+------------+----------------------------------------------------------------------------------------------+
    | 1 | 0.00043250 | select count(1) from t_online_group_records where UNIX_TIMESTAMP(gre_updatetime) > 123456789 |
    +----------+------------+----------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    MySQL> show profile cpu,block io for query 1; (可看出SQL在各个环节的耗时和资源消耗)
    +----------------------+----------+----------+------------+--------------+---------------+
    | Status | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
    +----------------------+----------+----------+------------+--------------+---------------+
    ...
    | optimizing | 0.000016 | 0.000000 | 0.000000 | 0 | 0 |
    | statistics | 0.000020 | 0.000000 | 0.000000 | 0 | 0 |
    | preparing | 0.000017 | 0.000000 | 0.000000 | 0 | 0 |
    | executing | 0.000011 | 0.000000 | 0.000000 | 0 | 0 |
    | Sending data | 0.000076 | 0.000000 | 0.000000 | 0 | 0 |
    ...

    SQL优化的技巧 (只提一些业务常遇到的问题)
     
    1、最关键:索引,避免全表扫描
    对接触的项目进行慢查询分析,发现TOP10的基本都是忘了加索引或者索引使用不当,如索引字段上加函数导致索引失效等(如where UNIX_TIMESTAMP(gre_updatetime)>123456789)
    +----------+------------+---------------------------------------+
    | Query_ID | Duration | Query |
    +----------+------------+---------------------------------------+
    | 1 | 0.00024700 | select * from mytable where id=100 |
    | 2 | 0.27912900 | select * from mytable where id+1=101 |
    +----------+------------+---------------------------------------+
    另外很多同学在拉取全表数据时,喜欢用select xx from xx limit 5000,1000这种形式批量拉取,其实这个SQL每次都是全表扫描,建议添加1个自增id做索引,将SQL改为 select xx from xx where id>5000 and id<6000;
    +----------+------------+-----------------------------------------------------+
    | Query_ID | Duration | Query |
    +----------+------------+-----------------------------------------------------+
    | 1 | 0.00415400 | select * from mytable where id>=90000 and id<=91000 |
    | 2 | 0.10078100 | select * from mytable limit 90000,1000 |
    +----------+------------+-----------------------------------------------------+
    合理用好索引,应该可解决大部分SQL问题。当然索引也非越多越好,过多的索引会影响写操作性能。
     
    1.1 只select出需要的字段,避免select
    +----------+------------+-----------------------------------------------------+
    | Query_ID | Duration | Query |
    +----------+------------+-----------------------------------------------------+
    | 1 | 0.02948800 | select count(1) from ( select id from mytable ) a |
    | 2 | 1.34369100 | select count(1) from ( select * from mytable ) a |
    +----------+------------+-----------------------------------------------------+
    1.2 尽量早做过滤,使Join或者Union等后续操作的数据量尽量小
     
    1.3 把能在逻辑层算的提到逻辑层来处理,如一些数据排序、时间函数计算等
     
    PS:关于SQL优化,已经有足够多文章了,所以就不讲太全面了,只重点说自己1个感受:索引!基本都是因为索引!
     


    四、SQL层面已难以优化,请求量继续增大时的应对策略?


    下面是我能想到的几个方法,每个方法又都是一篇大文章了,这里就不展开。
    • 分库分表
    • 使用集群(master-slave),读写分离
    • 增加业务的cache层
    • 使用连接池

    五、MySQL如何做主从数据同步?

    复制机制(Replication)master通过复制机制,将master的写操作通过binlog传到slave生成中继日志(relaylog),slave再将中继日志redo,使得主库和从库的数据保持同步。 复制相关的3个MySQL线程:[list=1]
  • slave上的I/O线程:向master请求数据
  • master上的Binlog Dump线程:读取binlog事件并把数据发送给slave的I/O线程
  • slave上的SQL线程:读取中继日志并执行,更新数据库
  • 属于slave主动请求拉取的模式 实际使用可能遇到的问题数据非强一致:CDB默认为异步复制,master和slave的数据会有一定延迟(称为主从同步距离,一般 < 1s)主从同步距离变大:可能是DB写入压力大,也可能是slave机器负载高,网络波动等原因,具体问题具体分析 相关监控命令
    show processlist:查看MySQL进程信息,包括3个同步线程的当前状态show master status :查看master配置及当前复制信息show slave status:查看slave配置及当前复制信息

    六、如何防止DB误操作和做好容灾?

    业务侧应做到的几点:
    • 重要DB数据的手工修改操作,操作前需做到2点:1 先在测试环境操作 2 备份数据
    • 根据业务重要性做定时备份,考虑系统可承受的恢复时间
    • 进行容灾演练,感觉很必要
     MySQL备份和恢复操作 1、备份:使用MySQLdump导出数据
    MySQLdump -u 用户名 -p 数据库名 [表名] > 导出的文件名MySQLdump -uxxx -p xxx mytable > mytable.20140921.bak.sql
    2、恢复:导入备份数据
    MySQL -uxxx -p xxxx < mytable.20140921.bak.sql
    3、恢复:导入备份数据之后发送的写操作。先使用MySQLbinlog导出这部分写操作SQL(基于时间点或位置)如导出2014-09-21 09:59:59之后的binlog:
    MySQLbinlog --database="test" --start-date="2014-09-21 09:59:59" /var/lib/MySQL/mybinlog.000001 > binlog.data.sql
    如导出起始id为123456之后的binlog:
    MySQLbinlog --database="test" --start-position="123456" /var/lib/MySQL/mybinlog.000001 > binlog.data.sql
    最后把要恢复的binlog导入db
    MySQL -uxxxx -p xxxx < binlog.data.sql

    七、该选择MySQL哪种存储引擎,Innodb具有什么特性?

    存储引擎简介:插件式存储引擎是MySQL的重要特性,MySQL支持多种存储引擎以满足用户的多种应用场景存储引擎解决的问题:如何组织MySQL数据在介质中高效地读取,需考虑存储机制、索引设计、并发读写的锁机制等MySQL5.0支持的存储引擎有MyISAM、InnoDB、Memory、Merge等 MyISAM和InnoDB的区别(只说重点了) 1. InnoDB,MySQL5.5之后及CDB的默认引擎
    • 支持行锁:并发性能好
    • 支持事务:故InnoDB称为事务性存储引擎,支持ACID,提供了具有提交、回滚和崩溃恢复能力的事务安全
    • 支持外键:当前唯一支持外键的引擎
     2. MyISAM,MySQL5.5之前默认引擎
    • 支持表锁:插入+查询速度快,更新+删除速度慢
    • 不支持事务
     使用show engines可查看当前MySQL支持的存储引擎详情:
    engine.png
     

    八、MySQL内部结构有哪些层次?

     非专业DBA,这里只简单贴个结构图说明下。MySQL是开源系统,其设计思路和源代码都出自大牛之手,有空可以学习下。
    connect.png
    [list=1]
  • Connectors:连接器。接收不同语言的Client交互
  • Management Serveices & Utilities:系统管理和控制工具
  • Connection Pool: 连接池。管理用户连接
  • SQL Interface: SQL接口。接受用户的SQL命令,并且返回用户需要查询的结果
  • Parser: 解析器。验证和解析SQL语句成内部数据结构
  • Optimizer: 查询优化器。为查询语句选择合适的执行路径
  • Cache和Buffer:查询缓存。缓存查询的结果,有命中即可直接返回
  • Engine:存储引擎。MySQL数据最后组织并存储成具体文件

  •  
    作者:王昂 
    原文地址:https://www.qcloud.com/community/article/233 

    InnoDB: Error: Table "mysql"."innodb_table_stats" not found.

    空心菜 回复了问题 2 人关注 1 个回复 4341 次浏览 2017-07-18 22:02 来自相关话题

    MySQL之BLGC介绍

    Rock 发表了文章 0 个评论 4413 次浏览 2017-07-08 23:51 来自相关话题

    一、组提交介绍 1.1 什么是组提交 Binary Log Group Commit 即二进制日志组提交。这是 MySQL5.6 版本中引进的一个新的特性。为什么需要引进这个特性呢?我们知道当我们把 MySQL 的 bin ...查看全部


    一、组提交介绍


    1.1 什么是组提交
    Binary Log Group Commit 即二进制日志组提交。这是 MySQL5.6 版本中引进的一个新的特性。为什么需要引进这个特性呢?我们知道当我们把 MySQL 的 binlog 开启的时候,MySQL 会将每个事务的操作都记录到 binlog 中,方便我们使用 binlog 来完成复制或者恢复操作。可是需要调用 fsync() 才能将缓存中被更改的 binlog 真正的写到磁盘上,保证数据的持久化。但是这是一个从内存写到磁盘的过程,I/O 比较慢。如果每次事务提交都执行一遍 fsync() 将 binlog 持久化落盘到磁盘的话,效率很低。于是就想,能不能等几个事务的 binlog 一起调用一次 fsync(),一次性落盘。减少 fsync() 的次数,从而提高效率。这就是二进制日志组提交的概念。
     


    二、两阶段提交


    2.1 为什么需要二阶段提交
    我们知道在 MySQL 中不仅仅有 binlog,还有 redo log 和 undo log 。binlog 用来记录每个事务的操作信息,redo 是在数据库宕机恢复时使用,用来恢复数据库数据,undo 用来回滚还未被提交的数据。binlog 是在数据库 Server 层产生的,即它会记录所有存储引擎中事务的操作,而 redo 是 InnoDB 存储引擎特有的日志。

    在事务提交的时候,我们需要先写入二进制日志,再写 InnoDB 存储引擎的 redo。并且要求二进制日志和 redo 要么都写,要么都不写。不然可能会出现这样的情况:在主从复制的环境下,master 提交了一个事务,先写了二进制日志,但是在要写 InnoDB 存储引擎的时候,数据库发生了宕机,此时 binlog 又已经被 slave 接收到了,slave 会执行这个事务,但是实际 master 上并没有这个事务。这就会导致主从数据的不一致。所以我们引入了二阶段提交来解决这个问题,即将写 binlog 操作个 InnoDB 提交操作通过事务变成原子的。
     
    2.2 什么是二阶段提交
    所谓的二阶段提交就是,我在事务提交的时候,确保先将 binlog 写入,然后再到数据引擎层提交,并且这两个操作是原子的。在 MySQL 中用内部的 XA 事务来完成,即将这两个操作包装成一个事务的概念。
    twocommit.png

    上图表示了二阶段提交的过程。当一个会话中的某一事务 COMMIT 的时候,进去二阶段提交的过程。首先数据库先去协调 Server 层和 Engine,询问是否都可以开始写日志,这个过程就是图中的的 prepare 阶段。协调好两层之间的关系,Server 层和 Engine 层都表示可以写日志,这时候进入下一个过程。

    第二个过程就是写 binlog 的过程,先把 binlog 写到内存中,然后调用 fsync() 将 binlog 从内存写到磁盘上。

    第三个过程就是在存储引擎层提交的过程,将真实修改的数据提交到数据库中。当这一步完成才最终返回给会话一个 COMMIT 成功的信号。

    这整个过程就是二阶段提交的过程,如果在 fsync() 之前数据库 crash 了,重启之后数据将会被回滚,若在 fsync() 之后 crash,则会进行重做操作。通过二阶段提交的方式就保证了存储引擎与二进制日志保持一致
     


    三、三阶段提交


    3.1 为什么需要三阶段提交
    上面的二阶段提交是针对单一事务提交时候的操作顺序,下面我们来看看当多个事务并发的时候会是什么样的一个情况。
    t3commit.png

    现在有T1、T2、T3 三个事务需要执行,从图中可以看到数据在 fsync() 之前,三个事务已经写入到了 binlog 中,通过 fsync() 操作将 binlog 刷到磁盘。之后先是 T2 COMMIT,将数据更改更新到存储引擎层,接着是 T3 COMMIT,将数据更新到存储引擎层。这时候我们做了一个热备份的操作,有多种方式进行数据库的热备份,比如:XtraBackup等。这时候就会发生错误。会发生什么错误,我们需要先了解一下 XtraBackup 等热备工具的备份原理。

    XtraBackup备份原理:直接拷贝数据库文件,并且记录下当前二进制日志中已经提交的最后一个事务标记。在新的数据库实例上完成 recovery 操作。

    了解完备份原理之后,我们就可以想到上述情况下做热备会出现什么情况。因为 T2、T3 已经提交,所以备份的时候会记录下 T3 是最后一个提交的事务,会认为 T3 之前的事务都是已经提交的,由于是直接拷贝数据库文件,可以看到 T1 事务的数据还没有提交到存储引擎层,所以备份数据中还并没有 T1 的数据。如果新的数据库是用来做主从复制的话,change master to 会指向二进制日志中 T3 的位置,从 T3 事务开始往后进行复制,这样一来 T1 事务的数据就这样没了。产生这个问题的主要原因就是:事务写入二进制日志的顺序与事务在存储引擎层提交的顺序不一致。

    为了解决这个问题,MySQL 引入了 prepare_commit_mutext 的机制,当事务提交的时候,需要先获得 prepare_commit_mutext 这个锁。有了这个锁就可以保证事务写入二进制日志的顺序与事务在存储引擎层提交的顺序一致。
    3tcommit.png

    但是这样一来,从图中我们也可以看到,原先是并发的事务,又变成了串行的,效率又变低了。只要是问题,必然存在解决方法。于是三阶段提交就出现了。
     
     
    3.2 什么是三阶段提交
    三阶段提交,顾名思义有三个阶段: Flush 阶段、sync 阶段、commit 阶段。分别对应的就是二进制日志写内存的阶段、二进制日志刷盘的阶段、事务提交到存储引擎层的阶段。
     
    3commit.png

    每个阶段都有 leader、follower 两种角色。当一个事务进入三个阶段中的某一个阶段,如果发现这个阶段中的队列为空,那么这个事务就会成为 leader 的角色,之后进入同一阶段的事务,发现这个阶段的队列中已经有事务存在了,那就变成 follower 角色。leader 角色的任务是安排当前阶段队列中的事务按顺序执行,并且带领队列中所有的事务进入下一个阶段。当 leader 带领队列中的事务进入下一阶段的时候,如果发现下一阶段中已经有事务存在(即下一阶段已有 leader 存在),新来的 leader 自动变成 follower 角色。

    三阶段提交在每个阶段都控制了事务的顺序,从而也就控制了事务执行的整体顺序。解决了 prepare_commit_mutex 锁导致的问题,事务可以并发的执行。


    参考:http://blog.itpub.net/28218939/viewspace-1975809/
               http://blog.itpub.net/28218939/viewspace-1975822/
    http://mysqlmusings.blogspot.jp/2012/06/binary-log-group-commit-in-mysql-56.html  


    腾讯云正式成为MariaDB基金会白金会员

    图灵之歌 发表了文章 0 个评论 2636 次浏览 2017-06-16 16:35 来自相关话题

    6月16日,全球开源组织MariaDB基金会宣布,腾讯云正式成为MariaDB基金会白金会员,这是基金会最高级别会员。这也是腾讯云继上个月加入CNCF基金会和Linux基金会后,在开源界的又一项新动作,意味腾讯云在开源领域的步伐正在不断深入,从IaaS的开源进 ...查看全部
    6月16日,全球开源组织MariaDB基金会宣布,腾讯云正式成为MariaDB基金会白金会员,这是基金会最高级别会员。这也是腾讯云继上个月加入CNCF基金会和Linux基金会后,在开源界的又一项新动作,意味腾讯云在开源领域的步伐正在不断深入,从IaaS的开源进入到PaaS的开源。
     


    腾讯云将输出腾讯在MariaDB数据库上的经验和技术。腾讯云专家工程师程彬加入基金会成员组,成为全球仅有的7位官方成员之一。程彬负责腾讯云数据库CDB以及内核TXSQL的研发,专注于数据库和分布式存储领域相关技术和产品。他将代表腾讯云的数据库团队参加基金会每周的技术会议,提供MariaDB数据库的意见和建议,并在内部推动腾讯云MariaDB的开源进程,推动MariaDB在中国的开源工作。  
     
    MariaDB基金会主席高度评价腾讯云
     
    MariaDB基金会主席 Otto Kekäläinen表示:“MariaDB是未来的IT基础设施的一个基本组成部分,腾讯云在这个领域不断的思考和布局,具备锐意开创未来的主宰领导力。”他同时指出,强大的开源文化生长在中国以及亚洲,基金会的目标是将来在亚洲发起更多的活动。我们下一个MariaDB 开发者大会将在中国深圳举行。
     
    MariaDB基金会官方同时评价,腾讯云的加入为基金会的发展提供强有力的资源支持,保障MariaDB开源生态的良好运转,为不断成长的用户和开发者提供服务。
     
    MariaDB是由MySQL之父Michael Widenius于2009年开创的一个MySQL分支,在MySQL被商业企业收购后,为保证行业仍有开源可用的兼容MySQL的分支可用,Michael Widenius在创立了 MariaDB的同时,还成立了非赢利组织 MariaDB 基金会为MariaDB 项目、用户和开发者社区提供基础架构支持。目前MariaDB是发展最快的MySQL分支版本,新版本发布速度已经超过了商用的MySQL版本,在开源数据库领域拥有较强的技术影响力。
     
    腾讯云将重点开源MariaDB内核积累
     
    在腾讯内部,一直有一个数据库内核团队,在MySQL和MariaDB基础上之上做出改进优化,重点排出一些平时难以触发的bug,并在此基础上打造出了腾讯云的数据库产品。
     
    在参与MySQL和MariaDB优化的过程中,腾讯云完成了主备节点锁拆分、动态调整各种级别复制参数,以及binlog写优化等;发现并解决了刷脏死锁引起的 innodb 600S crash 问题、memory barrier 引起的 hang 问题以及字符串问题等影响数据库稳定的问题。
     
    未来,腾讯云还将投入更多精力到内核研发上,并会合并之前的一些内部稳定使用功能发布开源版本,尤其是适合云环境的功能的开源版本,为开源组织贡献自己的一份力量。
     
    腾讯云深度拥抱全球开源生态圈
     
    近年来,腾讯云大力拥抱开源事业。今年5月,腾讯云以金牌会员的身份正式加入CNCF基金会,为CNCF开源社区开放自身的Kubernetes相关特性,释放自身在容器服务、KVM虚拟化等方面的优势积累。同时基于腾讯云在Linux领域的积极贡献,腾讯云获CNCF基金会邀请加入Linux基金会。
     
    此次腾讯云加入MariaDB基金会,将在数据库内核研发和功能开发方面开放助力开源,与国际的数据库专家团体建立更密切的联系,推动开放更多的技术开源。
     
    未来腾讯云继续加大在开源领域的步伐,深度拥抱全球开源生态圈,从产品出发,基于大量用户在产品使用的感受和腾讯云的服务实践,将有价值的特性反馈给社区,与社区一起完善相关特性,同时从社区获得广泛的用户反馈,再次回到产品,提升腾讯云的产品体验。
     
     
    延伸阅读:
    腾讯云加入MariaDB基金会的官方消息:
    https://mariadb.org/tencent-cloud-becomes-platinum-sponsor-mariadb-foundation/

    MYSQL的不同SQL模式解析

    chris 发表了文章 0 个评论 2920 次浏览 2017-05-15 23:05 来自相关话题

    一、Mysql SQL Mode简介 通常来说MySQL服务器能够工作在不同的SQL模式下,并能针对不同的客户端以不同的方式应用这些模式。这样,应用程序就能对服务器操作进行量身定制以满足自己的需求。   这类模 ...查看全部


    一、Mysql SQL Mode简介


    通常来说MySQL服务器能够工作在不同的SQL模式下,并能针对不同的客户端以不同的方式应用这些模式。这样,应用程序就能对服务器操作进行量身定制以满足自己的需求。
     
    这类模式定义了MySQL应支持的SQL语法,以及应该在数据上执行何种确认检查。这样,就能在众多不同的环境下、与其他数据库服务器一起更容易地使用MySQL。
     
    可以使用" --sql-mode="modes" "选项,通过启动mysqld来设置默认的SQL模式。而从MySQL 4.1开始,也能在启动之后,使用SET [SESSION|GLOBAL] sql_mode='modes'语句,通过设置sql_mode变量更改其模式。
     
    通常在linux下安装完mysql后,其默认的sql-mode值是空,在这种情形下mysql执行的是一种不严格的检查,例如日期字段可以插入'0000-00-00 00:00:00'这样的值,还有如果要插入的字段长度超过列定义的长度,那么mysql不会终止操作,而是会自动截断后面的字符继续插入操作,如下例:
    mysql> create table t1 (c1 char(3));
    mysql> insert into t1 values('abcd');
    mysql> select * from t1;
    +------+
    | c1 |
    +------+
    | abc |
    +------+
    1 row in set (0.00 sec)
    我们发现插入的字符被自动截断了,但是如果我们本意希望如果长度超过限制就报错,那么我们可以设置sql_mode为STRICT_TRANS_TABLES,如下:
    mysql> set session sql_mode='STRICT_TRANS_TABLES'
    这样我们再执行同样的操作,mysql就会告诉我们插入的值太长,操作被终止,如下:
    mysql> insert into t1 values('abcd');
    ERROR 1406 (22001): Data too long for column 'c1' at row 1

    经常使用的sql_mode值:
    sqlmode.png

    说明:如果把sql_mode的值设置成后面的两个值(也就是我们说的严格模式),那么当在列中插入或更新不正确的值时,mysql将会给出错误,并且放弃insert/update操作。
     
    在我们的一般应用中建议使用这两种模式,而不是使用默认的空或ANSI模式。但是需要注意的问题是,如果数据库运行在严格模式下,并且你的存储引擎不支持事务,那么有数据不一致的风险存在,比如一组sql中有两个dml语句,如果后面的一个出现了问题,但是前面的已经操作成功,那么mysql并不能回滚前面的操作。因此说设置sql_mode需要应用人员权衡各种得失,从而得到一个合适的选择。
     
    Sql_mode的值还有很多,这里不再累述,可以参考相关的手册。
     
     


    二、SQL Mode与可移植性


    如果mysql与其它异构数据库之间有数据移植的需求的话,那么下面的sql_mode的组合设置可以达到相应的效果:
    databaseclass.png

     


    三、SQL Mode与数据效验


    SQL Mode 还可以实现对数据效验和转移等功能如: 
    1. 效验日期数据合法性. 
    2. 在INSERT或UPDATE过程中,如果被零除(或MOD(X,0)),则产生错误 
    3. 将‘"'视为识别符引号(‘`'引号字符) 
    4. 禁用反斜线字符(‘\')做为字符串内的退出字符。启用NO_BACKSLASH_ESCAPES模式,反斜线则成为普通字符。 
    5. 将||视为字符串连接操作符(+)(同CONCAT()),而不视为OR。

    MYSQL大小写敏感介绍

    chris 发表了文章 0 个评论 2956 次浏览 2017-05-08 22:55 来自相关话题

    简介 在MySQL中,数据库对应数据目录中的目录。数据库中的每个表至少对应数据库目录中的一个文件(也可能是多个,取决于存储引擎)。因此,所使用操作系统的大小写敏感性决定了数据库名和表名的大小写敏感性。   在大 ...查看全部


    简介


    在MySQL中,数据库对应数据目录中的目录。数据库中的每个表至少对应数据库目录中的一个文件(也可能是多个,取决于存储引擎)。因此,所使用操作系统的大小写敏感性决定了数据库名和表名的大小写敏感性。
     
    在大多数Unix中数据库名和表名对大小写敏感,而在Windows中对大小写不敏感。一个显著的例外情况是Mac OS X,它基于Unix但使用默认文件系统类型(HFS+),对大小写不敏感。然而,Mac OS X也支持UFS卷,该卷对大小写敏感,就像Unix一样。
     
    变量lower_case_file_system说明是否数据目录所在的文件系统对文件名的大小写敏感。ON说明对文件名的大小写不敏感,OFF表示敏感。
     
    例如在Linux下查看:
    mysql> show variables like 'lower%';
    +------------------------+-------+
    | Variable_name | Value |
    +------------------------+-------+
    | lower_case_file_system | OFF |
    | lower_case_table_names | 0 |
    +------------------------+-------+
    2 rows in set (0.00 sec)
    说明Linux系统对大小写敏感,MySQL也默认设置为对大小写敏感, 而Windows则相反。
     


    大小写区分规则


    Linux下
    • 数据库名与表名是严格区分大小写的;
    • 表的别名是严格区分大小写的;
    • 列名与列的别名在所有的情况下均是忽略大小写的;
    • 变量名也是严格区分大小写的;
     windows下
    • 都不区分大小写
     Mac OS下(非UFS卷):
    • 都不区分大小写
     

    参数说明

    unix下lower_case_table_names默认值为 0 ;  Windows下默认值是 1 ;Mac OS X下默认值是 2 .
    args.png

    由大小写敏感转换为不敏感方法

    如果原来所建立库及表都是对大小写敏感的,想要转换为对大小写不敏感,主要需要进行如下3步:[list=1]
  • 将数据库数据通过mysqldump导出。
  • 在my.cnf中更改lower_case_tables_name = 1,并重启mysql数据库。
  • 将导出的数据导入mysql数据库。

  •  


    注意事项


    为了避免大小写引发的问题,一种推荐的命名规则是:在定义数据库、表、列的时候全部采用小写字母加下划线的方式,不使用任何大写字母
     
    在任何系统中可以使用lower_case_tables_name=1。使用该选项的不利之处是当使用SHOW TABLES或SHOW DATABASES时,看不出名字原来是用大写还是小写。
     
    请注意在Unix中如果以前lower_case_tables_name = 0将lower_case_tables_name设置为1之前,重启mysqld之前,必须先将旧的数据库名和表名转换为小写。

    编译cmake MySQL 5.6.10报错

    Nock 回复了问题 2 人关注 1 个回复 7859 次浏览 2017-03-10 16:03 来自相关话题

    MYSQL的八大缺陷

    小白菜 发表了文章 0 个评论 3525 次浏览 2016-12-29 11:39 来自相关话题

    MySQL体积小,速度快,功能丰富,总体拥有成本低。它还是一个开源的关联式数据库管理系统,它的伟大成就说明了一个成功的公司是可以建立在开源之上的。   虽然用过mysql的人都曾对其出现的问题而抓狂,但只要是机器,总避免不了出问题的,更 ...查看全部
    MYSQL.png

    MySQL体积小,速度快,功能丰富,总体拥有成本低。它还是一个开源的关联式数据库管理系统,它的伟大成就说明了一个成功的公司是可以建立在开源之上的。
     
    虽然用过mysql的人都曾对其出现的问题而抓狂,但只要是机器,总避免不了出问题的,更何况是一种每秒能保存成千上万行互联网数据,你怎么保证它一点错误都没有呢?
     
    以下列举了8个开源关系型数据库的缺陷,其中不仅限于MySQL,还有是针对关系型数据库的。只有明白了关系型数据库和MySQL,才能更好地避免在使用MySQL中尽量少地遇到一些意外。
     


    1、无法避免的bugs


    任何一个软件包都有bug。但稍微深入了解一下,就会发现和Mysql相关的bugs自成体系。突然你就需要留心,因为NULL并不是以同样的方式出现,外键约束也没有像你想像的那样执行,连主键自动增长也会出错。

    到处都避免不了小问题,而且并不总是可以修复的,这就是为什么一些人保持一个列表。还好MySQL维护着一个非常好的bug报告系统,让我们可以知道我些我们无法想像的事情,知道其他人也在经受同样的磨难。
     


    2、关系表的不灵活性


    关系表具有条理性是好的,但这迫使程序员要编造或把一些数据塞到已经定义好模式的列中。NoSQL之所以越来越受欢迎,其中一个原因就是它为程序员提供了足够的灵活性,以加速数据库的使用。如果一个街道地址需要增加一行,那么,你可以将它很容易地插入到一个NoSQL文档中。如果你想添加一个完整的新的数据块,无论它包含什么内容,文档模型也可以原封不动地接受你的数据,而不必改为它要求的数据格式。

    假设你用整数格式建立了一个全部是邮编的表格。这个表十分高效,执行规则也很好。可是有一次,有人上传了一个使用了连字符的九位数邮编。或者说你得到了一位来自他国的客户的信件,上面写有邮政编码。这时,你会感到一切都乱了。老板要求网站要在几小时内恢复正常工作。然而,你已经没有时间重建数据库。程序员可以做什么?使用黑客手段把这位客户的邮政编码由base 64的数字格式改为base 10格式?或者设置一个使用转义编码的辅助表格,用来说明真正的邮政编码或者其他?危险的黑客无处不在,但你没有时间来搞定它。

    MySQL的关联规则让每个人都诚实和谨慎,但它能强制我们避开易受攻击和欺骗的麻烦。
     


    3、存储引擎混乱


    总体来说,Mysql的存储引擎接口定义还算良好的。MySQL不是实际上的同一的数据库。它是由几个数据库组成,它们的大多数细节都被统一的表面掩盖了。开始时有一个MyISAM引擎,它很快但在前后一致上不能做到完备。有时你需要速度并且可以接受不一致的结果时是很好的。

    当人们需要更多时,具备完整事务支持的Inno DB出现了。但这还不够。现在,它可能有20种存储引擎的选择——这足以使一个数据库管理员疯狂。当然,有时在不同的存储引擎之间切换而不必重写你的SQL是很好的,但是切换后总会带来混乱。这个表格我选择的引擎是MyISAM还是innoDB呢?或者,我决定输出的数据是CSV格式的吗?
     


    4、JOIN联合查询


    曾经,将数据分表保存是计算机科学史上的伟大创新。分开后的表不仅结构简单,使用上也简化了许多。但它却需要使用join语句来进行查询。

    sql通过一系列join构建的复杂查询将开发者推入了困惑与绝望的深渊。而且存储引擎也需要以最优的方式来高效地解析join语句。开发者需要绞尽脑汁编写查询语句,然后数据库对其进行解析。

    这就是很多注重运行速度的开发者放弃数据分表转而使用不规范数据表的原因。不区分数据实体,将所有数据保存到一个大表中——以避免复杂的查询。这样确实很快,并且服务器也不会耗尽内存。

    现在的磁盘空间很廉价。8TB的磁盘已经在售,更大容量的也将上市。我们不再需要为使用join而绞尽脑汁了。
     


    5、分支的混乱


    毋庸置疑,一个可靠的、得到良好支持的MySQL分支,可以带来竞争和选择,但是它也引起困惑和混乱。更糟糕的是,一个称为MariaDB的MySQL分支,由Monty Widenius维护着。他同样也在参与编写MySQL。那么,Maria DB是真正独立的值得我们拥护的吗?或者它是MySQL?我们是否应该坚持使用由创建原始mysql数据库的组织运营的核心代码?或者我们应该加入那些被认为更聪明的,往往很酷的背叛者?

    如何获取关于兼容性的信息?虽然Maria DB和MySQL十分相似,但它们之间也有差异。这就是大家一直都在争论它的原因。在性能方面,在我们查询的范围内,在两个阵营中,也许它们的工作方式相同,但也许不同,也许将来会不同。
     


    6、开发MySQL的动机


    虽然MySQL是一款成功的开源产品,但它仍属于商业中的一款产品,专业开发者需要靠它来获得利益,当然,最直接的利益就是薪资。当大多数用户在持续地享受开源许可证带来的最佳体验时,毫无疑问这家公司还在为赚取足够的钱来维持运营而努力。这导致自由代码在“社区版”和出售给企业的完整产品之间产生了奇怪的分岐。

    我们应该对这款产品付钱吗?这种在社区版开展经营的行为是否公平?企业版中额外的功能是不是一个噱头,以引诱我们不断付费的呢?这至少说明一点,它是另一些需要回答的问题:选用哪个版本?遵照哪种许可证?选用它的哪个功能集?
     


    7、原生JSON支持的缺乏


    通过安装MySQL查看其年龄,然后你就知道需要添加哪些驱动程序使它变得可用。MySQL通常在3306端口上通信,一般输出的是它本身难以理解的格式化数据。如果要让你的代码和它通信,你必须添加另一层代码,将MySQL的语言转换成有用的东西。这些层的代码,以库的形式分发,经常需要人们购买一个商业许可证。

    现代数据存储层通常直接以JSON通信。虽然MySQL和Maria DB现在有能力解析SQL中的JSON部分,但这还远远不够,原生的JSON接口已经被广泛使用于CouchDB、MongoDB,或任何最新的工具中。
     


    8、封闭源和专有模块的兴起


    虽然MySQL是开源的,但除了一些在”开源核心“周边开发的一些较新的、非开源的代码和专有模块。程序员也需要赚钱、需要生活,Oracle需要拿它的辛苦成果来换钱,这是一种现实,也是商业的性质。使用MySQL你也不可以免费得到任何东西。

    要求MySQL始终坚持在一个很高的标准上,这有点不公平,因为开源的成功可能是一个圈套。它开始可以免费,但并不意味着它可以始终免费。如果企业需要更多新的功能,他们就要通过各种方式付费来获取。有时向Oracle付费,比自己来编写代码要便宜得多。有时商业的、不开源的代码是有意义的。

    MySQL虽然作为一个成功的开源系统,但以上这些问题也总不可避免地出现,这就需要我们在它们发生之前有个深刻的认识,才能在今后的应用中避免不必要的麻烦。