http://eseuta.mine.nu/#SMAF
And you need download the following soft too.
http://eseuta.mine.nu/ssc-ma3_dl.html
http://eseuta.mine.nu/#SMAF
And you need download the following soft too.
http://eseuta.mine.nu/ssc-ma3_dl.html
http://hostlibrary.com/installing_apache_mysql_php_on_linux
This tutorial is designed to guide you through the initial steps of setting up Apache, MySQL, and PHP on Linux. The Linux distribution being utilized for this tutorial is Fedora Core 1, however the steps should be very similar across most distributions. This tutorial makes the assumption that you have the required development tools loaded for compiling programs from source, these tools are beyond the scope of this document and will not be covered here. Also, it assumes you can use the vi text editor for basic editing tasks.
Apache, MySQL, and PHP have become one of the most utilized combinations for developing content driven websites. They are robust, flexible, provide a decent level of security, and they are available for many different platforms. That being said, lets get to building a web server.
Get the sourceballs -
The first thing you need to do is obtain the sourceballs for each package, we will be compiling each package from scratch here, and, while there are also binary packages available for some distributions, I find your end results are usually better when building each package for your machine. Make sure you get the source files.
Here are the links and the package versions available at the time this tutorial was written
Apache
URL : http://httpd.apache.org/download.cgi
Current Version – 2.0.48
MySQL
URL : http://www.mysql.com/downloads/mysql-4.0.html
Current Version – 4.0.16
PHP
URL : http://www.php.net/downloads.php
Current Version – 4.3.4
Ok, so you’ve got the files now what ?, well now the fun begins..
Installation –
The first thing we need to do is extract the sourceballs so we can work with the files included in them. Beginning now we will be working as root, so open a terminal window, change to the directory in which you saved your downloaded files and become root by issuing the su command, enter the root password and you should be good to go.
To extract the sourceballs type the following commands;
#tar -zxf httpd-2.0.48.tar.gz (enter)
#tar -zxf mysql-4.0.16.tar.gz (enter)
#tar -zxf php-4.3.4.tar.gz (enter)
The commands above will extract the sourceballs into their own separate directories. Now lets move on to compiling the source into usable programs. We’ll start with Apache.
Compiling Apache –
Change into the directory created when you untarred the sourceball as follows;
#cd httpd-2.0.48 (enter)
Follow this command by typing;
#./configure –prefix=/usr/local/apache2 –enable-mods-shared=most (enter)
This tells Apache to install in the /usr/local/apache2 directory, and to build most of the available loadable modules. There are a ton of options with Apache, but these should work for the most part. Once the configure is done and the system returns the prompt to you, issue the following command;
#make
This will take a few minutes, once the prompt comes back again issue the following command;
#make install
Wait for a few minutes and viola !, Apache is installed with the exception of a few minor changes we still need to make. They are as follows..
Issue the following command;
#vi /usr/local/apache2/conf/httpd.conf
Check to make sure the following line is present in the file at the bottom of the LoadModule list, if it is not there add it;
LoadModule php4_module modules/libphp4.so
Find the DirectoryIndex line and edit it so it looks like the following;
DirectoryIndex index.html index.html.var index.php
Find the AddType application section and add the following line;
AddType application/x-httpd-php .php
Thats it, save the file and we are done with Apache. Now, on to MySQL !
Compiling MySQL -
Change into the MySQL source directory as follows;
#cd mysql-4.0.16 (enter)
Follow this command by typing;
#./configure –prefix=/usr/local/mysql –localstatedir=/usr/local/mysql/data –disable-maintainer-mode –with-mysqld-user=mysql –enable-large-files-without-debug (enter)
Sit back and wait for a while while configure does its thing, once the system returns the prompt to you issue the following command;
#make (enter)
Unless you have a very fast machine this will take some time, so spend time with your family, grab a beer, go for a walk, or whatever you’re into. When you get back, assuming the system has returned the prompt to you issue the following command;
#make install (enter)
Cool !, MySQL is installed, there are only a couple things left to do to get it working, first we need to create a group for MySQL as follows;
#/usr/sbin/groupadd mysql (enter)
Then we create a user called mysql which belongs to the mysql group;
#/usr/sbin/useradd -g mysql mysql (enter)
Now we install the database files as follows;
#./scripts/mysql_install_db (enter)
Then we make a couple minor ownership changes;
# chown -R root:mysql /usr/local/mysql (enter)
# chown -R mysql:mysql /usr/local/mysql/data (enter)
Last but not least, we use vi to add a line the ld.so.conf file as follows;
#vi /etc/ld.so.conf
And we add the following line;
/usr/local/mysql/lib/mysql
Thats it, MySQL is installed, you can run it by issuing the following command;
#/usr/local/mysql/bin/mysqld_safe –user=mysql &
And as long as we’re here we might as well set a root password for MySQL as follows;
#/usr/local/mysql/bin/mysqladmin -u root password new_password
Where new_password is the password you want to use.
Ok, so far so good, on to PHP !
Compiling PHP -
Change into the PHP source directory as follows;
#cd php-4.3.4 (enter)
Follow this command by typing;
#./configure –prefix=/usr/local/php –with-apxs2=/usr/local/apache2/bin/apxs –with-mysql=/usr/local/mysql (enter)
Once the prompt comes back to you issue the following command;
#make (enter)
Hang out for awhile, and then yep, you guessed it, once you have the prompt back;
#make install (enter)
Once the install finishes and you have the prompt back issue the following command;
#cp php.ini-recommended /usr/local/php/lib/php.ini (enter)
Then edit that file;
#vi /usr/local/php/lib/php.ini (enter)
And change the following;
Find the doc_root section and enter the correct path for the directory which serves your web content, such as;
doc_root= “/usr/local/apache2/htdocs/”
(this is default for apache2)
Then find the file_uploads section and change it to reflect the following;
file_uploads=Off
(for security reasons)
Thats if for PHP, now lets see if it all works..
Testing –
Assuming your MySQL process is still running from earlier, lets start Apache by issuing the following command;
#/usr/local/apache2/bin/apachectl start (enter)
This starts the Apache web server, now change into the following directory;
#cd /usr/local/apache2/htdocs (enter)
And using vi create a file called test.php;
#vi test.php
Add the following line to the file;
<?php phpinfo(); ?>
Save the file, then fire up your browser and point it to localhost/test.php. You should see a listing of all kinds of cool info about Apache, PHP, etc. If you do then your set !, if you don’t, then take a look at your logs for Apache and MySql, and remember Google is your friend. But hopefully you do, and now you have a fully functioning setup.
Ok, one last step and we’ll be done, you have everything running now, but you had to start Apache and MySql manually, that’s something you don’t want to have to remember to do everytime you reboot your machine, so lets fix it.
Starting Apache and MySQL Automatically –
Lets start with MySQL, as root make your working directory that of the MySQL source directory you worked with earlier, something similar to;
#cd /home/xxxx/mysql-4.0.16 <enter>
Then, copy the file mysql.server to your /etc/init.d directory as follows;
#cp support-files/mysql.server /etc/init.d/mysql
Ok, lets create some links in the startup folders for run levels 3 and 5.
#cd /etc/rc3.d <enter>
#ln -s ../init.d/mysql S85mysql <enter>
#ln -s ../init.d/mysql K85mysql <enter>
#cd /etc/rc5.d <enter>
#ln -s ../init.d/mysql S85mysql <enter>
#ln -s ../init.d/mysql K85mysql <enter>
#cd ../init.d <enter>
#chmod 755 mysql <enter>
Thats it for MySQL, it should start automatically now when you reboot your machine. Now lets do the same for Apache, still as root make your working directory that of the Apache binaries as follows;
#cd /usr/local/apache2/bin <enter>
Then, copy the file called apachectl as follows;
#cp apachectl /etc/init.d/httpd <enter>
Now, for some more links;
#cd /etc/rc3.d <enter>
#ln -s ../init.d/httpd S85httpd <enter>
#ln -s ../init.d/httpd K85httpd <enter>
#cd /etc/rc5.d <enter>
#ln -s ../init.d/httpd S85httpd <enter>
#ln -s ../init.d/httpd K85httpd <enter>
And thats it for Apache !, it should start automatically along with MySQL the next time you boot your machine.
That brings us to the end of this tutorial, hopefully you found it helpful, and Good Luck !
Written By Rick Nicholas
http://hackingart.com/replication/555-tai_lieu_chinh_thuc_mysql_replication_tieng_viet.html
Replication
I. Cách cài dặt Replication
Để cài đặt một môi trường replication cần làm những việc sau:
- Tạo một user có quyền replication trên MySQL Server
- Cấu hình Master MySQL
- Cấu hình Slave MySQL
- Cập nhật cấu hình master trên slave, để slave có thể nhận và kết nối với Master
- Bắt đầu quá trình Replication
Cụ thể như sau:
1. Tạo user có quyền replication (trên master)
mysql> GRANT REPLICATION SLAVE ON *.*
-> TO ‘repl’@'%.mydomain.com’ IDENTIFIED BY ’slavepass’;
2. Cấu hình Master
Cấu hình trong file my.ini (hoặc my.cnf)
[mysqld]
log-bin=mysql-bin
server-id=1
- Khởi tạo binary logging trên Master, nếu không quá trình replication sẽ không có bản ghi nhị phân để thực hiện việc chuyển đổi dữ liệu giữa Master và Slaves
- Đặt Server-id cho các server trong nhóm replication. Server-id của mỗi server phải là duy nhất (không trùng nhau)
3. Cấu hình Slave
Cấu hình trong file my.ini (hoặc my.cnf)
[mysqld]
server-id=2
- Trên các Slave chỉ cần cấu hình Server-id, nếu có nhiều slave, nên đặt ID một các dễ phân biệt, có thể trùng với IP của server chẳng hạn
4. Lấy thông tin replication từ Master
Khi cấu hình replication trên Slave cần xác định được điểm hiện tại của master trong bản ghi nhị phân Master. Dựa vào thông tin này, khi slave bắt đầu quá trình replication, nó có thể bắt đầu quá trình sử lí sự kiện tại thời điểm đúng dựa vào bản ghi nhị phân.
Để lấy thông tin tình trạng Master, cần làm:
mysql> FLUSH TABLES WITH READ LOCK;
Flush tất cả các bảng và ngăn cản những lênh write lên database
mysql > SHOW MASTER STATUS;
+—————+———-+————–+——————+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+—————+———-+————–+——————+
| mysql-bin.003 | 73 | test | manual,mysql |
+—————+———-+————–+——————+
Hiển thị tên của log file (mysql-bin.003) và offset (73).
Nếu Master đang chạy mà không khởi tạo bản ghi nhị phân trước đó thì khi show master status, sẽ hiển thị trống, khi đó cấu hình trên slave thì slave’s log và position sẽ là ký tự trắng‘ ’ và 4.
5. Tạo một Data Snapshot sử dụng mysqldump
- Cần lock table trước, hoặc flush tất cả talbe và block tất cả những lênh ghi lên table:
mysql> FLUSH TABLES WITH READ LOCK;
- Tạo một dump cho tất cả những database cần replication hoặc một database riêng lẻ nào đó:
shell> mysqldump –all-databases –lock-all-tables >dbdump.db
- Có thể dùng tùy chọn – master-data, nó sẽ tự động mở rộng câu lênh CHANGE MASTER được yêu cầu trên Slave để có thể bắt đầu replicate
shell> mysqldump –all-databases –master-data >dbdump.db
- Sau đó cần copy file dump tới Slave hoặc sử dụng file từ trên Master khi kết nối từ xa tới Slave để import data.
6. Tạo Data Snapshot sử dụng file dữ liệu thô (Raw data file)
- Với những database lớn thì đôi khi việc copy dữ liệu thô lại có hiệu quả hơn là sử dụng mysqldump và import file tới từng slave
- Nhưng với những kiểu storage engine có caching hoặc thuật toán phức tạp thì thời gian snapshot và thời gian update thông tin cache và log đôi khi không được cùng lúc, kể cả khi đã read lock. Điều này phụ thuộc vào khả năng phục hồi của storage engine.
- Nếu sử dụng innoDB tables, thì nên sử dụng công cụ InnoDB Hot Backupđể snapshot. Công cụ này ghi lại log name và offset tương ứng để sau sử dụng trên slave. (tool này không free)
- Nếu sử dụng MyISAM table, có thể dùng những tool copy chuẩn như cp hoặc copy, công cụ copy từ xa như là scp hoặc rsync, một công cụ lưu trữ như zip hoặc tar. Hoặc công cụ snapshot file hệ thống như dump
- Để snapshot có hiệu quả, nên shutdown MySQL server trong quá trình xử lí:
o Readlock trước, và lấy master’s status
o Shut down MySQL server:
shell> mysqladmin shutdown
o Copy lại file dữ liệu, có thể dùng một trong những cách sau:
shell> tar cf /tmp/db.tar ./data
shell> zip -r /tmp/db.zip ./data
shell> rsync –recursive ./data /tmp/dbdata
o Khởi động MySQL server
- Nếu sử dụng InnoDB, thi có thể snapshot mà không cần phải shutdown MySQL server
7. Cài đặt Replication trên vơi master và Slaves hoàn toàn mới
- Với Master và những slaves hoàn toàn mới (chưa có dữ liệu) thì sẽ sử dụng cách này. Cũng có thể sử dụng cách để cài đặt trong trường hợp có master mới và có dump dữ liệu mà muốn load lên để replication. Bằng cách load dữ liệu lên trên master mới, rồi sau đó cho replicate với slaves.
- Các bước cài đặt:
o Cấu hình MySQL Master (như phần 2)
o Khởi động MySQL Master
o Khời tạo User có quyền replicate
o Lấy thông tin Master status
o Hủy read lock
mysql> UNLOCK TABLES;
o cấu hình MySQL trên Slave (như phần 3)
o khởi động MySQL Slave
o Chạy lênh CHANGE MASTER để cấu nhận cấu hình Master từ slave
- Nếu cài đặt một môi trường replication sử dụng dữ liệu từ một database server có sẵn thì cần chạy file dump trên Master trước, dữ liệu sẽ tự động được nhân bản xuống các slave
8. Cài đặt Replication với một dữ liệu đã có
- Trước khi replication dữ liệu, cần chọn được cách lấy dữ liệu tốt nhất từ master chuyển tới Slave
- Các bước cài đặt:
o Cấu hình MySQL Master (phần 2)
o Tùy vào trạng thái hiện thời của Master mà dùng Mysqldump đẻ take a snapshot, hoặc snapshot dữ liệu thô (phần 6,7) . Trước đó nên lấy thông tin Master trước. (phần 4)
o Tạo User có quyền replicate
o Cấu hình Slave (phần 3)
o Bước tiếp theo sẽ phụ thuộc vào cách take a snapshot
§ Nếu sử dung mysqldum:
· Khời động Slave, nhưng bỏ qua replication sử dụng tùy chọn –-skip-slave
· Import file dump: shell> mysql < fulldb.dump
§ Nếu snapshot sử dụng dữ liệu thô
· Bung file dữ liệu ra data directory trên slave. Vd: shell> tar xvf dbdump.tar
Ở đây cần quyền ownership trên file này phù hợp với cấu hình trên slave
· Khởi động slave nhưng bỏ qua replication bằng tùy chọn –skip-slave
o Câp nhật thông tin Master trên slave (CHANGE MASTER TO…)
o Bắt đầu slave : mysql> START SLAVE;
9. Thêm Slave vào một môi trường replication đã có
Khi thêm một slave vào, không cần thiết phải stop master mà chỉ cần sao chép cấu hình từ slave cũ sang slave mới.
- Các bước:
o Shutdown slave đang chạy: shell> mysqladmin shutdown
o Copy thư mục dữ liệu từ slave đang chạy sang slave mới. có thể làm việc này bằng cách tạo ra một archive sử dụng tar hoặc win-zip, hoặc dùng ngay cp, rsync. Cần copy cả những file log và file logs và file relay logs,
o Chú ý một lỗi rất hay xảy ra là:
071118 16:44:10 [Warning] Neither –relay-log nor –relay-log-index were used; so
replication may break when this MySQL server acts as a slave and has his hostname
changed!! Please use ‘–relay-log=new_slave_hostname-relay-bin’ to avoid this problem.
071118 16:44:10 [ERROR] FAILED TO OPEN THE RELAY LOG ‘./OLD_SLAVE_HOSTNAME-RELAY-BIN.003525′
(RELAY_LOG_POS 22940879)
071118 16:44:10 [ERROR] COULD NOT FIND TARGET LOG DURING RELAY LOG INITIALIZATION
071118 16:44:10 [ERROR] FAILED TO INITIALIZE THE MASTER INFO STRUCTURE
Lỗi này xảy ra là do –relay-log ở slave mới. Cách giải quyết tôt nhất là copy lại nội dung của relay log trên slave cũ sang slave mới. chú ý trong lúc copy cần stop cả 2 slave này.
o Copy master.info vàrelay.info files từ Slave cũ sang Slave mới. Những file này chứa vị trí của log
o Khởi động slave
o Cấu hình MySQL slave trên slave mới (phần 3) với một id mới
o Start slave, file master.info được sử dụng để bắt đầu quá trình xử lí replication.
10. Cài đặt cấu hình Master trên Slave:
Mysql> Stop slave;
CHANGE MASTER TO
MASTER_HOST=’master.mydomain.com’,
MASTER_USER=’repl’,
MASTER_PASSWORD=’slavepass’,
MASTER_LOG_FILE=’recorded_log_file_name’, #lay gia tri trong cau hinh da ghi lai
MASTER_LOG_POS=recorded_log_position; #lay gia tri trong cau hinh da ghi lai
#truoc khi replication thi log=”"; post=4;
11. Thực hiện Replicate:
- Tại Master: Unlock table
Mysql> Unlock tables;
- Tại Slave
Mysql> Start slave;
II. Những giải pháp Replication
1. Replication dùng để backup dữ liệu
Chủ yếu dùng Mysqldump (đối với dữ liệu nhỏ), hoặc copy dữ liêu thô (đối với dữ liệu lớn)
2. Replication giữa Master và slaves dùng những kiểu storage engine khác nhau
Quá trinh replication không để ý đến việc các storage engine dùng cho các table ở Master và Slave khác nhau hay không, vì các biến hệ thống storage_enginevà table_typekhông được replicated. Điều này cũng thuận lợi cho nhu cầu sử dụng database tai mội Server, ta có thể để Master là InnoDB để nó có thể tận dụng chức năng transaction, còn slave thì để MyISAM để nó chỉ hỗ trợ read, còn transaction thì không cần thiết, mà vẫn replication được
Ta cũng có thể convert kiêu storage engine ở các table sang loại khác, sử dụng:
ALTER TABLE … Engine=’enginetype
3. Replication tăng tốc truy cập sử dụng database từ client vào hệ thống database
Khi đã được replicate, việc truy vấn tới database sẽ có thể được chia sẻ theo chức năng và mục đích. VD: những truy vấn Read sẽ được gửi tới Slave, còn write được gửi tới Master. sẽ được gửi tới Slave, còn write được gửi tới Master.
4. Replication các Databases khác nhau đến các Slaves khác nhau
Khi có một Master và nhiều slaves. Sẽ có nhu cầu replicate các database khác nhau trên Master tới các slave khác nhau, mỗi database (hoặc table) sẽ được replication với một slave. VD:
Có một vài cách sau để thực hiện:
§ Đồng bộ tất cả dữ liệu tới Slave, sau đó database nào không cần thi xóa đi, giữ lại những Database cần thiết (cách này cùn quá ^ ^)
§ Sử dụng Mysqldump để tạo ra những file dump (hoặc copy dữ liệu thô) chỉ chứa database hoặc table cần thiết cho mỗi slave tương ứng.
§ Cấu hình giới hạn những câu lệnh trong Binary log, mà mỗi slave sẽ xử lí khi replicate chỉ là những database hoặc table cần thiết bằng lệnh: replicate-wild-do-table trên mỗi Slave:
· MySQL Slave 1cần replicate những bảng sale, finance trong databaseA cần cấu hình:
replicate-wild-do-table=sales.%
replicate-wild-do-table=finance.%
· MySQL Slave 2 cần replicate những bảng support trong databaseB, cần được cấu hình:
replicate-wild-do-table=support.%
· MySQL Slave 3 cần replicate những bảng service trong databaseC, cần được cấu hình:
replicate-wild-do-table=service.%
§ Trong trường hợp cần loại bỏ một số database, table khỏi quá trình replication:
replicate-ignore-table=table1
replicate-ignore-db=database2.%
5. Cải thiện quy trình replication
Khi một số lượng lớn slaves kết nối với 1 Master, kể cả lưu lượng không lớn nhưng khi tạo kết nối từ từng slave đến server và nhận bản full copy file master binary log, tải mạng ở Master sẽ tăng rất cao và có thể gây ra hiện tượng thắt cổ chai, công với việc khi Master phải đáp ứng nhiều request cùng lúc nữa thì sẽ không ổn.
Có cách để cải thiện vấn đề này là tạo một cấu trúc replication sâu hơn: Master sẽ replicate với một Slave, còn những slave khác sẽ kết nối đến Primary Slave kia để replicate theo yêu cầu:
Để có được như vậy cần cấu hình:
§ Master 1 sẽ là nơi thay đổi, cập nhật và viết lên database. Binary log được khởi tạo
§ Master 2 là Slave của Master 1, và nó là server duy nhất kết nối đến Master 1. ở đây có khởi tạo binary log, và tùy chọn -log-slave-updates để cấu trúc replication từ Master 1 được ghi vào binary log ở Master 2 giúp nó có thể trở thành Master và replicate được với những slaves còn lại.
§ Slave1, 2 3 sẽ cấu hình nhận Master 2 làm master
6. Chuyển đổi Master trong trường hợp lỗi xảy ra
Trong trường hợp Master bị lỗi, cách khắc phục tốt nhất là dựng một slave lên làm master thay thế, vừa có chức năng đáp ứng các requests vừa replication với các slaves còn lại. Việc này chỉ có hiệu quả khi viết một Script đảm bảo được:
§ Theo dõi tình trạng hoạt động của Master
§ Nếu Master fail, một Slave sẽ được chuyển thành Master thay thế
§ Chuyển đổi các ứng dụng và slave với Master mới
VD: một cấu trúc replication:
Khi Master fail, vấn đề đặt ra là chuyển Slave1 thành Master, cấu hình lại cấu trúc replicate với master mới:
§ Khởi tạo sẵn –log-binvà -log-slave-updatestrên Slave1
§ Khi Master Unavailable Chắc chắn tất cả các slaves đã xử lí xong những câu lênh trong relay log, trên từng slave, STOP SLAVE IO_THREAD, sau đó kiểm tra SHOW PROCESSLISTcho đến khi thấyHas read all relay log.Lúc này các slaves mới sẵn sàng cho cấu hình mới
§ Thăng chức Slave1 lên Master: STOP SLAVEvàRESETMASTER.
§ Trên các slaves: STOP SLAVE vàCHANGE MASTER TO MASTER_HOST=’Slave1′.
Không cần thiết phải viết binlog và vị trí, vì nó là lần đầu ghi lên binlog nên nó mang gia trị mặc định (binlog = ‘ ’ và position = 4)
§ Trên slave2 và slave3: START SLAVE
Sau khi cấu hình cấu trúc replication sẽ bị thay đổi như sau:
Trong trường hợp khắc phục xong Master ban đầu và muốn thay thế lại giống cấu trúc đầu thì ta lại tạo quá trình xử lí tình huống, Slave1 bị fail và dựng master cũ lên làm Master mới thay thế. Cần nhớ RESET MASTER để các slaves nhận master mới.
7. Cài đặt replication sử dụng SSL
Khi sử dụng SSL trong replication, chính là việc dùng một Security certificate để chứng thực giữa Master và Slave. Đồng thời các Bin log sẽ được mã hóa trong quá trình đồng bộ.
Cần cấu hình:
§ Master cần hỗ trợ kết nối mạng SSL
§ Trên Master, khởi tạo Certificate và thêm cấu hình này vào file cấu hình của Master bên trong mysqld:
ssl-ca=cacert.pem
ssl-cert=server-cert.pem
ssl-key=server-key.pem
§ Trên Slave có thể dùng một trong 2 cách:
· Cũng tạo certificate đó trong file cấu hình của Slave:
ssl-ca=cacert.pem
ssl-cert=server-cert.pem
ssl-key=server-key.pem
· Cấu hình certificate trong lệnh CHANGE MASTER:
CHANGE MASTER TO \
MASTER_HOST=’master_hostname’, \
MASTER_USER=’replicate’, \
MASTER_PASSWORD=’password’, \
MASTER_SSL=1, \
MASTER_SSL_CA = ‘ca_file_name’, \
MASTER_SSL_CAPATH = ‘ca_directory_name’, \
MASTER_SSL_CERT = ‘cert_file_name’, \
MASTER_SSL_KEY = ‘key_file_name’;
§ Khởi động quá trình replication:
mysql> START SLAVE;
III. Replication FAQ
1. Slave có cần thiết phải kết nối với Master liên tục không?
Không cần thiết. Slave có thể tự kết nối và cập nhật với Master sau khi kết nối lại. Chỉ cần không xóa binlog khỏi Master, vì nếu không có, Slave sẽ không có thông tin để cập nhật
2. Làm thế nào để biết được Slave trễ so với master là bao lâu (lênh cuối cuối được replicatie với slave là lúc nào?)
Dùng lệnh SHOW SLAVE STATUSquan sát cột Seconds_Behind_Master (thời gian được tính bằng giây)
3. Làm thế nào để áp master block lại những update cho đến khi slaves theo kịp
Trên master:
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;
Ghi lại thời điểm replicate (bao gồm tên file và offset)từ kết quả của lênh Show
Trên Slave:
mysql> SELECT MASTER_POS_WAIT(‘log_name’, log_offset);
Thời điểm bắt đầu được replicate sẽ được slave xác định, và chuẩn bị cho replicate (dựa vào kết quả ở bước làm trên master)
Trên master:
mysql> UNLOCK TABLES;
Cho phép Master bắt đâu lại quá trình update
4. Những điều cần lưu ý khi cấu hình replication theo 2 hướng
Không nên cấu hình một Slave nhận replication từ 2 Masters.Những bản update từ 2 Master khác nhau chưa chắc đã giống nhau, điều này có thể làm cho dữ liệu và bản update không được an toàn
5. Làm sao để sử dụng Replication tăng hiệu quả hoạt động của hệ thống
Nên sử cài đặt một Master, và cho các lênh write trỏ vào nó. Lệnh Read sẽ được phân chia giữa Master và Slaves.
Hoặc chúng ta cũng có thể Start Slaves với –skip-innodb,–low-priority-updates, và –delay-key-write=ALLđể tăng tốc trên Slave cuối, vì nó không sử dụng Transaction bởi innoDB nữa mà sẽ là non-transaction MyISAM.
6. Replication có thể tăng tốc được bao nhiêu và khi nào cho hiệu năng hệ thống?
Để có thể quyết định được cần sử dụng được bao nhiêu slaves cần dùng trong replication, ta cần biết được nhu cầu Reads, Write lên database, sau đó benchmark mối quan hệ giữa Read and write trên một master và một slaves,
(Có ví dụ như sau:
Let’s say that system load consists of 10% writes and 90% reads, and we have determined by benchmarking that reads is 1200 – 2× writes. In other words, the system can do 1,200 reads per second with no writes, the average write is twice as slow as the averageread, and the relationship is linear. Let us suppose that the master and each slave have the same capacity, and that we have one
master and N slaves. Then we have for each server (master or slave):
reads = 1200 – 2 × writes
reads = 9 × writes / (N + 1) (reads are split, but writes go to all servers)
9 × writes / (N + 1) + 2 × writes = 1200
writes = 1200 / (2 + 9/(N+1))
The last equation indicates the maximum number of writes for N slaves, given a maximum possible read rate of 1,200 per minuteand a ratio of nine reads per write.
This analysis yields the following conclusions:
• If N = 0 (which means we have no replication), our system can handle about 1200/11 = 109 writes per second.
• If N = 1, we get up to 184 writes per second.
• If N = 8, we get up to 400 writes per second.
• If N = 17, we get up to 480 writes per second.
• Eventually, as N approaches infinity (and our budget negative infinity), we can get very close to 600 writes per second, increasing
system throughput about 5.5 times. However, with only eight servers, we increase it nearly four times.)
7. Replication có thể hoạt động trên Mix mode
có thể bao gồm nhiều loại hệ điều hành, và nhièu kết cấu phần cứng khác nhau
8. Chu trình viết script cho quá trình Master Failover
( Master
o Show master status: => nếu pos = 0 => fail; (binlog không có hoặc bị lỗi)
o Show master status: => nếu pos # 0 => không fail; )
- Slaves:
Dùng lệnh show slave status với tất cả các slave:
Show slave status: => Slave_IO_State = reconnecting after a failed master event read
§ Kết quả như trên chỉ ở một số máy => gửi report đến admin => check slaves này
§ Kết quả như trên ở tất cả slaves => Master fail
- Master Fail:
o Dựng slave 1 lên làm Master:
§ Khởi tạo sẵn –log-binvà -log-slave-updatestrên Slave1
§ Thăng chức Slave1 lên Master: STOP SLAVEvàRESETMASTER.
o Chuyển kết nối sang Master mới với các Slaves
§ Khi Master Unavailable Chắc chắn tất cả các slaves đã xử lí xong những câu lênh trong relay log, trên từng slave, STOP SLAVE IO_THREAD, sau đó kiểm tra SHOW PROCESSLISTcho đến khi thấyHas read all relay log.Lúc này các slaves mới sẵn sàng cho cấu hình mới
§ Trên các slaves: STOP SLAVE vàCHANGE MASTER TO MASTER_HOST=’Slave1′.
Không cần thiết phải viết binlog và vị trí, vì nó là lần đầu ghi lên binlog nên nó mang gia trị mặc định (binlog = ‘ ’ và position = 4)
§ Trên Slaves: START SLAVE
Các link liên quan:
Setup MySQL Replication – How to?
http://livechung.wordpress.com/2007/11/16/mysqlrepli/
Mình đi theo step by step cho nó dễ làm một chút.
Một cách ngắn gọn: MySQL replication cho phép bạn có một bản copy của database chính (master) trên một server phụ (slave) và tất cả mọi update của master server thì lập tức được sao chép sang slave server. Vì thế sẽ có sự đồng bộ giữa master và slave server. Dĩ nhiên cần phân biệt rằng MySQL replication không phải là backup vì một câu lệnh delete của MySQL cũng thực hiện trên slave.
MySQL replication làm cho hệ thống high availability.
Ta có tesdb tại server master có ip=192.168.1.2 và muốn tạo bản sao của nó
1. Phần master
Trước hết comment dòng sau , trong file /etc/mysql/my.cnf
#skip-networking
#bind-address = 127.0.0.1
Và thêm vài dòng sau vào /etc/mysql/my.cnf
log-bin = /var/log/mysql/mysql-bin.log
binlog-do-db=testdb
server-id=1
File log này để xem những thay đổi của master trên slave. Khởi động lại rồi vào root
mysql -u root -p
Enter password:GRANT REPLICATION SLAVE ON *.* TO ’slave_user’@’%’ IDENTIFIED BY ‘<some_password>’;
FLUSH PRIVILEGES;
USE testdb;
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;
Dòng lệnh cuối cùng sẽ cho ra một cái bảng có một record. Bạn ghi lại cái record ra giấy nháp để cần thiết cho sau này.
Đến bây giờ sẽ có hai cách để master update ra slave. Trường hợp thứ nhất là dùng database dump, thứ hai là dùng lệnh LOAD DATA FROM MASTER; trên slave
mysqldump -u root -p<password> –opt testdb > testdb.sql
Chuyển file này đến slave server .
Sau cùng là unlock testdb
mysql -u root -p
Enter password:
UNLOCK TABLES;
quit;
Phần cấu hình trên master đã xong.
2. Cấu hình slave
Trước hết tạo database testdb (slave)
mysql -u root -p
Enter password:
CREATE DATABASE testdb;
quit;
Nếu bạn dùng cách thứ nhất để update thì chạy dòng lệnh sau:
mysql -u root -p<password> exampledb < /path/to/testdb.sql
Bây giờ cần nói cho mySQL của slave bít rằng nó là slave và nó cần bít cái master database của nó nữa. Thêm các dòng sau vào /etc/mysql/my.cnf
server-id=2
master-host=192.168.1.2
master-user=slave_user
master-password=secret
master-connect-retry=60
replicate-do-db= testdb
Với cách thứ hai thì bạn sử dụng dòng sau để update:
mysql -u root -p
Enter password:
LOAD DATA FROM MASTER;
quit;
Sau cùng :
mysql -u root -p
Enter password:
SLAVE STOP;
CHANGE MASTER TO MASTER_HOST=’192.168.1.2′, MASTER_USER=’slave_user’, MASTER_PASSWORD=”, MASTER_LOG_FILE=’xem note’, MASTER_LOG_POS= int;START SLAVE;
quit;
master_host: là địa chỉ ip của server master
master_user: là user đã grant replication trên master server
master_log_file: trong bảng đã show master status
master_log_pos: trong bảng show master status phần cấu hình master
Ok xong rồi! Khi nào testdb được update trên master nó sẽ được lặp lại trên slave
http://trac.symfony-project.org/wiki/AjaxAndJSON
I’d like to show an other way to play with AJAX using symfony. Right now if you look at the askeet or ajax tutorial you basically write ajax with remote_function using the update option which let you update a whole div or HTML tag with the result from a view. This is very nice, but what if you want to update more than one HTML element ? Isn’t it the worst to refresh a whole div tag with heavy HTML code for only one integer value ? What we figured out, when it comes to creating more interactive web 2.0 application(like chat apps), is that it’s more than refreshing a div tag with HTML code that you might want to do… This wiki page will try to show you how to use prototype.js ajax/JSON features to prove symfony is indeed a good choice for a web 2.0 framework.
So what do we want ? This is a basic example taken from http://openrico.org/ javascript updater demo. Suppose you have a basic HTML body like this:
<div id="content"> <span id="title">basic letter</span> <p Hello Mr, <span id=name>name_here</span> we are proud to announce that symfony has been approuved for web <span id='version'>version_here</span> application coding.</p> <p id='thanks'>thanks_here</p> </div>
The question is how to populate some database information in this HTML code ? We would make a simple ajax call that can populate title, name etc.. at one time.
Let’s create a module:
symfony module publishing
Now create an action that will simply return the content we wrote just before. Edit indexSucess.php and type:
<div id="content">
<span id="title">basic letter</span>
<p Hello Mr, <span id=name>name_here</span> we are proud to announce that symfony has been approuved for web <span id='version'>version_here</span> application coding.</p>
<p id='thanks'>thanks_here</p>
</div>
<?php echo link_to_remote("refresh", array("url" => "/publishing/refresh", 'complete'=>'updateJSON(request,json)') ); ?>
Notice the last line: we have added a refresh link that call an ajax function to refresh the page. Now if you simply call the action with the url “http://localhost/publishing” you just get the HTML code and the refresh button that does nothing. Let’s ignore the “, json” part of the code. I’ll explain it later.
So now let’s create the refresh action. Just add this to your “actions.class.php” :
/**
* Executes refresh action
*
*/
public function executeRefresh()
{
$this->output = '[["title","My basic letter"],["name","Mr Brown"], ["version","2.0"], ["thanks","gracefully"]]';
}
I know this is a little cryptic. But this notation is called JSON.http://www.json.org and it is the abbrevation for Javascript Simple Object Notation in which { is used for defining an object and [ for defining an array. There are many ways to encode and decode an object or an array from PHP to JSON or from JSON to PHP. There's even a C php extension that does lightspeed encoding but it's not in the scope of this wiki page. For now we're going to produce it "by hand" even if I recommend you to use PHP-JSON extension if you are considering doing JSON Ajax with symfony on a production environment. So what we wrote here is a simple array of key/value pairs that we'd like javascript to populate in our page.
Create a template for this action: (refreshSuccess.php)
<?php echo $output ?>
You also need to tell symfony not to use any layout in the view.yml file of your application. So our action won't use any layout and only JSON text will be received:
all: has_layout:off
So now we need a bit of javascript code ( yes we need it
!) but prototype.js is here to help us !
Create a file named "updaterJSON.js" in your web/js directory with this content:
function updateJSON(request, json){
var responses = json;
if (!json){
//if you don't use the json tips then evaluate the renderedText instead
var responses = eval('(' + request.responseText + ')');
}
var resSize = responses.length;
for (var i = 0; i < resSize; i++)
{
Element.update(responses[i][0], responses[i][1]);
}
}
So a bit of explanation, remember what we wrote in our template :
link_to_remote("refresh", array("url" => "/publishing/refresh", 'complete'=>'updateJSON(request,json)') );
This line says create a refresh link(<a> tag) which will call the url /publishing/refresh through an XmlHttpRequest?(ajax). On complete event the javascript function updateJSON(request,json) will be called. The request will contain the xmlhttprequest itself. Now the updateJSON javascript call 'request.responseText' to retrieve the text from the symfony view template(the JSON text we output from the refreshSuccess.php). For javascript to understand the JSON and decode it to an object/array just call eval('(' + originalRequest.responseText + ')') . This will return an array of array with key/value pairs. The script updateJSON is a very quick one. This wiki is not about learning javascript so we used only a simple array definition to be able to iterate over key/value pairs. But you must know that JSON is more close to object than array and that you can imagine generating a binding to an object instead, and even create a real Class with prototype.js and instantiate them through JSON with a bit of javascript code... But let's stay focused to our tutorial for now... What the javascript does is basically, iterating over key/value pairs, fetching the Element key from the page and setting its value to value...
For our javascript to work we need to include it and also take care that prototype.js is included before it as we use it in updaterJSON.js. To accomplish this you'll need to modify the view.yml in your module's config directory:
all: has_layout:off javascripts: [/sf/js/prototype/prototype, updaterJSON]
That's it. Now just browse to "http://localhost/publishing", press the refresh link and watch the magic
...
Element.update from updaterJSON doesn't work with IE
Why ?
"with IE you can't have two id with the same name for modification with Element.update"
But wait what about the json parameter we've ignored till now ? In fact, prototype.js has a very handy feature for JSON. When using an AJAX function, it always looks for the header "X-JSON" and will evaluate it automatically and pass it as a second argument to your javascript callback function. Note that for now there exists a bug in symfony preventing this feature from working. I made a patch #252 and #272 for this issue. As soon as it's fixed you'll be able to replay the tutorial but this time change those:
/**
* Executes refresh action
*
*/
public function executeRefresh()
{
$output = '[["title","My basic letter"],["name","Mr Brown"], ["version","2.0"], ["thanks","gracefully"]]';
$this->getResponse()->setHttpHeader("X-JSON", '('.$output.')');
return sfView::HEADER_ONLY;
}
You should notice two things here. Symfony will camel-case the X-JSON to X-Json but it doesn't seem to bother prototype.js for now, also we'll need to enclose the $output with braces so prototype 1.4 can acknowledge it's the json server work ... Doing these will do the trick. So, what are the advantages? Debugging! When outputted with an header, the logs would show you the result header is X-JSON and then when in development environment you can simply follow your request and see where the bug might be. Developing AJAX is an asynchronous nightmare and a javascript call with symfony is a bit hard to follow so seeing the header is a must.
Its not clear yet which other AJAX frameworks support the X-JSON header. So it seems that with YUI its more reliable to simply use application/json as the content type, which aside from being a cleaner way to return json data also addresses some security issues. Here is an example helper class that from which all JSON enabled modules should extend. As you can see the code is also able to return the data as HTML in case this method is used on a request that is made directly (not via XMLHTTPRequest) using the debug frontend. This requires the existence of a global _json.php template. This way you can also use the debug panel when debugging JSON requests.
sfJSONActions.class.php
class sfJSONActions extends sfActions
{
/**
* Return in JSON when requested via AJAX or as plain text when requested directly in debug mode
*
*/
public function returnJSON($data)
{
$json = json_encode($data);
if (SF_DEBUG && !$this->getRequest()->isXmlHttpRequest()) {
sfLoader::loadHelpers('Partial');
$json = get_partial('global/json', array('data' => $data));
} else {
$this->getResponse()->setHttpHeader('Content-type', 'application/json');
}
return $this->renderText($json);
}
}
_json.php global template
<!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="en" lang="en">
<head>
<title>JSON response</title>
<link rel="shortcut icon" href="/favicon.ico" />
<script language="JavaScript" type="text/javascript" src="<?php echo javascript_path('/sf/sf_web_debug/js/main.js') ?>" />
<link rel="stylesheet" type="text/css" media="all" href="<?php echo stylesheet_path('/sf/sf_web_debug/css/main.css') ?>" />
</head>
<body>
json:<br>
<?php echo json_encode($sf_data->getRaw('data')); ?>
<br>
data structure:<br>
<pre>
<?php print_r($sf_data->getRaw('data')); ?>
</pre>
With the participation of Noel, thanks for reading, hope my english isn't too bad and that this might be the start for other wiki about AJAX/object binding with symfony as server. Feel free to ask on irc : benoitm on #symfony
http://www.mellowmorning.com/2007/08/18/ten-reasons-why-symfony-rocks-part-1/
In the short attention span of most fellow PHP developer’s, here the first 5 great reasons to use Symfony. (Update: part 2 is here.) This is by no means a full explanation of Symfony, but just enough to get you running over to the documentation to learn more.
Few general highlights first:
With all the hype surrounding web II.0, any major PHP framework has to add some Javascript and Ajax support. Symfony gives you a few nice building blocks. Small example:
<?php echo form_remote_tag(array(
'url' => 'project/addReply',
'update' => 'replys',
'complete' => visual_effect('highlight', 'replys').
"Element.hide('addReply')",
'position' => 'bottom',
), 'id=addReply style=display:none;') ?>
<?php echo input_hidden_tag('id', $project->getId()) ?>
<?php echo textarea_tag('body') ?><br />
<?php echo submit_tag('submit') ?>
</form>
<?php echo link_to_function('Add a reply', visual_effect('toggle_appear', 'addReply')) ?>
This little snippit gives you an AJAX form, which submits its data to project/addReply (module/action). With a nice visual effect for appearance. Extremely fast to implement and extend. Have a look at my ajax comment form example.
Read More: Ajax in Symfony
Useful for almost any type of website. Say you have a job listing website, run the command:symfony propel-init-admin backend listing listings
and there you have your crud admin interface ready. Pretty, friendly, fully featured and without writing a single line of code.
But wait, what if I want to include feature X in the admin interface? Symfony uses a generator.yml configuration file which allows you to set filters and customize your admin interface. Most of the time this will more than fulfill your needs and you will easily create complete and functional backends.
See it happening: Generator Movie
Symfony uses a frontend controller, in which all requests are managed through a single frontend. This makes creating nice urls simpler than ever.post:
url: /weblog/:title
param: { module: post, action: permalink }
list_of_posts:
url: /latest_posts
param: { module: post, action: list }
How does that compare to writing htaccess files?
If you for instance would want the url for member profiles on your site to be www.mysite.com/members/member-name you would simply use:url: /members/:membername
param: { module: users, action: show }
The url indicates how you want the url to look and the param value tells Symfony where the code is located.
Read More: Links and the routing system
One of the areas where Symfony really shines is the handling of forms. The code for generating forms is clean and easy to understand and learn.
<?php echo select_tag('name', options_for_select(array(
'Steve' => 'Steve',
'Bob' => 'Bob',
'Albert' => 'Albert',
'Ian' => 'Ian',
'Buck' => 'Buck'
), 'Ian')) ?>
=> <select name="name" id="name">
<option value="Steve">Steve</option>
<option value="Bob">Bob</option>
<option value="Albert">Albert</option>
<option value="Ian" selected="selected">Ian</option>
<option value="Buck">Buck</option>
</select>
Furthermore validation and re-filling the form is done in a configuration file. This keeps your code and templates nice and clean. An example:fillin:
enabled: true
fields:
name:
required:
msg: The name field cannot be left blank
sfStringValidator:
min: 2
min_error: This name is too short (2 characters minimum)
max: 100
max_error: This name is too long. (100 characters maximum)
With some simple config lines you can take care of fillin and validation. For the skeptics, off course you can define your own validators. As far as I’ve experienced you can pretty much extend Symfony any way you like, with minimal effort. If you want client side validation as well you can opt to do so by installing one of the many plugins.
Read More: Forms in Symfony
We all wish our code to run smoothly in the first try. However the only way to achieve this is to never try anything new. If we have to Debug, let it at least be fast. Symfony provides us with a few awesome tools. First one is the developer toolbar.
Showing you: 1. your application variables (useful for multiple development environments) 2. logs and messages (all the steps used for executing the page, perfect for debugging) 3. the number of queries and their sql 4. the size of the page 5. the load time throughout various points of the code.
If you do something wrong related to Symfony, it gives you a nice explanation of the problem, through it’s custom error display. Installing the famous Xdebug extension further increases the amount of information displayed.
Read More: Application Management Tools
All these little things together make developing with Symfony a joy. More goodness to come up in part two of this post.
(Watch out with installing Symfony though. It will take you anywhere between 30 seconds and two days. Depending on your experience with PEAR. There are some great install guides on the Symfony Wiki.)
Update:
Part 2 has been published: Ten Reasons why Symfony rocks – part 2
By Thierry Schellenbach on 08 Sep 2007
If you weren’t convinced by the first 5 reasons why Symfony rocks, you will certainly be today.
Symfony’s closest competitors are probably RoR or rolling your own framework. Using a pre-made framework instead of rolling your own has several advantages:
Lets see the final 5 reasons why Symfony rocks. My chosen 10 are just a small subset of the powerful capabilities of Symfony and I will link to all good blog posts covering this topic. (Current Symfony version as of writing is 1.0.7)
Symfony offers a really fantastic suite of internationalization tools. I suppose the fact that the creators are in France has something to do with it. The simple comment example of the last post actually gives us a nice start to show the possibilities. We will support these nice languages: (English, Dutch, Italian and Romanian – the last two thanks to my girlfriend).
As mentioned Symfony provides a full solution. For the basic translation needs Symfony uses a helper function with two underscores, as such: __(’text which will be translated’). The text which needs to be translated can be exported to an XLIFF format using a plugin (Will be part of Symfony in 1.1.0) . For those wondering the XLIFF format looks like this:
<trans-unit id="5">
<source>Your name</source>
<target>Uw naam</target>
</trans-unit>
A simple config setting deals with the usage of utf-8; Formatting for numbers and dates are available and use the culture automatically. format_date() and format_number() automatically adjust their output depending on the culture.
Best of all the data model supports the concept of I18n tables. This allows you to have translations of items in your database (for instance products) and leave all the logic of dealing with this to Symfony. More advanced translation needs such as sentences, which depending on the database results need to be pluralized are also supported.
Lets look at the possibilities using the simple comment example. Implementing these languages is achieved in a few simple steps:
Firstly Symfony needs to be configured to support translations. This feature is turned off by default for performance reasons. To do this simply uncomment the commented lines in frontend/config/i18n.yml and set the following settings in frontend/config/settings.yml:
standard_helpers: [i18n]
charset: utf-8
i18n: on
Secondly we need to tell Symfony how to change the URLs, which we do in routing.yml. We will use URLs like this symfony-examples/nl/comment. Thirdly we need to actually use the interface translation helper __ on all our text, as such:__('All Comments:')
I happened to forget the submit button the first time around. This is a rather tedious process and you would usually do this while you create the template and not afterwards.
So now the fun of actually translating. First we create the messages.ro.xml and run the command: symfony i18n extract frontend ro. This command uses the plugin to extract the text, which needs translating. After some translating we now have a nicely internationalized version of the comment example. Go see and click the flags!
Those cute flags were created by famfamfam
Read More: Internationalization in the Manual
Caching is essential to the performance of any website. In many situations you can mess everything else up as long as your caching is good.
When reading about frameworks you will likely read that Symfony is somehow slow. Now off course you start to wonder whether this is true given that Yahoo uses it for its bookmark service. My impression is that these tests either use oversimplified ‘hello world’ examples or forget to query the database efficiently. A proper tests of speeds has to my knowledge not yet been conducted. Symfony is in fact lighting fast and offers a wide array of caching tools:
In order to make the nice comment example nice and fast we will add some simple caching to it.
in myapplication/mymodule/config/cache.yml:
index:
enabled: on
with_layout: false
lifetime: 3600
This enables the cache, however we do want to clear the cache when someone submits a new comment. This is easily achieved by adding the following to your update action:
$sf_root_cache_dir = sfConfig::get('sf_root_cache_dir');
$cache_dir = $sf_root_cache_dir.'/frontend/*/template/*/all';
sfToolkit::clearGlob($cache_dir.'/*/*/comment.cache');
sfToolkit::clearGlob($cache_dir.'/*/comment.cache');
This looks a bit complicated, but these four lines of code deal with deleting the cache for all languages.
Read more: Caching in Symfony
Read more: Memcached
Environments are a great way of running a few different set of configurations next to each other. This comes in extremely handy for development. By default Symfony has two environments: production and development. In the later all the caching is disabled, errors are displayed and the WebDebug toolbar is available.
When I wanted to setup caching these environments came in very handy. Somehow my comment form was not updating as it should. To diagnose the situation I added another environment called test (accessible by frontend_test.php), similar to dev, but with caching enabled. It quickly became clear that the problem originated from caching, client side to be specific.
For every larger application you will need to keep track of these different sets of configurations and Symfony enables this with great ease. To access the various environments simply browse to the corresponding front controller (index.php for production, frontend_dev.php for development, frontend_test.php for testing.)
To set the configuration settings, simply specify the config files as follows (example from standard frontend/config/settings.yml):
all: .settings: escaping_strategy: both escaping_method: ESC_ENTITIES standard_helpers: [i18n, Partial] charset: utf-8 i18n: on cache: on prod: .settings: no_script_name: on dev: .settings: # E_ALL | E_STRICT = 4095 error_reporting: 4095 web_debug: on cache: off no_script_name: off etag: off test: .settings: # E_ALL | E_STRICT & ~E_NOTICE = 2047 error_reporting: 4095 cache: on web_debug: on no_script_name: off etag: on
Read more about: Development Environments
All coders live by the rule of not repeating yourself. Symfony tries to make this as easy as possible for you. This is completely integrated into all aspects of Symfony. You can for instance write your own: Propel Behaviors, Filters, Validators and pretty any piece of normal code. This is one of the things which you will really like in Symfony. As a starter and to keep it short I’ll just cover the DRY tools in the view layer.
In Symfony there are four important methods to not repeat yourself in the view layer:
A partial is a simple piece of repeated template code. Say that you want to have the ability to add comments on multiple parts of your website. Simply stash the template code for adding comments in a partial. Partials are stored in the template directory with a _ (single underscore) before the partial name. When you want to include them simply use:
<?php include_partial('module/partial',array('varinpartial' => $myvar)) ?>
When the code to repeat becomes more complex and also requires some logic we can separate the logic and template code by using a component. Suppose for instance that you created a blog using Symfony and want to display the latest blog posts. The logic part of querying the database goes in a components.class.php file and the template in a partial. This gives you a very convenient way to reuse code. Including goes as follows:
<?php include_component('blog', 'latestposts') ?>
Slots are placeholders. You can define its content anywhere in the view layer. This is great if you for instance want to have a default sidebar in your layout, with the ability to overwrite it in the template.
The really interesting one is the component slot. This combines the power of the configuration file with logic and view separation. It functions very similar to a component, except that logic part to execute is indicated by a config file. As follows:
all:
components:
sidebar: [bar, user]
indexSuccess:
components:
sidebar: []
showSuccess:
components:
sidebar: [bar, options]
This would make the component slot display a user related sidebar by default, but on the index page display no sidebar and on the page displaying the user data display a sidebar with options.
Read more: Symfony’s View Layer
A short, but important point. Both the Zend framework and EZ components offer quite some valuable tools. Symfony feautures bridges to both of these, giving you access to two large arrays of tools.
This allows for nice things, such as an instant search engine for your site, using Zend Search Lucene (released just days ago). There is always a lot of discussion regarding the so called best framework, but I believe that eZComponents and Zend are actually pretty complimentary to Symfony.
These 10 points showed some of the power of Symfony. Hope you enjoyed them and will run over straight to The Symfony Documentation. If you like Symfony then Digg this post up and spread the word!
http://www.phpvn.org/index.php?topic=544.0
Phần I: Quảng cáo cho PDO 
Một trong những đồ chơi hoành tráng nhất trong phiên bản PHP “5 chấm” là sự ra đời của thư viện đối tượng PDO mở rộng, cho phép chúng ta thao tác với các CSDL khác nhau một cách nhẹ nhàng, đơn giản như là đi chơi Tết (Nói vậy chớ CMXQ thấy đi chơi tết cũng khó bỏ xừ, ít nhất là cái công đoạn rúc ra khỏi cái chăn ấm áp
).
Để chính thức khởi động PHPVN cho năm mới, CMXQ sẽ trùm chăn làm một serial về PDO. Điều kiện cần và đủ là:
- Biết qua một tí về ADO, BDO, ODBC hay cái quái gì có liên quan đến Data Object cũng được (để dễ so sánh với cái PDO này)
- Một cốc cafe G7 (cái này thì chắc ai cũng có sẵn).
- Nếu ở ngoài Bắc thì cần một cái chăn ấm nữa 
Nào, bây giờ chúng ta bắt đầu:
I. Giới thiệu về PDO
PDO là cụm từ viết tắt của PHP Data Objects, có nghĩa là Các đối tượng dữ liệu trong PHP (đại loại thế). Đây là một thành phần mở rộng của PHP nhằm cung cấp cho chúng ta một cách thức đơn giản đề truy cập vào các CSDL khác nhau trong PHP.
Nếu như các bạn đã từng lập trình trên .Net, các bạn sẽ thấy một cái gọi là ADO (bản cũ) và ADO.Net, còn nếu các bạn đã từng code bằng Delphi, nó cũng có một món đồ chơi tương tự gọi là BDO, còn trên Java là JDBC… Về cơ bản thì mấy cái này nó giông giống nhau, mà bản chất là cung cấp một mô hình trừu tượng để truy cập tới CSDL. (Có thể coi nó như là một lớp (layer) trong lập trình đa lớp).
Cơ chế làm việc của những cái này có thể được mô hình hoá như sau:
Ứng dụng <—-> PDO <—> Trình điều khiển các CSDL <—> Các truy vấn tới CSDL và kết quả trả về từ CSDL <—> CSDL (Access, MySQL, SQL Server, Oracle….).
Chúng ta có thể hình dung rằng mỗi một Hệ quản trị CSDL có một cách quản lý dữ liệu khác nhau, chẳng ai giống ai. Vì vậy, để truy xuất vào một loại CSDL nào đó, chúng ta cần phải khai báo trình điều khiển CSDL tương ứng với loại CSDL đó. Sau khi đã khai báo trình điều khiển, chúng ta có thể kết nối tới CSDL đó, tiến hành các truy vấn (có thể dựa trên ngôn ngữ truy vấn SQL, qua các Stored Procedure… mà CSDL đó hỗ trợ), lấy kết quả về rồi dùng các lệnh khác của PHP xử lý kết quả và hiển thị cho NSD.
II. Cài đặt PDO
PDO chỉ xuất hiện trong PHP từ ver 5 chấm trở đi, vì vậy nếu như server của các bạn chỉ support dưới 5 chấm, hãy chịu khó update lên 5 chấm.
Sau khi cài đặt xong, chúng ta phải mở cái php.ini và enable thư viện này (nếu chưa có) cùng các trình điều khiển tới các CSDL liên quan.
VD dưới đây là dòng lệnh cấu hình trình điều khiển CSDL chạy trên Windows:
extension=php_pdo.dll
extension=php_pdo_firebird.dll
extension=php_pdo_informix.dll
extension=php_pdo_mssql.dll
extension=php_pdo_mysql.dll
extension=php_pdo_oci.dll
extension=php_pdo_oci8.dll
extension=php_pdo_odbc.dll
extension=php_pdo_pgsql.dll
extension=php_pdo_sqlite.dll
Chi tiết hơn trên các HĐH khác nhau thì các bạn chịu khó xem trên PHP Manual nhé. Giờ tớ phải đi pha cafe đã.
I. Thiết lập kết nối tới CSDL
Đầu tiên, chúng ta cần phải biết rằng PDO thuần tuý là một lớp (class) được dùng để thao tác với CSDL. Vì vậy, nó cũng có các phương thức và thuộc tính như bất kỳ một lớp nào được xây dựng trên PHP.
PDO sử dụng một phương thức mặc định là __construct(). Phương thức này kiêm luôn nhiệm vụ tạo kết nối tới CSDL. Phương thức này có các tham số như sau:
PDO {
PDO __construct(string dsn,
string username,
string password,
array driver_options);
}
Trong đó:
- dsn (Data Source Name) là một chuỗi văn bản chứa các thông tin cần thiết để kết nối tới một CSDL xác định.
- username và password: chứa tên truy cập và mật khẩu của một tài khoản có quyền thao tác trên CSDL đó.
- driver_options là các tham số tuỳ chọn bổ sung nếu cần.
Cái DSN hơi khó nhớ một chút, và nó tuỳ thuộc vào loại CSDL. Nếu cần thiết thì các bạn chịu khó vào Google search. Ví dụ dưới đây là một chuỗi DSN kết nối tới CSDL MySQL:
‘mysql:dbname=testdb;host=127.0.0.1′;
Ví dụ:
Code:
<?php$dbh = new PDO('mysql:host=localhost;dbname=thumotti', 'thumotti', 'thuhaiti');?>
Đoạn mã trên tạo ra một biến $dbh (thể hiện của đối tượng PDO). Vì __construct là phương thức mặc định của PDO nên trong đoạn mã trên chúng ta không cần phải gọi tên phương thức này ra.
II. Huỷ kết nối tới CSDL
Để huỷ kết nối, đơn giản chúng ta chỉ việc gán instance của đối tượng đó với giá trị null.
VD:
Code:
<?php$dbh = new PDO('mysql:host=localhost;dbname=thumotti', 'thumotti', 'thuhaiti');$dbh=null?>
III. Sử dụng PDO để truy vấn SQL
Ở trên, các bạn đã biết cách kết nối và huỷ kết nối tới CSDL. Bây giờ chúng ta sẽ tiến hành thực hiện một truy vấn SQL thông qua PDO.
Để thực hiện một truy vấn SQL, chúng ta sử dụng một phương thức của PDO là exec().
PDO {
int exec(string statement);
}
Trong đó, statement là một câu lệnh SQL. Chú ý rằng câu lệnh SQL này phải chạy được trên CSDL mà ta đang sử dụng, (do mỗi một hệ quản trị CSDL lại có một vài câu lệnh SQL đặc chủng nên ta cần phải chú ý điều này). Phương thức trên trả về kết quả là số “râu” (row – record hay bản ghi) bị ảnh hưởng bởi câu lệnh SQL
Ví dụ dưới đây sử dụng để xoá một vài bản ghi nào đó:
<?php
$dbh = new PDO(‘mysql:host=localhost;dbname=thumotti’, ‘thumotti’, ‘thuhaiti’);
$count = $dbh->exec(“DELETE FROM users WHERE user_id<100″); // Xoá bỏ những “tên” có “số” nhỏ hơn 100.
print(“Đã xoá bỏ $count người khỏi CSDL.\n”);
?>
Comment: Hic, các ông thầy bói kể ra cũng đúng, mỗi người ai cũng có một cái số cả. Nhỡ bị exec delete thì toi 
Vậy là chúng ta đã biết cách thực hiện một truy vấn. Tuy nhiên, đời vẫn còn dài, ít nhất chúng ta cần phải lấy thông tin từ CSDL ra rồi in nó nữa chứ. Dù sao thì hồi 2 đã hết, xin xem tiếp hồi 3 … 
Hic, đợi mãi không thấy ai rate nên đành phải post thêm bài nữa, sau bài này CMXQ quyết tâm lột bỏ chăn gối để đi chơi chờ rate 
Nếu như các bạn làm theo những bước ở trên thì chưa đủ, ta phải tìm cách lấy dữ liệu trả về từ các query (VD như truy vấn Select chẳng hạn).
Để làm điều này, trước tiên chúng ta phải sử dụng một phương thức khác của PDO là PDO->query(). Phương thức này có nhiệm vụ thực thi một truy vấn SQL và trả về tập kết quả. Thường thì tập kết quả này sẽ được một lớp đối tượng khác là PDO Statement xử lý. Đây là tập các phương thức chuyên dụng để xử lý kết quả trả về, nó cũng gần giống như cái recordset vậy.
PDO {
PDOStatement query(string sql);
}
Các bạn cần chú ý phân biệt giữa hai phương thức exec() và query(). Exec() thực thi một truy vấn và trả về số các dòng bị ảnh hưởng bởi truy vấn, còn query() trả về một tập kết quả (thường là một recordset hoặc giá trị false). Người ta thường dùng exec() để truy vấn các câu lệnh như Insert, delete, update…, và dùng query() để truy vấn các câu lệnh Select.
Chúng ta có thể lấy kết quả ra theo hai cách: Lấy về từng dòng hay lấy về toàn bộ. Điểm đặc biệt là cũng như với các hàm xử lý MySQL, kết quả trả về thường được lưu trữ dưới dạng một mảng, rất thuận tiện và dễ dùng (hay nói ngắn gọn hơn là … đại tiện
).
I. Lấy kết quả về theo từng dòng
Để lấy kết quả theo từng dòng (tương tự như hàm mysql_fetch_array()), chúng ta có thể sử dụng phương thức PDOStatement->fetch().
PDOStatement {
mixed fetch(int fetch_style,
int cursor_orientation,
int cursor_offset);
}
Hàm này sử dụng 3 tham số tuỳ chọn:
- Fetch_style xác định cách thức lấy dữ liệu. Nó có thể nhận một trong các giá trị sau:
… và một vài giá trị khác, tham khảo thêm trong manual, nhưng vì chưa đến lúc sờ đến nên CMXQ không liệt kê ở đây.
Cũng tương tự như mysql_fetch_array, phương thức này lấy một dòng từ vị trí con trỏ hiện tại và đẩy con trỏ sang dòng kế tiếp.
Ví dụ:
Code:
$dbh = new PDO('mysql:host=localhost;dbname=thumotti', 'thumotti', 'thuhaiti');$stmt = $dbh->query("SELECT * FROM user where user_id<10") or die();
echo "<table>";while (($row = $stmt->fetch(PDO::FETCH_ASSOC))) { echo "<tr><td>${row['user_name']}<td>${row['e-mail']}\n";}echo "</table>";
II. Lấy toàn bộ dữ liệu và đưa vào mảng.
Để thực hiện điều này, chúng ta cần phải sử dụng một phương thức khác thay cho fetch, đó là fetchall(). Cách thức dùng cũng tương tư nặng thằng fetch, chỉ có điều nó đưa tất cả dữ liệu vào một mảng.
Ví dụ:
Code:
$dbh = new PDO('mysql:host=localhost;dbname=thumotti', 'thumotti', 'thuhaiti');$stmt = $dbh->query("SELECT * FROM user where user_id<10") or die();$result=$stmt->fetchAll();print_r($result);
cat /proc/meminfo
Linux comes with different command to check memory usage. free command displays the total amount of free and used physical and swap memory in the system, as well as the buffers used by the kernel.
vmstat command reports information about processes, memory, paging, block IO, traps, and cpu activity.
Then you can use top command which provides a dynamic real-time view of a running system. It can display system summary information as well as a list of tasks currently being managed by the Linux kernel.
Display free memory size in MB:
$ free -mOutput:
total used free shared buffers cached Mem: 750 625 125 0 35 335 -/+ buffers/cache: 254 496 Swap: 956 0 956
Displays a line containing the totals memory in MB:$ free -t -m
Output:
total used free shared buffers cached Mem: 750 625 125 0 35 335 -/+ buffers/cache: 253 496 Swap: 956 0 956 Total: 1707 625 1082
Type vmstat command at shell prompt:$ vmstatOutput:
procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu---- r b swpd free buff cache si so bi bo in cs us sy id wa 1 0 0 131620 35432 341496 0 0 42 82 737 1364 15 3 81 1
Type top command at shell prompt:$ topTo exit from top command type q key.
Read man page of free, vmstat, top command for complete information.