2012年11月26日星期一

MySQL 5.5 复制格式

基于语句复制的优点

从 MySQL 3.23 起就已经支持基于语句复制了

不用把大量的数据写进日志文件。当删除或者更新大量的数据时,日志的储存空间增长速度不会很快

日志记录了那些数据更改的SQL语句,保证数据库的一致。

基于语句复制的缺点

  • 基于语句的复制中,以下语句是不安全的。使用基于语句的复制中,并非所有的修改数据(例如 INSERT DELETE, UPDATE和 REPLACE语句)语句都可以成功被复制。在使用基于语句的复制中,任何不确定的行为是难以复制的。诸如这类数据修改语言(Data Modification Language),还有以下这些
  • 在基于行的复制中,对于 INSERT ... SELECT 的 SQL 语句,需要行级别的锁定。
  • 在需要进行表扫描(因为 WHERE 子句中没有用到索引)的UPDATE 语句中,在基于行的复制中必须锁定行
  • 对于使用InnoDB引擎的:一个使用 AUTO_INCREMENT 的 INSERT 语句,会阻塞其他不冲突的 INSERT 语句。
  • 对于复杂的语句,语句必须先被从服务器识别和执行,再进行更新或插入操作。基于行的复制,从服务器只会修改受影响的行,不执行所有语句。
  • 在从服务器上在识别出现错误的话,特别是在执行复杂的语句时,基于语句的复制会随着时间的推移,那些受影响的行可能会慢慢增加误差。
  • 存储函数调用语句时会执行相同的 NOW()值。
  • 用户自定义的函数功能必须是唯一确定的,才能适用于从服务器
  • 在主服务器和从服务器之间,表的定义必须保持一致

基于行复制的优点

  • 所有的改变都能被复制,这在复制中是最安全的一种方式。

mysql 数据库不会被复制, mysql 数据库不会被看作一个节点特定的数据库。但是,基于语句的复制会复制这些信息,包括 GRANT、REVOKE 还有触发器,存储过程和视图,都会被从服务器复制。

对于这些语句 CREATE TABLE ... SELECT,用 CREATE 语句创建表,都是用基于语句的复制的格式。而数据的插入则是使用 行复制。

对于下面的语句,在主服务器上只要很少的行锁定,能支持高并发。

INSERT ... SELECT

带有 AUTO_INCREMENT 的 INSERT 语句


UPDATE or DELETE statements with WHERE clauses that do not use keys or do not change most of the examined rows.


Row-Based 日志和复制的用法



  • RBL,非事务表和停止从服务器。 如果用 row-based 记录时,当从服务器在更新一个非事务表时,从服务器忽然被停止了,从服务器的数据库的可能会处于非一致的状态。所以当用 row-based 记录时,推荐用支持事务的引擎,如 InnoDB。
  • 数据库级别的复制选项。这些 --replicate-do-db, --replicate-ignore-db, 和 --replicate-rewrite-db 选项在基于  row-based 和  statement-based 来记录时,区别是很大的。基于这一点,尽量避免使用数据库级别的选项而改用表级别的选项,诸如  --replicate-do-table 和 --replicate-ignore-table
  • 不支持过滤 server ID 系统变量。经常会遇到这样一个场景:在 UPDATE 或者 DELETE 语句中通过 WHERE 中用 @@server_id <> id_value 语句来过滤掉从服务器的改变。如 WHERE @@server_id <> 1 。这个在用 row-based 来记录时,不能正常的工作。如果你一定要用 server_id 系统变量来声明过滤,要有 --binlog_format=STATEMENT.你也可以在  CHANGE MASTER TO 语句中 用IGNORE_SERVER_IDS 选项来过掉server_id 系统变量的影响。
  • 二进制日志缺乏校验
  • 当系统变量 slave_exec_mode 的值是 IDEMPOTENT 时,未能将更改应用于row-based 记录。因为无法找到原来的行不触发一个错误或会导致复制失败。这意味着更新不能成功的应用于从服务器上。所以主服务器和从服务器不会再同步。

2012年11月5日星期一

CURL 模拟登陆并获取数据

    在做采集程序时,有时我们要抓取一些登录才能访问的页面。但是有时即使我们登录成功了,却还是无法抓取相关页面,这是为什么呢?

    嗯,最有可能的原因是没把登录成功后的 cookie 一并传递过去。

    对于一些安全防范措施不是做得很高的网站,我们可以通过 PHP 的函数 curl_setopt 来登录的。

<?php
//在指定目录中建立一个具有唯一文件名的文件。如果该目录不存在,tempnam() 会在系统临时目录中生成一个文件,并返回其文件名。 
$cookie_file tempnam('./tmp','cookie');//其中 cookie 为文件名的前缀
$postfield 'LoginForm[username]=admin&LoginForm[password]=admin&LoginForm[rememberMe]=0&yt0=Login';
$url "http://localhost/testdrive/index.php?r=site/login";//登录 提交的 url,可以通过 firfox 的 firebug 工具或者 google chrome 的开发人员工具来查看
$ch curl_init($url);
curl_setopt($chCURLOPT_RETURNTRANSFER1);
curl_setopt($chCURLOPT_HEADER0);
curl_setopt($chCURLOPT_POST1);
curl_setopt($chCURLOPT_COOKIEJAR$cookie_file);//保存 cookie 的文件
curl_setopt($chCURLOPT_SSL_VERIFYPEERfalse);
curl_setopt($chCURLOPT_POSTFIELDS,$postfield);
$strlen curl_exec($ch);

$url "http://localhost/testdrive/index.php";//访问登录后的页面。
$ch curl_init($url);
curl_setopt($chCURLOPT_RETURNTRANSFER0);
curl_setopt($chCURLOPT_SSL_VERIFYPEERfalse);
curl_setopt($chCURLOPT_COOKIEJAR$cookie_file);//再次发送请求时,cookie 就会自动传递过去
$strlen curl_exec($ch);
?>

2012年11月1日星期四

PHP 5 文字图片混合水印与缩略图

一、水印制作

   1.水印文字

    PHP 中为图片打上水印文字主要是通过 GD 库提供的 imagettftext() 函数来实现的。

    其过程为:载入图片 =》 调好水印文字的颜色 =》 打上水印

<?php
$img 'Desert.jpg';//图像的路径。这里以 Windows 7 自带的一幅沙漠的图片为例
$img_info getimagesize($img);

//载入图像到PHP,转成 PHP 可识别的编码
switch($img_info[2]{
  case 1:
    $res imagecreatefromgif($img);//返回一图像标识符,代表了从给定的文件名取得的图像。 
    break;
  case 2:
    $res imagecreatefromjpeg($img);
    break;
  case 3:
    $res imagecreatefrompng($img);
    break;    
}

// 为一幅图像分配颜色(相当于 PhotoShop 的调色板)
// imagecolorallocate ( resource image, int red, int green, int blue )  返回一个标识符,代表了由给定的 RGB 成分组成的颜色。
$te imagecolorallocate($res,225,225,225);

//rand(0,10)倾斜度。msyh.ttf 是微软雅黑字体,可在 C:\Windows\Fonts 找到。然后拷贝到该文件的目录下
imagettftext($res,12,rand(0,10),20,80,$te,'msyh.ttf',"我的博客 www.woqilin.net");

switch($img_info[2]{
  case 1:
    header("Content-type: image/gif");
    imagegif($res);//以 GIF 格式将图像输出到浏览器
    break;
  case 2:
    header("Content-type: image/jpeg");
    imagejpeg($res);
    break;
  case 3:
    header("Content-type: image/png");
    imagepng($res);
    break;    
}
?>

   2.水印图片

    PHP 中为图片打上图片水印是通过 imagecopy() 函数来实现的。

<?php
$img 'Desert.jpg';//图像的路径。这里以 Windows 7 下一幅沙漠的图片为例,像素为 1024 X 768
$img_info getimagesize($img);

//载入图像到PHP
switch($img_info[2]{
  case 1:
    $res imagecreatefromgif($img);//返回一图像标识符,代表了从给定的文件名取得的图像。 
    break;
  case 2:
    $res imagecreatefromjpeg($img);
    break;
  case 3:
    $res imagecreatefrompng($img);
    break;    
}

$logo 'logo-mongodb.png';//像素为 210 X 90 ,该 logo 可从 http://www.mongodb.org/ 下载
$logo_info getimagesize($logo);
switch($logo_info[2]{
  case 1:
    $res_logo imagecreatefromgif($logo);//返回一图像标识符,代表了从给定的文件名取得的图像。 
    break;
  case 2:
    $res_logo imagecreatefromjpeg($logo);
    break;
  case 3:
    $res_logo imagecreatefrompng($logo);
    break;    
}

//bool imagecopy ( resource dst_im, resource src_im, int dst_x, int dst_y, int src_x, int src_y, int src_w, int src_h )
//将 src_im 图像中坐标从 src_x,src_y 开始,宽度为 src_w,高度为 src_h 的一部分拷贝到 dst_im 图像中坐标为 dst_x 和 dst_y 的位置上。 
imagecopy($res,$res_logo,100,100,0,0,210,90);

switch($img_info[2]{
  case 1:
    $res imagegif($res,'new.gif');//以 GIF 格式将图像输出文件
    break;
  case 2:
    $res imagejpeg($res,'new.jpg');
    break;
  case 3:
    $res imagepng($res,'new.png');
    break;    
}
?>

二、缩略图

     在 PHP 中要生成图片的缩略图,主要是靠函数 imagecopyresized() 来实现。


<?php
$img 'Desert.jpg';//图像的路径。这里以 Windows 7 下一幅沙漠的图片为例,像素为 1024 X 768
$img_info getimagesize($img);

//载入图像到PHP
switch($img_info[2]{
  case 1:
    $res imagecreatefromgif($img);//返回一图像标识符,代表了从给定的文件名取得的图像。 
    break;
  case 2:
    $res imagecreatefromjpeg($img);
    break;
  case 3:
    $res imagecreatefrompng($img);
    break;    
}

//新建一个真彩色图像
$new imagecreatetruecolor(400,400);
//bool imagecopyresized ( resource dst_image, resource src_image, int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h )
//将一幅图像中的一块正方形区域拷贝到另一个图像中。dst_image 和 src_image 分别是目标图像和源图像的标识符。如果源和目标的宽度和高度不同,则会进行相应的图像收缩和拉伸。坐标指的是左上角。本函数可用来在同一幅图内部拷贝(如果 dst_image 和 src_image 相同的话)区域,但如果区域交迭的话则结果不可预知。
imagecopyresized($new,$res,0,0,0,0,400,400,$img_info[0],$img_info[1]);

header("Content-type: image/png");
imagepng($new);// 以 PNG 格式将图像输出到浏览器
?>