2012年3月 的存档

mysqldump 存储过程

2012年3月14日 没有评论

mysqldump是mysql自带的一个备份数据库的工具,使用mysqldump可以很方便的把已有的数据库导出来,使用

mysqldump --help
如果MYSQL_HOME/bin没有加入PATH,需要指定去路径

可以看到有很多可选参数。

需要注意:默认情况下,mysqldump并不会导出数据库的存储过程和函数,如果数据库上创建了存储过程且备份是需要备份存储过程,那就需要用参数 -R 来指定,例如:

mysqldump -u root -p passwd -R testDB > db.sql

php 获取当前时间的毫秒数

2012年3月13日 没有评论

php本身没有提供返回毫秒数的函数,但提供了一个microtime()函数,该函数返回一个array,包含两个元素,一个是秒数,一个是小数表示的毫秒数,借助此函数,可以很容易定义一个返回毫秒数的函数,例如:

function getMillisecond() {
    list($s1, $s2) = explode(' ', microtime());
    return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
}

需要注意,在32位系统中php的int最大值远远小于毫秒数,所以不能使用int类型,而php中没有long类型,所以只好使用浮点数来表示。由于使用了浮点数,如果精度设置不对,使用echo显示获取的结果时可能会不正确,要想看到输出正确的结果,精度设置不能低于13位。

关于浮点数精度问题,可以参考:理解 php 浮点数精度值

理解 php 浮点数精度值

2012年3月13日 没有评论

php中浮点数的精度值是用来控制输出该浮点数时使用的,可以理解为控制输出的位数,精度值不同,看到输出结果也可能不一样,注意:其内部还是按照实际值存储的,当两个浮点数进行四则运算时,用的还是其本来的值

php的配置文件中使用precision来设定全局指定浮点数的精度值,似乎每个发行版,它的默认设置都不太一样,我在window下看到是12,在linux下看到此值是14,当然也可以通过程序中使用ini_set来改变全局设置,例如:

	ini_set("precision", "15");

对于精度我一直理解为小数点后保留多少,那么在php的浮点数中是这样的么?答案是否定的。

浮点数其实是整数部分和小数部分组成,这里的精度是指整数部分的位数加小数部分的位数不能超过其精度最大值,如果超过,则按照四舍五入的方法截断到最大的精度值。整数部分如果是0,则不计位数,小数部分末尾0也不计入位数。另外对于同一个数,precision的不同,可能显示的出来表现形式也不一样。下面通过例子的方式来说明。

整数部分为 0 情况

	$num = 0.12345600000000000;
	//整数部分为0 ,位数为 0 ,小数部分末尾的 0 不计入位数,所以总位数为 6

	ini_set("precision", "12");
	echo $num; // 0.123456
	//未超过精度值,显示的结果为 0.123456

	ini_set("precision", "3");
	echo $num; // 0.123
	//超过精度值,保留3位

	ini_set("precision", "5");
	echo $num; // 0.12346
	//超过精度值,保留5位

这种情况下,精度值等价于小数点后保留几位。

整数部分大于 0 情况

	$num = 12.12345600000000000;
	//整数部分为12 ,位数为 2 ,小数部分末尾的 0 不计入位数,位数为6,所以总位数为 2 + 6

	ini_set("precision", "12");
	echo $num; // 12.123456
	//未超过精度值,显示的结果为 12.123456

	ini_set("precision", "3");
	echo $num; // 12.1
	//超过精度值,整数部分位数为 2 ,所以只保留一位小数

	ini_set("precision", "5");
	echo $num; // 12.123
	//超过精度值,整数部分位数为 2 ,所以只保留3位小数

可以看到小数点后保留的位数跟精度已经整数部分的位数有关。

整数部分大于 0 情况 之二

	$num = 12345678.12345600000000000;
	//整数部分为12345678 ,位数为 8 ,小数部分末尾的 0 不计入位数,位数为6,所以总位数为 8 + 6

	ini_set("precision", "12");
	echo $num; // 12345678.1235
	//超过精度值,显示的结果为 12345678.1235

	ini_set("precision", "3");
	echo $num; // 1.23E+7
	//超过精度值,且整数部分位数超过精度,小数部分舍弃,且整数部分只取3位

	ini_set("precision", "5");
	echo $num; // 12346000
	//超过精度值,且整数部分位数超过精度,小数部分舍弃,且整数部分只取5位

上述例子中可以看到,精度值也关系到整数部分的截取。注意到最后两个例子中显示的方式不一样,一个是使用科学计数法,一个是后面用 0 补。通过实验得出的结论是当整数部分的位数 减去 精度值 大于 4 的时候,使用科学计数法的方式,否则后面用 0 补,换句话说,就是整数部分位数超过精度值后,截断后,补 0 的个数不会超过 4 。

浮点数运算

	$num1 = 1331625729.687;
	$num2 = 1331625730.934;
	ini_set("precision", "8");

	echo $num1 . '
';
	echo $num2 . '
';

	$sub = $num1 - $num2;

	echo $sub . '
';
//输出的结果为:
/*
	1331625700
	1331625700
	-1.247
*/

上述例子就说明了精度值只是控制显示结果,内部存储还是原始值,所以 $sub 的值为1331625729.687减1331625730.934。

分类: PHP 标签:

Open Flash Chart X坐标显示中文

2012年3月12日 2 条评论

从官网上下载的已编译好ofc的swf文件,x坐标是无法显示中文的,对于中文系统的用户,似乎有点不够友好,好在作者提供了源代码,我们只需要简单的修改就可以实现显示中文的功能。关于如何编译,可以查看文章:自己动手编译Open Flash Chart

需要说明的是,由于x坐标上的文本支持旋转,所以必须需要在swf中内嵌字体,作者也给出了这样的注释:Ugh, ugly code so we can rotate the text。作者内嵌的字体是Arial,该字库不支持中文,我们可以使用SimSun字体代替,它也是window操作系统是默认字体,但是体积比英文字体Arial大很多,所以最后编译出来的swf也比较大,我编译出来的大小是6.8M。

通过FlashDevelop打开项目,在open-flash-chart/elements/axis 下找到XAxisLabels.as文件并打开它,按如下提示修改:

修改 1:
注释下面内容,大概在25行
[Embed(systemFont = 'Arial', fontName = 'spArial', mimeType = 'application/x-font')]

在下面增加如下内容,如果系统没有安装SimSun,需要先安装
[Embed(systemFont = 'SimSun', fontName = 'spSimSun', mimeType = 'application/x-font')]

修改 2:
大概在226行有如下代码
fmt.font = "spArial";
把spArial替换成上述fontName指定的值,即
fmt.font = "spSimSun";

代码修改完后,重新编译,应该会在当前目录下重新生成一个新的swf,此swf就能让x坐标显示中文了。

上述编译好的新swf虽说能正常在x坐标上显示中文,但是由于体积庞大,用户体验应该不会太好。目前我的解决办法是,同时让原始swf和先编译好的swf一起加载,原始swf体积小,会在第一时间呈现给用户,体积大flash让其要一个隐藏的div中慢慢加载,当它加载完成时,隐藏先前显示的swf,用能显示中文的swf替换,这样效果还不错,另外浏览器有缓存功能,所以一旦某次成功加载过显示中文的swf,以后显示的速度还是蛮快的。改天有空做一个demo看看。

分类: web前端 标签:

Mysql 配置 master/slave

2012年3月12日 没有评论

关于mysql master/slave的应用场景就不做介绍,本文主要讲解是配置。配置相对还是比较简单,只需要在master和slave的mysql的配置文件中增加几行就可以了。

Master上修改:

修改master配置文件,linux默认为/etc/my.cnf,在 mysqld 段中添加如下配置。

server-id = 1
# 唯一ID,master/slave 集群中不能重复,默认master使用 1
log-bin = mysql-bin
# 同步事件的日志记录文件,master/slave通过该文件来达到同步的目的

binlog-do-db = db_name
# 需要同步的数据库名,如果多个库,重复设置binlog-do-db即可
# 如果指定,mysql服务器只会记录指定库的操作日志到mysql-bin中
# 也可以不指定,此时除binlog-ignore-db中指定的库外,其它所有库的操作日志都会记录在mysql-bin中

binlog-ignore-db = db_name1
# 忽略同步的数据库名,如果多个库,重复设置binlog-ignore-db即可
# 可以不指定

另外需要在master上需要创建一个用户,并且赋予其replication slave的权限,例如:

grant replication slave on *.* to slaveuser@192.168.1.3 identified by '123456';

其中slaveuser是用户名,192.168.1.3是slave的ip,可以使用通配符,例如192.168.1.%表示192.168.1.0 – 192.168.1.255这个网段所有slave都可以能通过该用户来访问master,123456是slaveuser对应的密码。

slave上修改:

修改配置文件,在 mysqld 段中增加如下配置:

server-id   = 2
# 唯一ID,不能与master或其他slave重复

master-host	= master ip
master-port = 3306
# master 服务的端口

master-user = slaveuser
master-password = 123456
# master上已授权replication slave的用户和密码

replicate-do-db = tagphi_asm
# 需要同步的数据库名,如果多个库,重复设置replicate-do-db即可
# 如果指定,slave上只会同步更新制定的库,其他库的更新将被忽略
# 可以不指定,此时slave会更新master上mysql-bin日志中记录所有库

上面主要讲了 master/slave 的配置细节,接下来通过实例来说明。

如果对于一个全新的环境,假设master服务器的ip为192.168.1.68,需要同步的库为testDB,

master 配置:

server-id   = 1
log-bin = mysql-bin
binlog-do-db = testDB

创建并授权用户:

grant replication slave on *.* to slaveuser@192.168.1.3 identified by '123456';

slave 配置:

server-id   = 2
master-host=192.168.1.68
master-port=3306
master-user=slaveuser
master-password=123456
replicate-do-db=testDB

配置到此就完成了,分别重启master和slave上的mysql服务器。

在master上使用如下命令:

show master status;

输出结果为:
+------------------+----------+--------------+-------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB              |
+------------------+----------+--------------+-------------------------------+
| mysql-bin.000016 |      892 |   testDB     |                               |
+------------------+----------+--------------+-------------------------------+

在slave上使用如下命令:

show slave status \G

如果输出的Slave_IO_Running和Slave_SQL_Running都为yes说明master,slave正常工作。现在在master创建数据库testDB以及其对应的表,应该在slave上会同步创建testDB库和表,同时如果master上的testDB中的表中数据有变化(插入、更新、删除),slave上对应的表也会做相应的变化。

上面的配置实例是在一开始规划数据库的部署就是用master,slave的情况,但现实中往往可能是先有一台mysql服务器,系统运行一段时间后,才准备使用master、slave的架构,这时我们的数据库中已经有了数据,另外记录log的文件也可能清除过,而且数据库的数据随时都可能变化,这种情况下,配置同上面的几乎一致,但需要额外处理一些其他的事,。这里也假设master服务器的ip为192.168.1.68,需要同步的库为testDB。

master上服务器的配置修改同上,修改配置后重新mysql服务,另外需要把testDB数据库使用mysqldump备份出来,同时使用show master status命令把输出的结果中的File和Position信息记录下来,命令如下:

锁定数据库为只读状态,防止在备份数据库时外部程序对数据修改
flush tables with read lock;

查看master的状态,同时记录File和Position
show master status;
+------------------+----------+--------------+-------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB              |
+------------------+----------+--------------+-------------------------------+
| mysql-bin.000012 |      653 |   testDB     |                               |
+------------------+----------+--------------+-------------------------------+

备份数据库
mysqldump -uroot -p123456 testDB > testDB.sql

备份完数据库后解除数据库的锁定
unlock tables;

slave配置也同上,注意此时启动slave的mysql服务时不启动slave服务,可以通过在配置文件中使用

skip-slave-start = true

来实现。启动mysql服务后,先在上面创建数据库testDB,然后将master上备份导入到testDB中,在mysql客户端下执行如下命令:

设定master信息,其中MASTER_LOG_FILE和MASTER_LOG_POS就是上面记录的File和Position的值

CHANGE MASTER TO MASTER_HOST='192.168.1.68',
MASTER_USER='slaveuser',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000012',
MASTER_LOG_POS=653;

启动slave

start slave;

不出意外,master,slave就正常工作了,另外把配置文件skip-slave-start去掉,下次重启slave上的mysql服务就会自动启动slave的。

自己动手编译Open Flash Chart

2012年3月11日 没有评论

Open Flash Chart是一个优秀的报表图形工具,由ActionScript 3.0语言开发的。通过它可以很简单的实现线状图、柱状图(包括3D)、饼图等。同时它提供了基于PHP, Perl, Python, Ruby, .NET, Google Web Toolkit 以及 JAVA来生成数据的库文件。

项目的主页:http://teethgrinder.co.uk/open-flash-chart-2,可以在http://teethgrinder.co.uk/open-flash-chart-2/downloads.php下载到最新版本,本文下载的是版本是:Version 2 Lug Wyrm Charmer(似乎这个版本是2009年发布,以后就没有再更新了),作者提供了AS3的源代码,我们可以通过源代码重新编译生成新的swf。

需要下载的工具有FlashDevelop和Flex SDK

FlashDevelop 下载地址:http://www.flashdevelop.org/community/viewforum.php?f=11

Flex SDK 下载地址:http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+3

下载安装上述软件后就可以动手编译了,本人是在windows下编译,FlashDevelop版本为3.0,Flex SDK版本为3.2。

Open Flash Chart的源代码位于压缩包(open-flash-chart-2-Lug-Wyrm-Charmer.zip)中的open-flash-chart文件夹里,解压下载的压缩包,进入open-flash-chart文件夹,点击open-flash-chart.as3proj,此时项目就通过FlashDevelop打开了,要编译前还需要指定一下Flex SDK位置,步骤为:Tools –> program settings,在出来的对话框左边的Plugins下面点击AS3Context,然后再右边的language下面可以看到Flex SDK Location,把它指定为本机安装的路径,我的是C:\Tools\Adobe\Flex Builder 3 Plug-in\sdks\3.2.0。至此,就可以自己重新编译Open Flash Chart了。

Mysql 存储过程注释问题

2012年3月9日 没有评论

Mysq支持单行和多行这两种注释代码的方式,单行使用两个减号,多行使用/* */

--  单行注释

/*
   多行注释,第一行
   第二行
   第三行
*/

曾经碰到过在本机window的mysql客户端下可以顺利创建存储过程,拿到linux服务器的客户端中创建的时候老是提示存储过程有错误,错误的原因就是因为单行注释造成,在大部分linux(至少我所接触过的所有linux中)的mysql客户端下单行注释符号和注释的内容之间至少要有一个空格,不能使用tab代替空格。

为了保证存储过程的兼容性,在使用单行注释的时,在注释符号后增加两个空格。

Mysql 存储过程查询结果赋值到变量的方法

2012年3月9日 没有评论

把查询结果赋值到变量,大部分情况下使用游标来完成,但是如果明确知道查询结果只有一行(例如统计记录的数量,某个字段求和等),其实可以使用set或into的方式来实现赋值。示例代码:

drop table if exists test_tbl;
create table test_tbl (name varchar(20), status int(2));
insert into test_tbl values('abc', 1),('edf', 2),('xyz', 3);

drop procedure IF EXISTS pro_test_3;
delimiter //
create procedure pro_test_3()
begin
--  方式 1
	DECLARE cnt INT DEFAULT 0;
	select count(*) into cnt from test_tbl;
	select cnt;

--  方式 2
	set @cnt = (select count(*) from test_tbl);
	select @cnt;

--  方式 3
	select count(*) into @cnt1 from test_tbl;
	select @cnt1;

--  多个列的情况下似乎只能用 into 方式
	select max(status), avg(status) into @max, @avg from test_tbl;
	select @max, @avg;
end
//
delimiter ;

call pro_test_3();

Mysql存储过程参数名和表列明相同引起的问题

2012年3月9日 1 条评论

下面存储过程原本是想根据传入的status值来更新对应列的name,代码如下:

drop table if exists test_tbl;

create table test_tbl (
	name varchar(20),
	status int(2)
);

insert into test_tbl values
('abc', 1),
('edf', 2),
('xyz', 3);

drop procedure IF EXISTS pro_test_1;
delimiter //
create procedure pro_test_1(in status int(2))
begin	
	update test_tbl set name = concat(name, '_new') where test_tbl.status = status;
end
//
delimiter ;

call pro_test_1(1);

select * from test_tbl;

调用上述存储过程后发现所有记录的name都被更新了,存储过程就只有一个update语句,而且执行了,问题出在where条件上,原意是where的第一个status为表的列名,第二个是参数,此处被存储过程都理解为参数,所以where条件永远是true。因此一定要注意列名和参数名相同问题,否则在执行delete或update时会酿成大祸。解决方法有3中,一是修改参数的名字,二是在字段前加上表名,第三种是update使用预处理语句的方式。代码如下:

第二种方法代码:

update test_tbl set name = concat(name, '_new') where status = status;
修改为:
update test_tbl set name = concat(name, '_new') where test_tbl.status = status;

第三种方法代码:

	set @t = status;
	PREPARE STMT FROM "
		update test_tbl  set name = concat(name, '_new') where status = ?
	";
	EXECUTE STMT USING @t;

另外定义游标时候可能也会出现这样的问题,解决方法跟上面类似,注意游标在申明前不能使用set,示例代码:

drop table if exists test_tbl;

create table test_tbl (
	name varchar(20),
	status int(2)
);

insert into test_tbl values
('abc', 1),
('edf', 2),
('xyz', 3);

drop procedure IF EXISTS pro_test_2;
delimiter //
create procedure pro_test_2(in status int(2))
begin	
	DECLARE done INT DEFAULT 0;
	DECLARE na varchar(50) DEFAULT NULL;

	DECLARE cur CURSOR FOR 
		select name from test_tbl where test_tbl.status = status;
--  或
--  	select name from test_tbl t where t.status = status;
--  再或, 注意后面需要为 @s 赋值
--  	select name from test_tbl where test_tbl.status = @s;

	DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

--  set @s = status;

	open cur;
	REPEAT
		FETCH cur INTO na;
		if not done then
			select na;				
		end if;
 	UNTIL done END REPEAT;
	CLOSE cur;	
end
//
delimiter ;

call pro_test_2(1);

nginx include 指令

2012年3月8日 没有评论

当一个nginx服务器中运行着多个虚拟主机,如果把这些虚拟主机的配置都放在主配置文件(nginx.conf)中,造成主配置文件很大,对日后的维护带来不便。其实可以把每个虚拟主机的配置信息存放在一个单独文件,然后使用include指令把该文件嵌入到主配置文件中即可。

假设有两个虚拟主机:www.netingcn.com和www.netingcn.net,分别为其创建配置文件为www_netingcn_com.conf和www_netingcn_net.conf,在nginx默认存放配置文件的目录下(/usr/local/nginx/conf/)建立一个vhost目录,把上述创建的两个文件存放在此目录中,并把虚拟主机相应的配置移到配置文件中。然后在nginx的主配置文件中添加如下配置即可:

    include /usr/local/nginx/conf/vhost/www_netingcn_com.conf;

    include /usr/local/nginx/conf/vhost/www_netingcn_net.conf;
分类: Linux, nginx 标签:

无觅相关文章插件,快速提升流量