Who am I


--------------------------
成江东@盛大在线
生肖:马
星座:处女
职业:IT民工
家乡:三峡.宜昌
住址:闵行
工作:张江
目标:做最好的DBA
爱好:读书,电影,音乐,旅游
性格:动中取静
喜欢的报刊杂志:
<南方周末>
<看电影>
<蓝球先锋报>
QQ:1913908
MAIL:YCZEALOT#GMAIL.COM

Catalog

我的豆瓣

 

2010年九月
« 八    
 12345
6789101112
13141516171819
20212223242526
27282930  

[转]MySQL’s binary log结构简介

binary log,是mysql中一个非常重要的部分,其主要作用有两个:

  • Replication:在master端开启binary log后,binary log记录所有数据库的改动,然后slave端获得这个binary log文件内容,就可以在slave端进行同样的操作,使master和slave保持一致.这是binary log的一个非常重要的用途.
  • 备份:在某个时间点a作了一次备份,然后利用binary log记录从这个时间点a后的所有对数据库的改动,然后下一次还原的时候,利用时间点a的备份文件和这个binary log文件,就可以将数据还原至最新时点.

本文简单介绍binary log的结构.
注:本文中,”binary log”是指整体,包括所有binlog文件和binlog index文件,而”binlog”,是指单独的某个二进制日志文件,”binlog index”,就是指二进制日志索引文件.

一.开启binary log功能
在my.cnf文件中添加:

log-bin=master-bin
log-bin-index=master-bin.index

log-bin是指定以后生成的各个binlog文件的前缀,在这里我们设为master-bin,因此以后生成的binlog文件将会是:

master-bin.000001
master-bin.000002
......

而log-bin-index则是指定binlog index文件的名称,这里我们设为master-bin.index.

二.Binary log的结构和组织
1.每个binlog记录的是一个个事件,是对数据库产生变动了的事件,例如一条update语句,而select语句一般不会写入binlog,因为它对数据库不产生变动.,在这里我们简称这些事件为”event”.注意不要和mysql的stored routines中的event混淆.
2.binlog index文件只有一个,它记录的是所有binlog的文件名称,引用”MySQL High Availability”中的图来表述各个binlog文件和binlog index文件之间的关系:

binlog_01

再实例查看一下,在某个存放了binlog文件的目录下:

[zhouminjun.pt@xxxx data]$ ls -l
-rw-rw---- 1 zhouminjun.pt users      973 Aug 23 17:06 mysql-bin.000001
-rw-rw---- 1 zhouminjun.pt users      106 Aug 23 17:07 mysql-bin.000002
-rw-rw---- 1 zhouminjun.pt users      324 Aug 23 17:08 mysql-bin.000003
-rw-rw---- 1 zhouminjun.pt users      598 Aug 23 21:01 mysql-bin.000004
-rw-rw---- 1 zhouminjun.pt users      149 Aug 24 08:36 mysql-bin.000005
-rw-rw---- 1 zhouminjun.pt users     3249 Aug 24 13:25 mysql-bin.000006
-rw-rw---- 1 zhouminjun.pt users      114 Aug 24 08:36 mysql-bin.index

[zhouminjun.pt@xxxx data]$ cat mysql-bin.index
./mysql-bin.000001
./mysql-bin.000002
./mysql-bin.000003
./mysql-bin.000004
./mysql-bin.000005
./mysql-bin.000006

可以看到,binlog index文件其实就是很简单的记录当前所有binlog的文件名,每行一个.当你使用”RESET MASTER”、”FLUSH LOGS”这类命令时,binlog index文件也会相应变动.

3.再看看binlog文件,binlog文件是二进制的,直接打开是不可阅读的.有两种方法阅读其中的内容:
a.在客户端中使用”show binlog events”查看:

mysql> show binlog events\G;
*************************** 1. row ***************************
   Log_name: mysql-bin.000005
        Pos: 4
 Event_type: Format_desc
  Server_id: 1
End_log_pos: 106
       Info: Server ver: 5.1.49-debug-log, Binlog ver: 4
*************************** 2. row ***************************
   Log_name: mysql-bin.000005
        Pos: 106
 Event_type: Rotate
  Server_id: 1
End_log_pos: 149
       Info: mysql-bin.000006;pos=4
2 rows in set (0.00 sec)

可以看到,当前有两条event,下面解释下各个字段的意义:
Log_name:这个event所在的binlog名称.这里是在mysql-bin.000005
Pos:这个event在当前binlog中的位置
Event_type:这个event的类型,类型是有很多,当前这个是Format_desc类型
Server_id:这个event是在哪个server上发生的.注意在replication中,这个server id记录的是master端的server id.
End_log_pos:下一个event的位置.因此当前这个event的长度是End_log_pos-Pos.
Info:直观的可读的关于本条event的信息.

在刚才查看binlog的时候,里面有两条event,第一条类型是Format_desc,第二条是Rotate:


Format_desc:这是每一个binlog文件的头,是每一个binlog文件必有的第一个event,在这个event中,记录了一些诸如binary log格式版本,产生这个event的mysql server版本等等.


Rotate:一般来说,这是每个binlog文件的结束event.有如下情况(我在5.1.49-debug-log上已测):
1.当你使用”flush logs”命令时,mysql会自动在当前正在使用的binlog文件末尾加上这个rotate事件,然后就不再使用这个binlog了,同时会创建一个新的binlog文件,然后自动在新创建的这个binlog中加上一个Format_desc event,并且更新binlog index(将这个新创建的binlog文件名添加进入).
2.每次重启mysqld(通过mysqladmin关闭,再手动重启)的时候,mysql也会关闭当前binlog,并且写入一个Stop event(注意不是rotate event),然后再启动的时候会按照上面一样,创建新的binlog文件并作相关工作.
3.通过kill命令直接杀死掉mysql,这个时候发生没有任何event写入.


其他还有很多event类型,最常见的可能就是Query了,update、delete等操作都是Query类型.通常一个update操作在binlog文件中会产生好几个event,因为为了保证主从一致,需要确保很多外部因素的一致.
在这里我们引入一个分组的概念:除了format_desc和rotate,其他的event我们往往可以对其进行分组,对于事务型数据库来说,往往认为一个事务就是一个分组,对于非事务型数据库和类似create、alter这类语句来说,一条语句本身就是一个分组.
那么通常,一个分区内的语句要么全都执行,要么全都不执行,在replication中,如果slave在执行一个分组内的某条语句时,mysql突然中断了,那么mysql会重新从头开始这个分组,而非从中断点继续.这就能很好的保证了事务的原则.

这里有一点要说明的是,用show binlog events命令查看的永远是binlog index文件中的第一个binlog文件内容,一般来说是master-bin.000001文件,要查看其他binlog文件需要使用:

show binlog events in 'mysql-bin.000003';

查看mysql目前正在写哪个binlog文件可以先执行”show master status\G;”查看.

b.使用mysql自带的工具mysqlbinlog,比如对于一个经历了正常启动,再正常关闭(mysqladmin shutdown)的binlog来说,用mysqlbinlog查看:

[zhouminjun.pt@xxxxx data]$ mysqlbinlog mysql-bin.000007
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#100825 19:19:30 server id 1  end_log_pos 106   Start: binlog v 4, server v 5.1.49-debug-log created 100825 19:19:30 at startup
ROLLBACK/*!*/;
BINLOG '
Qvx0TA8BAAAAZgAAAGoAAAAAAAQANS4xLjQ5LWRlYnVnLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAABC/HRMEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
'/*!*/;
# at 106
#100825 19:20:12 server id 1  end_log_pos 125   Stop
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;

用mysqlbinlog查看binlog可能比乱一点.但是能查看到更多的内容.
每个event都是以类似下面两行开始:

# at 267
#100825 11:57:57 server id 1  end_log_pos 335   Query   thread_id=99    exec_time=0     error_code=0

第一行的267代表这个event的起始位的位置.


第二行的100825 11:57:57代表这个event开始执行的时间(对于replication来说,无论在master的binlog中还是slave的relay-log中,值是相同的,都是指在master端开始执行的时间),100825是指10年8月25.
接着是master的server id.
end_log_pos指的是下一个event的起始位置,注意这个值如果是在replication中的relay-log中,那这个值是直接从master处搬过来的,因此对于relay-log来说有可能是不准的.
thread_id就是执行这个event的线程id.
exec_time对于master端的binlog来说是执行这个event所花费的时间,对slave端的relay-log来说,这个值是slave端执行这个event结束的时间减去master端开始执行这个event的时间,因此在一些情况下,我们还能根据这个值大概分析出slave落后于master的时间.

原文:http://saw-unix.com/2010/08/mysqls-binary-log_details.html

[转]浅谈数据库系统中的cache

Cache和Buffer是两个不同的概念,简单的说,Cache是加速“读”,而buffer是缓冲“写”,前者解决读的问题,保存从磁盘上读出的数据,后者是解决写的问题,保存即将要写入到磁盘上的数据。在很多情况下,这两个名词并没有严格区分,常常把读写混合类型称为buffer cache,本文后续的论述中,统一称为cache。

Oracle中的log buffer是解决redo写入的问题,而data buffer cache则解决data block的读写问题。对于Oracle来说,如果IO没有在SGA中命中,都会发生物理IO,Oracle并不关心底层存储的类型,可能是一套存储系统,可能是本地磁盘,可能是RAID 10,也可能是RAID 5,可能是文件系统,也可能是裸设备,或是ASM。总之,Oracle把底层的存储系统称为存储子系统。

在存储系统中,cache几乎无处不在(在后面的论述中,我们统称为cache),文件系统有cache,存储有cache,RAID控制器上有cache,磁盘上也有cache。为了提高性能,Oracle的一个写操作,很有可能写在存储的cache上就返回了,如果这时存储系统发生问题,Oracle如何来保证数据一致性的问题。

Oracle数据库最重要的特性是:Write ahead logging,在data block在写入前,必须保证首先写入redo log,在事务commit时,同时必须保证redo log被写入。Oracle为了保证数据的一致性,对于redo log采用了direct IO,Direct IO会跳过了OS上文件系统的cache这一层。但是,OS管不了存储这一层,虽然跳过了文件系统的cache,但是依然可能写在存储的cache上。

一般的存储都有cache,为了提高性能,写操作在cache上完成就返回给OS了,我们称这种写操作为write back,为了保证掉电时cache中的内容不会丢失,存储都有电池保护,这些电池可以供存储在掉电后工作一定时间,保证cache中的数据被刷入磁盘,不会丢失。不同于UPS,电池能够支撑的时间很短,一般都在30分钟以内,只要保证cache中的数据被写入就可以了。存储可以关闭写cache,这时所有的写操作必须写入到磁盘才返回,我们称这种写操作为write throuogh,当存储发现某些部件不正常时,存储会自动关闭写cache,这时写性能会下降。

RAID卡上也有cache,一般是256M,同样是通过电池来保护的,不同于存储的是,这个电池并不保证数据可以被写入到磁盘上,而是为cache供电以保护数据不丢失,一般可以支撑几天的时间。还有些RAID卡上有flash cache,掉电后可以将cache中的内容写入到flash cache中,保证数据不丢失。如果你的数据库没有存储,而是放在普通PC机的本地硬盘之上的,一定要确认主机中的RAID卡是否有电池,很多硬件提供商默认是不配置电池的。当然,RAID卡上的cache同样可以选择关闭。

磁盘上的cache,一般是16M-64M,很多存储厂商都明确表示,存储中磁盘的cache是禁用的,这也是可以理解的,为了保证数据可靠性,而存储本身又提供了非常大的cache,相比较而言,磁盘上的cache就不再那么重要。SCSI指令中有一个FUA(Force Unit Access)的参数,设置这个参数时,写操作必须在磁盘上完成才可以返回,相当于禁用了磁盘的写cache。虽然没有查证到资料,但是我个人认为一旦磁盘被接入到RAID控制器中,写cache就会被禁用,这也是为了数据可靠性的考虑,我相信存储厂商应该会考虑这个问题。

至此,我们可以看到Oracle的一个物理IO是经历了一系列的cache之后,最终被写入到磁盘上。cache虽然可以提高性能,但是也要考虑掉电保护的问题。关于数据的一致性,是由Oracle数据库,操作系统和存储子系统共同来保证的。

原文:http://www.hellodba.net/2010/08/db-storage.html

mysql 复制出错解决方法

中午正准备去吃饭,收到大量报警,10.xx.xx.xx- MySQL Replication [slave_lag] is still below threshold of 0 with -1

麻烦了,复制中断了,赶紧回办公室,连上服务器

show slave status

显示

*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.xx.xx.xx
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: 100025.000377
          Read_Master_Log_Pos: 261910
               Relay_Log_File: 100026-relay-bin.001279
                Relay_Log_Pos: 243970
        Relay_Master_Log_File: 100025.000377
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 1062
                   Last_Error: Error ‘Duplicate entry ‘31bc63deb64211dfbfb1002655d7deb0-’ for key ‘PRIMARY” on

query. Default database: ‘test’. Query: ‘INSE
RT INTO d_twitter.t_twitter_user (user_id,content,mood,release_time,type,tags,source_desc,ip,attachment,mood_id)

values (”,’添加了照片印象  \”在\” http://t.
sdo.com/photo/index.php?r=album/view/uid/1183155325/id/661/image/5649′,’0′,’2010-09-02

11:24:47′,’2′,”,”,’1034744164′,’a:3:{s:5:\”title\”;s:25:\”5649-11831
55325-8_260.jpg\”;s:12:\”original_url\”;s:64:\”http://photo.staticsdo.com/a1/36/92/49/5649-1183155325-

8_260.jpg\”;s:12:\”contract_url\”;s:64:\”http://photo.s
taticsdo.com/a1/36/92/49/5649-1183155325-8_260.jpg\”;}’,'31bc63deb64211dfbfb1002655d7deb0′)’
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 243828
              Relay_Log_Space: 262404
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 1062
               Last_SQL_Error: Error ‘Duplicate entry ‘31bc63deb64211dfbfb1002655d7deb0-’ for key ‘PRIMARY” on

query. Default database: ‘test’. Query: ‘INSE
RT INTO d_twitter.t_twitter_user (user_id,content,mood,release_time,type,tags,source_desc,ip,attachment,mood_id)

values (”,’添加了照片印象  \”在\” http://t.
sdo.com/photo/index.php?r=album/view/uid/1183155325/id/661/image/5649′,’0′,’2010-09-02

11:24:47′,’2′,”,”,’1034744164′,’a:3:{s:5:\”title\”;s:25:\”5649-11831
55325-8_260.jpg\”;s:12:\”original_url\”;s:64:\”http://photo.staticsdo.com/a1/36/92/49/5649-1183155325-

8_260.jpg\”;s:12:\”contract_url\”;s:64:\”http://photo.s
taticsdo.com/a1/36/92/49/5649-1183155325-8_260.jpg\”;}’,'31bc63deb64211dfbfb1002655d7deb0′)’

同时收到错误日志报警

100902 11:28:46 [ERROR] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with “SLAVE START”. We stopped at log ‘100001.000389′ position 437802

使用命令SHOW BINLOG EVENTS in ‘100001.000389′ from 437802\G;

可以看到中断点之后的events,明显的有若干语句的 user_id为”值,说明程序有异常,和开发人员联系后,确认程序有问题,已经修正了.

现在就是需要跳过这些错误,恢复复制.

如果错误是连续的,其实可以用

STOP SLAVE;

SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 15;

START SLAVE;

这样的语句,跳过所有的出错语句,但一般来说错误都是不连续的,就是中间夹杂着正确的语句,在语句比较少的情况下,可以

STOP SLAVE;

SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;

START SLAVE;

一行行跳过

如果出错的语句比较多,最好修改my.cnf,加入

slave-skip-errors =1062,1032

slave-skip-errors =all

不过修改后,需要重启服务,不能动态修改,这是比较不好的地方

当然还有一种方法就是,如果使用了中间代理层比如amoeba,可以将原来的读写分离的两台机器,都改为读写其中一台机器,以避免复制中断造成的读写不同步.

MongoDB 1.6 auto sharding 测试

1.6版终于发布了,据说sharding可以用于生产环境了,那就让我们来测试一下吧
MongoDB 1.6 is a drop-in replacement for 1.4. To upgrade, simply shutdown mongod then restart with the new binaries.
Sharding
Sharding is now production-ready, making MongoDB horizontally scalable, with no single point of failure. A single instance of mongod[......]

我当年的口语测试

1 What’s your name?
My name is ChengJiangdong. I don’t really look my age even though I am 27 years old.
2 Where are you from?
I grew up in the beautiful city Yichang. The meaning of the name is “Should Flourish”. With more than 7,000 or 8,000 years of history; it called as “the th[......]

我名字的出处

夏日绝句

李清照

生当作人杰,死亦为鬼雄。

至今思项羽,不肯过江东。

 

题乌江亭
杜牧

胜败兵家事不期,
包羞忍耻是男儿。
江东子弟多才俊,
卷土重来未可知。

虞美人   

南唐后主 李煜   

春花秋月何时了, 往事知多少。   
小楼昨夜又东风, 故国不堪回首月明中。   

雕阑玉砌应犹在, 只是朱颜改。
问君能有几多愁, [...]

钱神论–以今观之,其文如何?

西晋鲁褒
       昔神农氏没,黄帝、尧、舜教民农桑,以币帛为本。上智先觉变通之,乃掘铜山,俯视仰观,铸而为钱。使内方象地,外圆象天。大矣哉!钱之为体,有乾有坤。内则其方,外则其圆。其积如山,其流如川。动静有时,行藏有节。市井便易,不患耗损。难朽象寿,不匮象道;故能长久,为世神宝。亲爱如兄,字曰“孔方”。失之则贫弱,得之则富强。无翼而飞,无足而走。解严毅之颜,开难发之口。钱多者处前,钱少者居后。处前者为君长,在后者为臣仆。君长者丰衍而有余,臣仆者穷竭而不足。《诗》云:“哿矣富人,哀此茕独!”岂是之谓乎?
   钱之为言泉也!百姓日用,其源不匮。无远不往,无深不至。京邑衣冠,疲劳讲肄;厌闻清[......]

优化利器之覆盖索引和强制索引--mssql存储过程调优一则

 一个老的系统,有一个分页的存储过程,程序反应在有一些类别调用的时候超时,就是超过了30秒。
在Profiler监控该存储过程,发现当其中一个参数 type=1 or 2 的时候,时间会超长,检查发现原来这两个类别的记录量都达到200W左右,而其它的类别都有在50w以下。
做了以下几点工作:
1,索引整理重建
select b.name,avg_fragmentation_in_percent
from sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL , NULL, ‘LIMITED’) a,sys.indexes [......]

mysql show status中的queries 和questions的5点异同

1 \s命令显示的
Threads: 3  Questions: 137227384  Slow queries: 878668  Opens: 1922  Flush tables: 12  Open tables: 192  Queries per second avg: 21.710
中的Questions实际是Queries的值。
2 show status like ‘que%’
+—————+———–+
| Variable_name | Value [......]

perl角本监控mysql慢查询日志

因为打开了 log-queries-not-using-indexes选项,所以有一些信息需要过滤掉,如晚上backupuser备份的时候的一些查询语句,也可以根据时间,超过XXX毫秒的才发邮件:
perl -MCPAN -e shell
install Mail::Mailer
———————–
#!/usr/bin/perl
# MySQL慢查询监控角本
# author: chengjiangdong
# blog: http:/[......]