drupal转worldpress

作者:吴炳锡 来源:http://www.mysqlsupport.cn/ 联系方式:select unhex(’777562696E67786940676D61696C2E636F6D’); 载请注明作/译者和出处,并且不能用于商业用途,违者必究。

用Drupal太灵活了,灵活的我都搞不定了。所以我投向了worldpress.对比了一下表结构。参考网上的说明搞出了:

use support;
delete from wp_posts;    
delete from wp_comments;

# posts
INSERT INTO
    wp_posts (id, post_date, post_content, post_title,
    post_excerpt, post_name, post_modified)
SELECT DISTINCT
    n.nid, FROM_UNIXTIME(created), body, n.title,
    teaser,
    REPLACE(REPLACE(REPLACE(REPLACE(LOWER(n.title),’ ‘, ‘_’),’.’, ‘_’),’,’, ‘_’),’+’, ‘_’),
    FROM_UNIXTIME(changed)
FROM  drupal_bak.node n, drupal_bak.node_revisions r
WHERE n.vid = r.vid;

# comments
INSERT INTO
    wp_comments
    (comment_post_ID, comment_date, comment_content, comment_parent, comment_author, comment_author_email, comment_author_url)
SELECT
    nid, FROM_UNIXTIME(timestamp),
    comment, thread, name, mail, homepage
FROM drupal_bak.comments ;

# update comments count on wp_posts table
UPDATE `wp_posts` SET `comment_count` = (SELECT COUNT(`comment_post_id`) FROM `wp_comments` WHERE `wp_posts`.`id` = `wp_comments`.`comment_post_id`);

# fix post slugs. first we have to remove the duplicate _____ chars, then replace that with a single – char
UPDATE wp_posts set post_name = REPLACE(post_name, ‘__’, ‘_’);
UPDATE wp_posts set post_name = REPLACE(post_name, ‘__’, ‘_’);
UPDATE wp_posts set post_name = REPLACE(post_name, ‘__’, ‘_’);
UPDATE wp_posts set post_name = REPLACE(post_name, ‘__’, ‘_’);
UPDATE wp_posts set post_name = REPLACE(post_name, ‘_’, ‘-‘);

 

然后就可以看到worldpress工作了。

为什么mysql主从复制,从服务器的Time值诡异?

作者:吴炳锡 来源:http://www.mysqlsupport.cn/ 联系方式:select unhex(‘777562696E67786940676D61696C2E636F6D’); 载请注明作/译者和出处,并且不能用于商业用途,违者必究。

    从服务器show slave status\G;状态正常,show processlist;这个时候我观察到一个复制线程的Time值为4294967295,这个数字为2^32-1,数据比较特殊,然后我再show processlist;Time成为0,再查看,Time值变为1,等会再查看的时候Time值又变为4294967295,反正TIME值就是在 4294967295,0,1之间变化,show slave status\G,从服务器正常在运作。
mysql> show processlist;
+——-+————-+———–+——+———+————+———————————————————————–+——————+
| Id    | User        | Host      | db   | Command | Time       | State                                                                 | Info             |
+——-+————-+———–+——+———+————+———————————————————————–+——————+
|     4 | system user |           | NULL | Connect |    2950273 | Waiting for master to send event                                      | NULL             |
|     5 | system user |           | NULL | Connect | 4294967295 | Has read all relay log; waiting for the slave I/O thread to update it | NULL             |
| 14814 | root        | localhost | NULL | Query   |          0 | NULL                                                                  | show processlist |
+——-+————-+———–+——+———+————+——————————————————————

mysql> show processlist;
+——-+————-+———–+——+———+———+———————————————————————–+——————+
| Id    | User        | Host      | db   | Command | Time    | State                                                                 | Info             |
+——-+————-+———–+——+———+———+———————————————————————–+——————+
|     4 | system user |           | NULL | Connect | 2950543 | Waiting for master to send event                                      | NULL             |
|     5 | system user |           | NULL | Connect |       0 | Has read all relay log; waiting for the slave I/O thread to update it | NULL             |
| 14814 | root        | localhost | NULL | Query   |       0 | NULL                                                                  | show processlist |
+——-+————-+———–+——+———+———+———————————————————————-

mysql> show processlist;
+——-+————-+———–+——+———+———+———————————————————————–+——————+
| Id    | User        | Host      | db   | Command | Time    | State                                                                 | Info             |
+——-+————-+———–+——+———+———+———————————————————————–+——————+
|     4 | system user |           | NULL | Connect | 2950574 | Waiting for master to send event                                      | NULL             |
|     5 | system user |           | NULL | Connect |       1 | Has read all relay log; waiting for the slave I/O thread to update it | NULL             |
| 14814 | root        | localhost | NULL | Query   |       0 | NULL                                                                  | show processlist |
+——-+————-+———–+——+———+———+———————————————————————-

有两个原因:
第一个: 这个情况我以前在4.X以前遇到过。后来升级到4.1后就没这个问题了。如果你的版本低于这个版本,有可能会这种情况。
第二个:有可能是你的网络不稳定。导至从服务器连接Master不稳定,从而返还的时间比较不准确。或是你的Master太忙了,Slave得到的时间有可能超时了。

这个时间表示:
Slave的SQL线程连接上Master的时间点和实际进行的SQL点的时间差别。例,当Slave和Master断开时间为30分钟,再时连上,这个时间为1800。
另一方面网络不稳也会出现问题。

记录:基于连接的DDOS攻击防范

遇到攻击。
采取措施:
做了DNS负载均衡,一个域名指向多台机器(负载均衡器的Session已经经分配较慢)
加入:

net.ipv4.tcp_synack_retries=3
net.ipv4.tcp_syn_retries=3
net.ipv4.tcp_max_syn_backlog=2048
net.ipv4.tcp_syncookies=1

封超过100个连接的IP:

#!/bin/sh
/bin/netstat -na|grep ESTABLISHED|awk ‘{print $5}’|awk -F: ‘{print $1}’|sort|uniq -c|sort -rn|grep -v -E ‘172.16|127.0’|awk ‘{if ($2!=null && $1>100) {print $2}}’>/tmp/dropip
for i in $(cat /tmp/dropip)
do
/sbin/iptables -I INPUT  -p tcp -m tcp -s $i –dport 80 –syn -j REJECT
echo “$i kill at `date`”>>~river/ddos
done

 

最终效果还是不明显,IP变化太大。

今天继续找找别的方法。

用Tcpdump抓取MySQL执行的SQL

#!/bin/bash
tcpdump -i eth0 -s 0 -l -w – dst port 3306 | strings | perl -e ‘
#!/bin/bash
while(<>) { chomp; next if /^[^ ]+[ ]*$/;
if(/^(SELECT|UPDATE|DELETE|INSERT|SET|COMMIT|ROLLBACK|CREATE|DROP|ALTER|CALL)/i) {
if (defined $q) { print “$q\n”; }
$q=$_;
} else {
$_ =~ s/^[ \t]+//; $q.=” $_”;
}
}’

数据库表结构设计方法及原则

转:http://blog.csdn.net/c_sharp_Rookie/archive/2009/01/15/3786317.aspx

在目前的企业信息系统中,数据库还是最佳的数据存储方式,虽然已经有很多的书籍在指导我们进行数据库设计,但应该那种方式是设计数据库的表结构的最好方 法、设计时应遵从什么样的原则、四个范式如何能够用一种方式达到顺畅的应用等是我一直在思考和总结的问题,下文是我针对这几个问题根据自己的设计经历准备 总结的一篇文章的提纲,欢迎大家一块进行探讨,集思广益。其中提到了领域建模的概念,但未作详细解释,希望以后能够有时间我们针对这个命题进行深入探讨。

1) 不应该针对整个系统进行数据库设计,而应该根据系统架构中的组件划分,针对每个组件所处理的业务进行组件单元的数据库设计;不同组件间所对应的数据库表之 间的关联应尽可能减少,如果不同组件间的表需要外键关联也尽量不要创建外键关联,而只是记录关联表的一个主键,确保组件对应的表之间的独立性,为系统或表 结构的重构提供可能性。

2)采用领域模型驱动的方式和自顶向下的思路进行数据库设计,首先分析系统业务,根据职责定义对象。对象要符合封 装的特性,确保与职责相关的数据项被定义在一个对象之内,这些数据项能够完整描述该职责,不会出现职责描述缺失。并且一个对象有且只有一项职责,如果一个 对象要负责两个或两个以上的职责,应进行分拆。

3)根据建立的领域模型进行数据库表的映射,此时应参考数据库设计第二范式:一个表中的所 有非关键字属性都依赖于整个关键字。关键字可以是一个属性,也可以是多个属性的集合,不论那种方式,都应确保关键字能够保证唯一性。在确定关键字时,应保 证关键字不会参与业务且不会出现更新异常,这时,最优解决方案为采用一个自增数值型属性或一个随机字符串作为表的关键字。

4)由于第一点所述的领域模型驱动的方式设计数据库表结构,领域模型中的每一个对象只有一项职责,所以对象中的数据项不存在传递依赖,所以,这种思路的数据库表结构设计从一开始即满足第三范式:一个表应满足第二范式,且属性间不存在传递依赖。

5)同样,由于对象职责的单一性以及对象之间的关系反映的是业务逻辑之间的关系,所以在领域模型中的对象存在主对象和从对象之分,从对象是从1-N或N-N的角度进一步主对象的业务逻辑,所以从对象及对象关系映射为的表及表关联关系不存在删除和插入异常。

6) 在映射后得出的数据库表结构中,应再根据第四范式进行进一步修改,确保不存在多值依赖。这时,应根据反向工程的思路反馈给领域模型。如果表结构中存在多值 依赖,则证明领域模型中的对象具有至少两个以上的职责,应根据第一条进行设计修正。第四范式:一个表如果满足BCNF,不应存在多值依赖。

7) 在经过分析后确认所有的表都满足二、三、四范式的情况下,表和表之间的关联尽量采用弱关联以便于对表字段和表结构的调整和重构。并且,我认为数据库中的表 是用来持久化一个对象实例在特定时间及特定条件下的状态的,只是一个存储介质,所以,表和表之间也不应用强关联来表述业务(数据间的一致性),这一职责应 由系统的逻辑层来保证,这种方式也确保了系统对于不正确数据(脏数据)的兼容性。当然,从整个系统的角度来说我们还是要尽最大努力确保系统不会产生脏数 据,单从另一个角度来说,脏数据的产生在一定程度上也是不可避免的,我们也要保证系统对这种情况的容错性。这是一个折中的方案。

8)应针 对所有表的主键和外键建立索引,有针对性的(针对一些大数据量和常用检索方式)建立组合属性的索引,提高检索效率。虽然建立索引会消耗部分系统资源,但比 较起在检索时搜索整张表中的数据尤其时表中的数据量较大时所带来的性能影响,以及无索引时的排序操作所带来的性能影响,这种方式仍然是值得提倡的。

9) 尽量少采用存储过程,目前已经有很多技术可以替代存储过程的功能如“对象/关系映射”等,将数据一致性的保证放在数据库中,无论对于版本控制、开发和部 署、以及数据库的迁移都会带来很大的影响。但不可否认,存储过程具有性能上的优势,所以,当系统可使用的硬件不会得到提升而性能又是非常重要的质量属性 时,可经过平衡考虑选用存储过程。

10)当处理表间的关联约束所付出的代价(常常是使用性上的代价)超过了保证不会出现修改、删除、更改 异常所付出的代价,并且数据冗余也不是主要的问题时,表设计可以不符合四个范式。四个范式确保了不会出现异常,但也可能由此导致过于纯洁的设计,使得表结 构难于使用,所以在设计时需要进行综合判断,但首先确保符合四个范式,然后再进行精化修正是刚刚进入数据库设计领域时可以采用的最好办法。

11)设计出的表要具有较好的使用性,主要体现在查询时是否需要关联多张表且还需使用复杂的SQL技巧。

12)设计出的表要尽可能减少数据冗余,确保数据的准确性,有效的控制冗余有助于提高数据库的性能。

==================================================

以前也总写一些这方面的总结,无耐没办法提升到理论层次。今天看到这个感觉很不错,所以就转过来了。对一个大系统设计往往需要拆分成不同的功能去实现,同样对于内部数据也尽量减少关连直接操作。可以用基于主建的Hash类数据结构来获得相应的数据。设计表结构中太多东西需要注意了,以上原则部分也是一个基础部分,需要记住的。

大表删除数据的思路

作者:吴炳锡 来源:http://www.mysqlsupport.cn/ 联系方式:select unhex(‘777562696E67786940676D61696C2E636F6D’); 载请注明作/译者和出处,并且不能用于商业用途,违者必究。

对于一个2000W的大表,一次走一个全表扫描确是很困难的。不过对于100W的表走一个全描扫也困难。

如果做这件事情又不想影响太大,就要分步来完成。

我给你一个思路你来参考一下。
首先衡量删除操作有多大。
selet count(*) from table1 a ,table2 b where a.pid=b.pid;
如果都有索引的话,这个操作还是挺快的。
如果操作的操作大于原表的40%,那么很有必要重建这个表了。

重建表的方法:就是按条件提取数据到一个新表,最后改名完成。这是一种方案。

另一种 删除方向。

上面通过比较觉的需要删除的量不是太大时,把需要删除的PID生到到另一个临时表中。
mysql DBname -e “select a.pid from table1 a ,table2 b where a.pid=b.pid”>del_pid.txt;

sed -i ‘1d’ del_pid.txt
awk ‘{print “delete from table1 where pid=”,$1,”;”}’ del_pid.txt >del_pid.sql
mysql DBname<del_pid.sql

这样把SQL拆成多个SQL执行速度应该不会太慢了。

如果还是感觉不行,那就只能分段操作了。

 

备注:http://bbs3.chinaunix.net/thread-1453362-1-1.html

Sun的CxO大会 归来

     今天上午去参加了Sun的CxO大会,本想得到一些Sun关于MySQL发展方向的消息,但并没得到确切的消息。MySQL的Richard Mason(Sun公司MySQL全球销售副总裁)只是透漏Oracle收购了Sun后MySQL也可能做为Oracle的一个产品去运营。

     在大会上Richard更多的强调MySQL的策略就是攻占中端市场,网站市场。这点我是认同的。并切相信MySQL在这方面做的很棒。此次大会也可以说是Sun决心在中国建立一个好的销售渠道的一个表现。顺便支持一下Sun的行为。

     希望MySQL发展的更好吧。也期待5.4的Release。

     此次大会也一点稳人心的感觉。MySQL现在虽然属于Oracle了,大家不用担心他会被灭掉。MySQL还会永远的活下去。

mysql.user表怎么有两个root?密码怎么改?

作者:吴炳锡 来源:http://www.mysqlsupport.cn/ 联系方式:select unhex(‘777562696E67786940676D61696C2E636F6D’); 载请注明作/译者和出处,并且不能用于商业用途,违者必究。
MySQL的用户名有两部分组成: 用户名@机器名

用户名:一般用字母组成。
机器名:可以是机器IP也可以机器名。机器名可以用dns也可以在/etc/hosts中声明。

所以可以称为不是两个root用户。

反应到user表中,用户名对应user,机器名对应于host,密码对应于password
一个用户名完整的标识为:user@host

更改密码:
set  password for ‘用户名’@’主机名‘=password(‘yourpassword’);

所以你见到的两个Root不能算是一个用户名的。

MySQL Cluster 7.0 新特性

作者:吴炳锡 来源:http://www.mysqlsupport.cn/ 联系方式: wubingxi#gmail.com 转载请注明作/译者和出处,并且不能用于商业用途,违者必究。

1. 开始支持在Windows建立MySQL Cluster(不是稳定功能,不过有兴趣的可以测试).
2. 在线添加节点或节点组
3. 数据节点开始支持多线程。这样对于CPU的利用就更加有效了。
4. 配置文件缓存功能,减少对配置文件的重复读次数。
5. 快照备份(以前也有功能)
6. 动态结果集缓存分配
7. 加强了ddl语句的支持(新功能)减少运行ddl语句时,节点失败。
8. 在集群复制上支持ipv6.
9. 可以从备份集恢复特定的表或是特定的数据库。
10. 对于数据文件系统支持进行了加强。
11. 自动创建日值组和表空间
12. 改良了内部的消息管理机制(这是一个新特性,感觉应会对性能提高挺大的)

总的来说MySQL Cluster 7.0 改动挺多,值再去测试一次。另外在实际应用中MySQL Cluster 还有着不可取代的
位置。虽然有很人报怨内部网络通信慢之类的,但随着更多交易方面的应用,对事务要求的严格,MySQL Cluster的优势
就慢慢提现出来了。

参考:
http://dev.mysql.com/doc/refman/5.1/en/mysql-cluster-changes-5-1-ndb-7-0.html

MySQL大表备份

作者:吴炳锡 来源:http://www.mysqlsupport.cn/ 联系方式:select unhex(‘777562696E67786940676D61696C2E636F6D’); 载请注明作/译者和出处,并且不能用于商业用途,违者必究。

      这里所说的大表是超地4G以上的表,我目前见到过最大为60多G的单表,对于这种表每天一个全备可以说是一件很痛苦的事。
那么有没有办法,可以实现一个全备加增量的备份呢。
答案当然是有的。

在常规环境直可以用全备加binlog一同保存。
  这种环境大多可以用一个Slave上进行备份操作。
  思路:
 先停止Slave的同步,刷新buffer,对于Innodb 如果想直接拷贝还需要把innodb_max_dirty_pages_pct这个值置为零,然后在执行一次flush tables;
 就可以cp了。如果是Dump出来可以这这样做。

      这个方案目前来看也是比较完美的,但一个并发力度大的应用一天的Binlog有可能能达到50G-60G,这样的系统开Binlog可以说是对系统的IO性能及整体性能都有早影响。

另一种方案就是基于表的上数据的罗辑变化进行备份。
主体思想:全备加逻辑备份。
逻辑备份:当有数据插入时,利用触发器同时写入另一个表,当数据更新时,我们同时记录一下,更新后的数据情况到另一个表。
当有删除操作时,只需要记录一下,删除的主建ID就行。

例子:
要备份的表:

CREATE TABLE `wubx` (  `id` int(11) NOT NULL auto_increment, 
`user_id` int(11) NOT NULL default '0', 
 `friend_id` int(11) NOT NULL default '0', 
 `dir_id` int(11) NOT NULL default '0', 
 `created` int(11) NOT NULL default '0', 
 UNIQUE KEY `id` (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

对于这个表我们需要建一个记录有新数据变化的表为:
mysql> create table wubx_ii like wubx;
Query OK, 0 rows affected (0.00 sec)

mysql> create table wubx_uu like wubx;
Query OK, 0 rows affected (0.00 sec)
mysql> create table wubx_dd ( id int(11));
Query OK, 0 rows affected (0.00 sec)

建立相应的触发程器

记录insert的操作:
delimiter //
create trigger wubx_ii after insert on wubx for each row begin insert into  wubx_ii set id=new.id,user_id=new.user_id,friend_id=new.friend_id,dir_id=new.dir_id,created=new.created; end//
记录update的操作:
create trigger wubx_uu after update on wubx for each row begin replace into  wubx_uu set id=new.id,user_id=new.user_id,friend_id=new.friend_id,dir_id=new.dir_id,created=new.created; end//
记录删除的操作:
create trigger wubx_dd after delete on wubx for each row begin insert into wubx_dd values(old.id); end//

delimiter ;

操作:
先备份原始表wubx里的数据:
进行:
insert into wubx values(”,1,10,1,1198464252);
insert into wubx values(”,1,11,1,1198464252);
insert into wubx values(”,1,2,1,1198464252);
insert into wubx values(”,2,10,1,1198464252);
insert into wubx values(”,2,12,1,1198464252);
insert into wubx values(”,3,12,1,1198464252);
update wubx set dir_id=5 where user_id=3;
update wubx set dir_id=4 where user_id=3;
delete from wubx where user_id=2 and friend_id=12;
现在要实现增量备份:
取出insert的操作:
mysql -e ” select concat(‘replace into wubx set id=’,id,’,user_id=’,user_id,’,friend_id=’,friend_id,’,dir_id=’,dir_id,’,created=’,created,’;’) from wubx_ii;”>>backup_ii.sql

取出update的操作:
mysql -e ” select concat(‘update wubx set user_id=’,user_id,’,friend_id=’,friend_id,’,dir_id=’,dir_id,’,created=’,created,’ where id=’,id,’;’) from wubx_uu;”>>backup_uu.sql

取出delete的操作:
mysql -e “select concat(‘delete from wubx where id=’,id,’;’) from wubx_dd”>>backup_dd.sql

这样利用这些逻辑的备份加是完毕备份恢复到当前恢复点就很容易了。这里不演示。

这个操作最好用一个程序完成,当取完罗辑备份后,做一个标记点去清楚备份完的数据,以保证,逻辑记录表里的数据量比较少是正确的。