Who am I


--------------------------
成江东@sina
生肖:马
职业:IT民工
家乡:三峡.宜昌
住址:海淀
工作:中关村
目标:做最好的DBA
爱好:读书,电影,音乐,旅游
性格:动中取静
喜欢的报刊杂志:
<南方周末>
<看电影>
<读库>
QQ:1913908
MAIL:YCZEALOT#GMAIL.COM

Catalog

我的豆瓣

 

2012年五月
« 十二    
 123456
78910111213
14151617181920
21222324252627
28293031  

MySQL 查询价格连续上涨天数一则

朋友问的一个问题:
已知表结构如下,要求得到股价连续上涨的天数:

mysql@localhost.test>select d,price from stock order by d;
+————+——-+
| d | price |
+————+——-+
| 2012-05-01 | 20 |
| 2012-05-02 | 23 |
| 2012-05-03 | 25 |
| 2012-05-04 | 28 |
| 2012-05-05 | 30 |
| 2012-05-06 | 31 |
| 2012-05-07 | 33 |
| 2012-05-08 | 31 |
| 2012-05-09 | 39 |
| 2012-05-10 | 33 |
| 2012-05-11 | 40 |
| 2012-05-12 | 42 |
+————+——-+

结果应该如下(第一天不参与统计):
+————+——-+——+
| d | price | n |
+————+——-+——+
| 2012-05-02 | 23 | 1 |
| 2012-05-03 | 25 | 2 |
| 2012-05-04 | 28 | 3 |
| 2012-05-05 | 30 | 4 |
| 2012-05-06 | 31 | 5 |
| 2012-05-07 | 33 | 6 |
| 2012-05-08 | 31 | 0 |
| 2012-05-09 | 39 | 1 |
| 2012-05-10 | 33 | 0 |
| 2012-05-11 | 40 | 1 |
| 2012-05-12 | 42 | 2 |
+————+——-+——+

查询语句如下:
select d,price,@a:=if(zf=1,@a+zf,0) n from (select a.d,a.price,if(a.price-b.price>0,1,0) zf from stock a,stock b where a.d=date_add(b.d,interval 1 day) order by d) t,(select @a:=0) as a ;

思路是,先用自连接计算出当天和上一天的股票差值,如果>0,取值1,否则取值0
然后用子查询,用@a变量计算累计值,但如果是0就不计算。

该语句的问题是即使d上建了索引,因为有a.d=date_add(b.d,interval 1 day)语句,查询效率不高
explain select d,price,@a:=if(zf=1,@a+zf,0) n from (select a.d,a.price,if(a.price-b.price>0,1,0) zf from stock a,stock b where a.d=date_add(b.d,interval 1 day) order by d) t,(select @a:=0) as a ;

+—-+————-+————+——–+—————+——+———+——+——+———————————+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+—-+————-+————+——–+—————+——+———+——+——+———————————+
| 1 | PRIMARY | | system | NULL | NULL | NULL | NULL | 1 | |
| 1 | PRIMARY | | ALL | NULL | NULL | NULL | NULL | 11 | |
| 3 | DERIVED | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| 2 | DERIVED | b | ALL | NULL | NULL | NULL | NULL | 12 | Using temporary; Using filesort |
| 2 | DERIVED | a | ALL | idx_d | NULL | NULL | NULL | 12 | Using where; Using join buffer |
+—-+————-+————+——–+—————+——+———+——+——+———————————+

所以可以增加一个pre列,存放上一天的价格,用以下语句更新:
update stock a,stock b set a.pre=b.price where a.d=date_add(b.d,interval 1 day);

MSSQL:update a set a.pre=b.price from stock a,stock b where …;

查询语句变为
select d,price,@a:=if(zf=1,@a+zf,0) n from (select a.d,a.price,if(a.price-a.pre>0,1,0) zf from stock a order by d) t,(select @a:=0) as a ;

没有连接,更为高效,以后只需要更新新增数据的pre字段即可

使用alter ignore table去重一则

有分组表,结构如下:

CREATE TABLE `member` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`gid` bigint(20) unsigned NOT NULL,
`uid` bigint(20) unsigned NOT NULL,
`touid` bigint(20) unsigned NOT NULL,
`addtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`reason` varbinary(90) NOT NULL DEFAULT ”,
PRIMARY KEY (`id`),
KEY `idx_uid_gid_touid` (`uid`,`gid`,`touid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

uid是用户id,gid是分组id,touid是被分组人的id。

由于历史问题,`uid`,`gid`,`touid`不唯一,现在要将`uid`,`gid`,`touid`变为唯一键,这样就要进行去重工作。
去重有很多方法,方法一就是建一套新的库表,然后堵队列,由开发将历史数据插入库表,使用insert ignore 或者 insert replace的方法去掉重复记录,但这种方法比较慢。
另一种方法就是直接用一个从库,停复制后,将历史数据导出,修改表结构后,然后再用load data infile导入,当然也要使用ignore或者replace参数。此方案需要导入导出,有一定的风险,速度一般。
第三种方法就是用一个从库,停复制后,使用
alter ignore table member drop key `idx_uid_gid_touid` (`uid`,`gid`,`touid`),add unique key `idx_uid_gid_touid` (`uid`,`gid`,`touid`);
方法,可以直接达到去重的目的。

但测试发现,在5.5.12版上,仍然会报错
ERROR 1062 (23000): Duplicate entry ‘0-0-0′ for key ‘idx_uid_gid_touid’

查询官网,发现是一个bug(http://bugs.mysql.com/bug.php?id=40344),需要添加order by ….,可以正常使用。但此时不是使用fast index creation,而是使用table copy,速度较慢。
注意这只是一个变通的方法,其实order by 并没有实际的效果,执行完成,show warnings如下:
show warnings;
+———+——+————————————————————————————–+
| Level   | Code | Message                                                                              |
+———+——+————————————————————————————–+
| Warning | 1105 | ORDER BY ignored as there is a user-defined clustered index in the table ‘member_01′ |
+———+——+————————————————————————————–+

执行前:
mysql> select count(1) from member;
+———-+
| count(1) |
+———-+
|  8380821 |
+———-+

执行后:
mysql> select count(1) from member;
+———-+
| count(1) |
+———-+
|  8351907 |
+———-+

丢掉了大约3w条重复记录。

此时设想是开启复制,同时设置跳过1062错误(因为master库没有去重)。
但开启复制后,发现以下错误:

Last_Error: Could not execute Delete_rows event on table group_info.member_3e; Can’t find record in ‘member_3e’, Error_code: 1032; handler error
HA_ERR_KEY_NOT_FOUND; the event’s master log mysql-bin.000326, end_log_pos 958589387

去主库上查看日志:
sr/local/mysql55/bin/mysqlbinlog –base64-output=decode-rows  –verbose –start-position=958589290 –stop-position=958589387   mysql-bin.000326
显示
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 958589290
ERROR: malformed binlog: it does not contain any Format_description_log_event. I now found a Delete_rows event, which is not safe to process without a Format_description_log_event.
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;

怀疑是一个bug,–base64-output=decode-rows和–start-position一起使用的时候。

改为时间查看
/usr/local/mysql55/bin/mysqlbinlog -v –base64-output=decode-rows –start-datetime=’2011-12-24 18:08:22′  mysql-bin.000326|more
显示
#111224 18:08:22 server id 111164240  end_log_pos 958589387     Delete_rows: table id 1520 flags: STMT_END_F
### DELETE FROM group_info.member
### WHERE
###   @1=756175399
###   @2=201112200674529481
###   @3=1734139392
###   @4=1704116960
###   @5=1324388524
###   @6=”
### DELETE FROM group_info.member
### WHERE
###   @1=756312069
###   @2=201112200674529481
###   @3=1734139392
###   @4=1704116960
###   @5=1324721301
###   @6=”
# at 958589387
(注意时间变为unix_timestamp了)
发现有两条记录,分析认为,在主库上执行删除操作的时候是用@2,@3,@4定位删除的,删除了2条记录,但由于从库上已经去重了,只有一条记录,而在row格式时,找不到此行,所以报错。
可以设置跳过1032错误,但此时数据能否保持一致?
分析如果删除记录的时候是用`uid`,`gid`,`touid`定位,可以保持一致,因为主库的2条删除了,从库的唯一1条也删除了。也就是主库删除的1条或者多条记录里一定包含从库保留的那一条。

my.cnf加入
slave-skip-errors       = 1032,1062

开启复制,问题解决。

MySQL DBA 必须收藏的网站

一、官网
http://www.mysql.com/ 下载GA版本
http://dev.mysql.com/ 开发社区,可下载开发版本以及老版本
http://dev.mysql.com/doc/ 文档下载,必下
http://bugs.mysql.com/ bug提交
http://forums.mysql.com 论坛
http://lists.mysql.com/ 邮件列表
http://forge.mysql.com/ mysql用户社区
http://forge.mysql.com/wiki/MySQL_Internals mysql内部原理
http://planet.mysql.com/ mysql博客群
http://blogs.innodb.com/wp InnoDB官方blog
http://www.google.com/reader/view/feed%2Fhttp%3A%2F%2Fwww.facebook.com%2Ffeeds%2Fnotes.php%3Fid%3D10
2841356695%26viewer%3D100000661144542%26key%3Dda
630ea5d3%26format%3Drss20
MySQL at Facebook
二、中间件
http://amoeba.meidusa.com/ amoeba –陈思儒 暂时打不开
http://rdc.taobao.com/team/jm 淘宝JAVA中间件团队博客
http://dev.mysql.com/downloads/mysql-proxy/ mysqlproxy
https://github.com/MysqlProxy 金山毛剑基于mysqlproxy开发
三、其它版本
http://mariadb.org/ mariadb,原作者之一
http://www.skysql.com/
http://www.percona.com/ 高性能作者
http://www.schoonerinfotech.com/ 号称5个9可用性,支持同步复制,并行复制
http://www.innomysql.org/ 姜承尧,《MySQL技术内幕:InnoDB存储引擎》作者
http://yoshinorimatsunobu.blogspot.com/ Handler-socket
四、技术服务
http://www.actionsky.com/ 爱可生,官方合作伙伴,和thinkinlamp社区经常在上海组织一些活动 http://weibo.com/actiontech
五、技术博客
http://www.mysqlperformanceblog.com/ 高性能作者,其实就是perocona公司的技术博客,必看
http://mysqlha.blogspot.com/ High Availability MySQL
http://www.taobaodba.com/ 淘宝数据库技术团队
六、个人博客
http://www.ningoo.net/ NinGoo’s blog — 宁海元 http://weibo.com/ningoo
http://www.hellodb.net/ Hello Database –张瑞 http://weibo.com/hellodba
http://www.orczhou.com/ 一个故事–周振兴 http://weibo.com/orczhou
http://isky000.com/ Sky.Jian – i Sky000–简朝阳,《MySQL性能调优与架构设计》作者 http://weibo.com/isky000
http://www.mysqlab.net/ MySQL 实验室–谭俊青
http://www.mysqlops.com/ MySQLOPS 数据库与运维自动化技术分享–金官丁 http://weibo.com/mysqlops
http://www.dbanotes.net/ dbanotes–冯大辉,偏架构 http://weibo.com/fenng
http://www.imysql.cn/ MySQL中文网–叶金荣 http://weibo.com/yejinrong
http://www.penglixun.com/ P.Linux Laboratory–彭立勋 http://weibo.com/penglixun
http://dinglin.iteye.com/ 追风刀·丁奇–丁林 http://weibo.com/tdingqi
七、工具
http://www.maatkit.org/ 不用多介绍?
http://www.coreseek.cn/ 中文全文检索/搜索软件,基于Sphinx研发
http://code.google.com/p/mysql-cacti-templates/ mysql的cacti监控模版
http://sourceforge.net/projects/sysbench/ 压测工具
http://vegan.net/tony/supersmack/ 压测工具
http://www.percona.com/software/percona-xtrabackup/ 开源热备工具
http://code.google.com/p/tungsten-replicator/ 第三方复制工具
八、论坛
http://www.itpub.net/forum-73-1.html itpub的mysql版
http://bbs.chinaunix.net/forum-17-1.html chinaunix的mysql版

[转]Top 20+ MySQL Best Practices

09年的一篇文章,现在写建表和查询规范的时候仍然值得参考。

1. Optimize Your Queries For the Query Cache
Most MySQL servers have query caching enabled. It’s one of the most effective methods of improving performance, that is quietly handled by the database engine. When the same query is executed multiple times, the result is[......]

[转]Facebook shares some secrets on making MySQL scale

Whеn уου’re storing еνеrу transaction fοr 800 million users аnԁ handling more thаn 60 million queries per second, уουr database environment hаԁ better bе a upset special. Many readers mіɡht see thеѕе numbers аnԁ rесkοn NoSQL, bυt Facebook held a Tech Talk οn Monday night explaining hοw іt built a[......]

MySQL版本进化

Unions
4

Subqueries
4.1

R-trees
4.1 (for the MyISAM storage engine)

Stored procedures and
functions
5

Views
5

Cursors
5

XA transactions
5

Triggers
5.0 and 5.1

Event scheduler
5.1

Partitioning
5.1

Pluggable storage engine
API
5.1

Plugin API
5.1

InnoDB Plugin
5.1

[......]

MySQL DBA的个人修养

做为一个MySQL DBA,必须具有以下的素质:
一, 身体素质
DBA必须接收和处理各种报警,不论是中午在吃饭或者凌晨三点已经进入深度睡眠。接到报警需要立即进入应急状态,找到电脑,联上网络,快速定位故障原因,并解决之。睡眠不好的同学不太适合当DBA,因为半夜处理故障后很难再次入睡,长期会严重影响生活质量。
另外,在抢修大型故障的时候,可能需要很长时间,没有好的身体很难坚持。
二, 心理素质
1 沉稳
凡是涉及到数据库的事没有小事,DBA必须具有“卒然临之而不惊,无故加之而不怒”的心理素质,[......]

mysql从statement到row格式复制导致复制中断一则原因分析

测试步骤:
master(5.1.46)上执行:
use test;
drop table if exists t;
create table t(id int not null auto_increment,
mid char(3) not null,
sid int not null,
primary key (id),
unique key (mid)
);
insert into t
values(1,’aaa’,1000),(2,’bbb’,1001);
slave(5.1.57)上执行:
update t set id=3 where[......]

Facebook是怎么做MySQL备份的?

Facebook的用户每天创造大量的数据,为了确保数据可靠的存储,我们每天进行数据备份.我们通过将原来的逻辑备份改成定制化的物理备份,显著地提升了备份的速度(不增加体积的情况下).
从mysqldump到Xtrabackup
我们使用mysqldump来进行每日的数据库备份,mysqldump对数据进行逻辑备份,就像应用访问数据库那样,mysqldump以SQL语句的 方式从数据库中读取一张张表,将表结构和数据转保存到文本文件.mysqldump最大的问题是速度太慢(对于我们的一些大的数据库,通常要花24小时, 甚至更久),并且以SQL语句的方式读取数据可能造成磁盘的随机读,这就会造成主机的l[......]

xtrabackup增备错误Broken pipe at /usr/bin/innobackupex line 336.

用innobackupex 的perl角本全备成功,增备失败,提示Broken pipe at /usr/bin/innobackupex line 336.
分析源码,然后查看官方bug说明(https://bugs.launchpad.net/percona-xtrabackup/+bug/783596),发现增备的时候没有进行调用锁表函数进行锁表
修改源码(+号增加,-号删除)

=== modified file ‘innobackupex’

2
— innobackupex 2011-04-29 14:12:21 +0000

3
+++[......]

blackjack, roulette, slots, slots, blackjack, roulette, casino, blackjack, blackjack, blackjack, slots