레이블이 Server-Side인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Server-Side인 게시물을 표시합니다. 모든 게시물 표시

2010. 10. 13.

[PHP] how to install memcached on Windows XP

1. memcahced 를 Download 한다.


2. memcached 를  install 한다.

c:\memcached 에 압축을 풀고 command line(cmd)으로 간다.

c:\> cd c:\memcached
c:\> memcached.exe -d install
c:\> memcached.exe -d start
c:\> netstat -a
.
.
TCP     junp:11211     junp:0     LISTENING
.
.

3. php extension을 Download 한다. pecl-5.2.6-Win32.zip
압축풀면 php_memcache.dll 이 있으므로 extension_dir 에 복사를 하고
php.ini에 extension=php_memcache.dll 을 추가한다.


2010. 10. 12.

[PHP] 정규식으로 한글 영어 숫자 추출하기

$pattern = '/([\xEA-\xED][\x80-\xBF]{2}|[a-zA-Z0-9])+/';
$str = 'abc!@하나둘셋#123';
echo $str;
preg_match_all($pattern, $str, $match);
$str = implode('', $match[0]);
echo $str;
==================
abc!@하나둘셋#123
abc하나둘셋123

한글과 영어 숫자를 제외한 나머지문자는 무시하게 된다.




2010. 10. 11.

[MySQL] lower_case_table_names 세팅하기

유닉스계열은 0, 윈도우 계열은 1, Mac OS 의 경우는 2(이건 확실치 않음)가 기본 값이라고 한다.

유닉스 계열에서 값을 변경하고 싶다면 다음과 같이 하면 된다.

# /etc/init.d/mysqld stop
# mysqld_safe --lower_case_table_names = 1 &


확인하기

mysql> show variables like '%lower%';

2010. 10. 3.

[MySQL]skip-name-resolve

MySQL 서버는 외부로 부터 접속 요청을 받을 경우 인증을 위해 IP 주소를 호스트네임으로 바꾸는 과정을 수행하여 접속시에 불필요한 부하가 발생하게 됩니다. skip-name-resolve를 설정하시고 접속시에 IP 기반으로 접속을 하게 되면 hostname lookup 과정을 생략하게 되어 좀 더 빠르게 접속을 하실 수 있습니다.

# vi /etc/my.cnf

[mysqld]
skip-external-locking
skip-host-cache
skip-locking
skip-name-resolve

이렇게 추가를 해주고 mysqld를 restart를 하면 된다.

[MySQL]Too Many Connection Error

show variables like '%timeout%';
show variables like '%connect%';
show variables like '%thread%';

show status like '%thread%';
show status like '%connect%';

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

show status like 'Threads_created';
show status like 'Connections';
Cache Miss Rate(%) =  Threads_created / Connections * 100

show status like 'Aborted_connects';
show status like 'Connections';
Connection Miss Rate(%) = Aborted_connects / Connections * 100

show status like 'Threads_connected';
show variables like 'max_connections';
Connection Usage(%) = Threads_connected / max_connections * 100

show status like 'Max_used_connections';

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

Connection Usage가 100%면 max_connections 수를 증가시켜야 한다.
Connection Miss Rate 가 1%이상이면 wait_timeout을 더 길게 설정해야한다.
Cache Miss Rate가 높다면 thread_cache_size를 더 높게 잡아야 한다.

Max_used_connections 에서는 그 동안 사용되었던 최대 커넥션 수를 보여준다.

나의 경우는 Cache Miss Rate가 100%에 가깝게 나왔다.
그건 thread_cache_size가 0이기 때문에 매번 쓰레드를 생성해서이다.
일반적으로 Peak-time의 threads_connected보다 약간 낮은 수치로 설정하는 것이 좋습니다.

SET GLOBAL thread_cache_size = 40;

이렇게 값을 세팅해주었고, Cache Miss Rate 가 줄어들길 기다려야겠다.


2010. 9. 19.

mysql 접속자 수 늘리기

netstat으로 살펴보니 mysql 의 time_wait 가 너무 많아 보였다.

그래서 1차적으로 mysql의 동접자 수를 늘려주기로 했다.

우선 현재 동접자 수를 확인해보자.

# mysqladmin -u root -p패스워드 variables | grep max_connection


1-1. /etc/my.cnf 를 통해 늘려주기

[mysqld]
set-variable=max_connections=200   ---> 다음 한 줄을 추가한다.

1-2. mysqld_safe 로 늘려주기

# mysqld stop
# mysqld_safe -O max_connection=200 &

위의 두가지 방법중 1가지로 동접자 수를 늘려보자.

2010. 8. 29.

[MySQL] Slave_Sql_Running = No

Master-Slave Replication 환경에서 Master에만 있는 테이블을 변경한다던가, Slave에서 테이블을 DROP하는 작업을 하는 경우 Slave의 Replication이 중단된다.

 

이 경우 SHOW SLAVE STATUS\G 명령어를 수행하면

 

Slave_Sql_Running = No

 

라는 부분을 발견한다. 이런 경우 error를 유발한 쿼리를 skip 해줘야 한다.

 

mysql> SLAVE STOP;
mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
mysql> SLAVE START;


SQL_SLAVE_SKIP_COUNTER : Slave를 작동한 후 Master로부터 읽어온 쿼리 중 skip할 쿼리 수

 

 

[MySQL] Master-Slave Replication

가. Master 서버 설정

 

1. Slave 서버에서 접근할 수 있도록 권한을 준다.

 

mysql> GRANT REPLICATION SLAVE ON *.* TO 'ID'@'IP' IDENTIFIED BY 'PASSWORD';


ID : Master MySQL의 user id로 Slave의 MySQL에서 접근함

IP : Slave 서버의 IP

PASSWORD : Slave의 MySQL에서 쓰는 id의 password

 

2. Master 역할을 할 수 있는 권한 부여

 

# vi /etc/my.cnf

[mysqld]
server-id = 1
binlog-do-db = 'DB_NAME'
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
log-bin = mysql-bin


server-id : 동기화 구성에 참여한 각각의 MySQL들을 구분짓기 위한 UNIQUE ID로서 중복되면 안된다.

binlog-do-db : 실제 동기화 하려는 대상 DB의 이름. DB마다 한 라인씩 추가하면 된다.

binlog-ignore-db : 동기화 하지 않을 DB의 이름. DB마다 한 라인씩 추가하면 된다.

log-bin : 아마도 mysql의 log file 이름.

 

나. Slave 서버 설정

 

1. Slave 역할을 할 수 있는 권한 부여

 

# vi /etc/my.cnf

[mysqld]
server-id = 2
master-host = 'Master IP'
master-user = 'ID'
master-password = 'PASSWORD'
master-port = 3306
log-bin = mysql-bin

 

server-id : Master에서의 역할과 동일하게 UNIQUE ID

master-host : Master 서버의 IP

master-user : Master 서버의 MySQL에 생성했던 Replication 계정 ID

master-password : Replication 계정 ID의 비밀번호

master-port : Master 서버의 MySQL 원격 접속 포트번호 (기본: 3306)

log-bin : Master에서의 역할과 동일하게 아마도 log file 이름

 

다. 동기화 작동

 

1. Master 서버 재시작 후 MySQL에 접속

 

2. Master 서버 동작 확인

 

mysql> SHOW MASTER STATUS\G
********************** 1. row **********************
                   File : mysql-bin.000003
             Position : 98
     Binlog_Do_DB : test
Binlog_Ignore_DB : mysql, information_schema
1 row in set (0.00 sec)
mysql>

 

3. Slave 서버 재시작 후 MySQL에 접속

 

4. Slave 서버 동작 확인

 

 

mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G
********************** 1. row **********************
           Slave_IO_State : Waiting for master to send event (정상)
              Master_Host : IP
              Master_User : ID
               Master_Port : 3306
        Connection_Retry : 60
         Master_Log_File : mysql-bin.000003
Read_Master_Log_Pos : 98
.
.
       Slave_IO_Running : Yes (정상)
    Slave_SQL_Running : Yes (정상)
.
.
1 row in set (0.00 sec)
mysql>

 

Read_Master_Log_Pos : MASTER STATUS의 Position과 동일하다.

 

Slave_IO_State, Slave_IO_Running, Slave_SQL_Running 의 상태가 위와 같다면 정상

 

 

 

2010. 8. 17.

[PHP] MongoDB 사용하기

<?php
$mongoDB = new Mongo();
$newDB = $mongoDB->newDB;
$newCollection = $newDB->newCollection;

$doc = array('name' => 'owner', 'text' => 'this is test');
$newCollection->insert($doc);

$mongoDB->close();
?>

쉘에 들어가서 다음을 입력하면 확인가능하다.
>db.newCollection.find()

[MongoDB] 사용자추가 스키마생성 DB삭제

mongod 를 기동할 때는 --auth 옵션을 추가해야 함

mongoDB는 system영역 내에서 admin이라는 DB관리를 위한 스키마를 가짐

>use admin // admin DB 사용
>db.addUser('name','pswd') // 사용자 추가

>use newDB => 해당 디비가 없으면, 새로운 디비를 생성함
   mysql의 스키마 생성과 같음

>db.collectionName.drop() => 해당 collection을 삭제함
   mysql의 DROP TABLE과 같음

2010. 8. 16.

[MongoDB] APM에서 시작하기

1. mongoDB 설치하기

2. 압축풀기
   본인은 C:\MongoDB 에 풀었다.

3. data 폴더 생성하기 (DB data를 위해 생성함)
   본인은 C:\MongoDB\data 에 생성함

4. MongoDB 시작
   
C:\MongoDB\bin> mongod --dbpath C:\MongoDB\data


5. php에서 쓸 MongoDB 드라이버설치
   다른버전 찾기 -> 여기

6. 압축풀고 PHP의 extension 폴더에 dll 파일을 넣음
   C:\APM_Setup\Server\PHP5\ext 폴더가 extension 폴더임
   (본인은 APM_Setup에 APM을 설치함)

7. php.ini에서 해당 모듈을 적용함
   php.ini에 보면 extension정보가 쭉 나열되어 있는 곳이 있음
   거기에 밑의 한줄을 추가해줌
   이왕이면 알파벳 순서에 맞게 하는게 나중에 찾기 편할 듯
 
extension=php_mongo.dll

8. 아파치 재시작
   APMSETUP Monitor를 열어서 Apache를 재시작한다.

9. 확인하기
   echo phpinfo(); 를 이용해서 불러온 정보에 mongo 관련 설정이 있는지 확인한다.
   설치 끝!


[테스트하기] - 반드시 "4번.몽고DB실행"을 한 뒤에 작업해야함.

<?php
$m = new Mongo();
?>


MongoDB를 실행하지 않으면 다음과 같은 에러를 볼 수 있다.

Fatal error: Uncaught exception 'MongoConnectionException' with message ': Unknown error' in C:\APM_Setup\htdocs\mongoDB_tester\index.php:4 Stack trace: #0 C:\APM_Setup\htdocs\mongoDB_tester\index.php(4): Mongo->__construct() #1 {main} thrown in C:\APM_Setup\htdocs\mongoDB_tester\index.php on line 4
 

[참고 사이트]


2010. 8. 15.

[MySQL] index 추가, 삭제, 확인하기

1. 테이블의 인덱스 확인하기

SHOW INDEX FROM tablename;

2-1. 테이블의 인덱스 추가하기 : 컬럼은 1개도 가능, 2개 이상도 가능
ALTER TABLE tablename ADD INDEX indexname (column1, column2);

2-2. 테이블의 유니크 인덱스 추가하기 : 컬럼은 1개도 가능, 2개 이상도 가능
ALTER TABLE tablename ADD UNIQUE INDEX indexname (column1, column2);

3. 테이블의 인덱스 삭제하기
ALTER TABLE tablename DROP INDEX indexname;

2010. 7. 19.

FirePHP 사용법

require_once './library/FirePHP.class.php';
$firephp = FirePHP::getInstance(true);
$firephp->log($variable);

FirePHP 사용법.


post raw data

file_get_contents("php://input");

POST 방식으로 보낸 http 패킷의 body에 접근할 수 있다.

일반적으로 PHP에서는 form방식 전송을 이용하는 경우가 대부분이지만

body에 JSON으로 만든 raw data를 넣어서 보내는 경우에 서버단에서 접근하려면

위와 같은 명령어를 이용해야 한다.

2010. 7. 1.

PHP 이미지 crop

<iframe name="cropFrame" width="60" height="50" scrolling="no" style="display:none;"></iframe>
<form action="crop.php" method="post" target="cropFrame">
    <input id="imageSrc" type="hidden" name="imageSrc" value="" />
    <input id="x" type="hidden" name="x" value="0" />
    <input id="y" type="hidden" name="y" value="0" />
    <input id="w" type="hidden" name="w" value="450" />
    <input id="h" type="hidden" name="h" value="200" />
    <input type="submit" value="crop" />
</form>

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

<?php
    require_once './FirePHPCore/FirePHP.class.php';
    $firephp = FirePHP::getInstance(true);

    //$firephp->log($_POST['imageSrc']);
    
    $imageSrc = $_POST['imageSrc'];
    $x = $_POST['x'];
    $y = $_POST['y'];
    $w = $_POST['w'];  // 높이
    $h = $_POST['h'];   // 길이

    $target_w = 450;
    $target_h = 200;
    $jpeg_quality = 90;
    $src = substr($imageSrc, 2);
    $img_r = imagecreatefromjpeg($src);
    $dst_r = ImageCreateTrueColor($w, $h);

    imagecopyresampled(
        $dst_r,
        $img_r,
        0, 0, $x, $y,
        $target_w, $target_h, $w, $h
    );

    $output_filename = './pic/test.jpg';

    header('Content-type: image/jpeg');
    imagejpeg($dst_r, $output_filename, $jpeg_quality);
?>

imagecreatefromjpeg($src);
 - 해당 경로의 파일을 jpeg 이미지로 생성함

ImageCreateTrueColor($w, $h);
 - 파라미터로 받은 넓이와 높이의 크기만한 검정색 이미지를 생성함

imagecopyresampled(
    $dst_r, // 타겟 이미지
    $img_r,  // 복사할 이미지
    0,         // 타겟 이미지의 x좌표
    0,         // 타겟 이미지의 y좌표
    $x,       // 원본 이미지의 x좌표
    $y,       // 원본 이미지의 y좌표
    $target_w, // 타겟 이미지의 넓이
    $target_h,  // 타겟 이미지의 높이
    $w,      // 원본 이미지의 넓이
    $h        // 원본 이미지의 높이
);
 - 이미지의 크기를 변경해서 복사함
 - 이미지의 x, y 좌표는 좌상단 모서리에서 시작함

PHP 파일업로드

<iframe name="uploadFrame" width="60" height="50" scrolling="no" style="display:none;"></iframe>
<form action="upload.php" method="post" enctype="multipart/form-data" target="uploadFrame"/>
    <input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
    <label for="userfile">Upload a file:</label>
    <input type="file" name="userfile" id="userfile" />
    <input type="submit" value="Send File" />
</form>

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

<?php
file_exists($filepath);
 - 파일경로를 파라미터로 넘겨주고 존재 여부를 Boolean으로 받음

 move_uploaded_file($_FILES['userfile']['tmp_name'], $path);
 - 파일을 해당 경로에 업로드함
?>



2010. 4. 22.

[Code Igniter] layout 적용하기

http://codeigniter.com/wiki/layout_library/ 에서 Layout Library를 구하고 사용법을 확인할 수 있다.

1. /application/libraries/Layout.php 에 다음 소스를 저장한다.
<?php  
if (!defined('BASEPATH')) exit('No direct script access allowed');
 
class Layout
{
 
var $obj;
var $layout;
 
function Layout($layout = "layout_main")
{
$this->obj =& get_instance();
$this->layout = $layout;
}
 
function setLayout($layout)
{
$this->layout = $layout;
}
 
function view($view, $data=null, $return=false)
{
$loadedData = array();
$loadedData['content_for_layout'] = $this->obj->load->view($view,$data,true);
 
if($return)
{
$output = $this->obj->load->view($this->layout, $loadedData, true);
return $output;
}
else
{
$this->obj->load->view($this->layout, $loadedData, false);
}
}
}
?
2. /application/controllers/intro.php (임의로 만든 파일) 의 생성자에 다음 코드를 넣는다.
<?php

class
Intro extends Controller {

function __construct()
{
parent::Controller();

$this->load->library('layout', 'layouts/default');
$this->layout->setLayout('layouts/default');
}
function index()
{
$this->layout->view('layouts/default');
}
}

3. /application/views/layouts/default.php 에 다음 코드를 넣는다.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko" lang="ko" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>CI 레이아웃</title>
<style type="text/css">
.header {
width: 760px;
height: 50px;
border: 1px solid #CCCCCC;
}
.navigation {
float: left;
}
.navigation li {
float: left;
margin-right: 10px;
list-style: none;
cursor: pointer;
}
</style>
</head>
<body>
<div class="header">
<ul class="navigation">
<li id="home">Home</li>
<li id="send">Send</li>
</ul>
</div>
</body>
</html>

2010. 3. 25.

PHP 시간함수( strtotime, time(), date() )

echo strtotime("now"); -> 1269520600

echo strtotime("+1 hour"); -> 1269524200

echo time(); -> 1269520600

위의 결과는 모두 timestamp 형태이다.

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

echo date( 'Y-m-d H:i:s', time() );
-> 2010-03-25 21:36:40

위의 결과는 string 형태이다.

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

$timeString = date( 'Y-m-d H:i:s', time() );

echo $timeString; -> 2010-03-25 21:44:32

$time = strtotime($timeString);

echo $time; -> 1269520600

date()와 strtotime() 만 있으면 시간을 string과 timestamp로
자유롭게 바꿀 수 있다.

2010. 3. 11.

mysql password 변경

1. 프로세스 확인
     # ps -ef | grep mysqld
2. 실행중인 mysql 종료     
     # killall mysqld
3. grant-table 미사용모드로 mysql 시작 (mysql 데몬 실행)
     # cd /usr/local/mysql/bin
     # ./mysqld_safe  --skip-grant-tables &
4. mysql 접속
     # ./mysql -u  root  mysql
5. password 갱신
     # update user set password=password('123') where user = 'root';




2009. 12. 10.

MySQL에서 인덱스 체크하기 : EXPLAIN

MySQL에서 인덱스를 타는지 체크하는 방법은 EXPLAIN을 사용하는 것이다.

 

phpMyAdmin에 접속을 하고, SQL 탭으로 이동한다.

 

EXPLAIN SELECT * FROM `member` WHERE `id` = 1;

 

다음과 같이 쿼리문 앞에 EXPLAIN을 붙여주면 된다.

 

 

다음 그림은 쿼리문에서 Primary Key로 인덱스를 탄 경우이다.

(possible_keys, key를 눈여겨 봐야 한다.)

 

 

 

 

다음 그림은 쿼리문에서 Primary Key와 Foreign Key로 인덱스를 탄 경우이다.

(possible_keys, key를 눈여겨 봐야 한다.)