Thứ Năm, 16 tháng 9, 2010
Tối ưu hóa apache, php và mysql trên CentOS
Tối ưu apache:
Mở file /etc/httpd/conf/httpd.conf và thay đổi các giá trị sau:
01 Timeout 200
02 KeepAlive On
03 maxKeepAliveRequests 100
04 KeepAliveTimeout 3
05 MinSpareServers 10
06 MaxSpareServers 20
07 StartServers 15
08 MaxClients 250
09 MaxRequestsPerChild 0
10 HostnameLookups Off
Tối ưu hóa php:
Để tối ưu hóa php thì ta có thể cài eAccelerator để tăng tốc độ xử lý cho php.
Đầu tiên vào trang chủ của eAccelerator để download phiên bản mới nhất về. Giải nén và di chuyển đến thư mục đó.
Và sau đó gõ các lệnh sau:
1 phpize
2 ./configure
3 make
và tiến hành cài đặt eAccelerator :
1 make install
Tiếp theo chúng ta sẽ mỡ file php.ini ( thường ở /etc/php.ini ) và chèn đoạn mã sau vào cuối dòng:
01 extension="eaccelerator.so"
02 eaccelerator.shm_size="16"
03 eaccelerator.cache_dir="/tmp/eaccelerator"
04 eaccelerator.enable="1"
05 eaccelerator.optimizer="1"
06 eaccelerator.check_mtime="1"
07 eaccelerator.debug="0"
08 eaccelerator.filter=""
09 eaccelerator.shm_max="0"
10 eaccelerator.shm_ttl="0"
11 eaccelerator.shm_prune_period="0"
12 eaccelerator.shm_only="0"
13 eaccelerator.compress="1"
14 eaccelerator.compress_level="9"
Bước cuối cùng là tạo thư mục cache cho eAccelerator:
1 mkdir /tmp/eaccelerator
2 chmod 0777 /tmp/eaccelerator
Kiểm tra xem eAccelerator đã hoạt động chưa. Ta gõ php -v, nếu thấy xuất hiện:
1 PHP 5.2.6 (cli) (built: May 5 2008 10:32:59)
2 Copyright (c) 1997-2008 The PHP Group
3 Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies
4 with eAccelerator v0.9.5.3, Copyright (c) 2004-2006 eAccelerator, by eAccelerator
nghĩa là eAccelerator đang hoạt động
Tối ưu hóa mysql:
Mở file my.cnf và chèn vào đoạn code sau:
01 [mysqld]
02 max_connections = 400
03 key_buffer = 16M
04 myisam_sort_buffer_size = 32M
05 join_buffer_size = 1M
06 read_buffer_size = 1M
07 sort_buffer_size = 2M
08 table_cache = 1024
09 thread_cache_size = 286
10 interactive_timeout = 25
11 wait_timeout = 1000
12 connect_timeout = 10
13 max_allowed_packet = 16M
14 max_connect_errors = 10
15 query_cache_limit = 1M
16 query_cache_size = 16M
17 query_cache_type = 1
18 tmp_table_size = 16M
19 skip-innodb
20
21 [mysqld_safe]
22 open_files_limit = 8192
23
24 [mysqldump]
25 quick
26 max_allowed_packet = 16M
27
28 [myisamchk]
29 key_buffer = 32M
30 sort_buffer = 32M
31 read_buffer = 16M
32 write_buffer = 16M
Thứ Năm, 26 tháng 8, 2010
Grant quyền trong mysql
GRANT quyền ON tên_csdl TO tên_user IDENTIFIED BY 'mật_mã';
- Quyền có dạng như sau:
ALL PRIVILEGES: tất cả mọi quyền.
Các quyền sau đây có thể được kết hợp với nhau, phân cách bằng dấu phảy (,):
ALTER: cho phép user sử dụng lệnh ALTER TABLE.CREATE: cho phép user sử dụng lệnh CREATE TABLE.CREATE TEMPORARY TABLES: cho phép user sử dụng lệnh CREATE TEMPORARY TABLE.CREATE VIEW: cho phép user sử dụng lệnh CREATE VIEW.DELETE: cho phép user sử dụng lệnh DELETE.DROP: cho phép user sử dụng lệnh DROP TABLE.FILE: cho phép user sử dụng lệnh SELECT ... INTO OUTFILE và LOAD DATE INFILE.INDEX: cho phép user sử dụng lệnh CREATE INDEX và DROP INDEX.INSERT: cho phép user sử dụng lệnh INSERT.LOCK TABLES: cho phép user sử dụng lệnh LOCK TABLES trên những table nào user có quyền SELECT.PROCESS: cho phép user sử dụng lệnh SHOW FULL PROCESSLIST.RELOAD: cho phép user sử dụng lệnh FLUSH.SELECT: cho phép user sử dụng lệnh SELECT.SHOW DATABASES: khi user sử dụng lệnh SHOW DATABASES, danh sach của toàn bộ các CSDL trong hệ thống.SHOW VIEW: cho phép user sử dụng lệnh SHOW CREATE VIEW.UPDATE: cho phép user sử dụng lệnh UPDATE.
Ngoài ra một quyền đặt biệc là USAGE sẽ gán toàn bộ các quyền của user là "không được phép". Quyền này thường được gán cho các account không có quyền global trên hệ thống. Thường sau khi gán quyền USAGE, quản trị viên của server sẽ tiếp tục gán một vài quyền nhất định cho account trên một số CSDL nhất định.
Ví dụ:
mysql> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'localhost' IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
mysql> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'%'
-> IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
mysql> GRANT RELOAD,PROCESS ON *.* TO 'admin'@'localhost';
mysql> GRANT USAGE ON *.* TO 'dummy'@'localhost';
sau khi Grant xong bạn phải gõ lệnh flush privileges
Thứ Tư, 25 tháng 8, 2010
Install Apache, PHP 4, MySQL từ CentOS
1. Cài đặt apache và PHP
Cài apache và PHP (đây là PHP 4; CentOS chưa đưa ra PHP 5):
yum install php php-devel php-gd php-imap php-ldap php-mysql php-odbc php-pear php-xml php-xmlrpc curl curl-devel perl-libwww-perl ImageMagick libxml2 libxml2-devel
sau đó edit /etc/httpd/conf/httpd.conf:
vi /etc/httpd/conf/httpd.conf
và chuyển DirectoryIndex tới
DirectoryIndex index.html index.htm index.shtml index.cgi index.php index.php3 index.pl
Cấu hình nó khởi dộng ban đầu nào (khi linux khởi động – nó start luôn):
chkconfig --levels 235 httpd on
Start Apache:
/etc/init.d/httpd start
2. Cài đặt Mysql
Để cài MySQL, chạy lệnh:
yum install mysql mysql-devel mysql-server
nó hỏi gì thì yes -> nó sẽ tìm và download thằng mysql về và cài đặt.
(note: theo những ng có kinh nghiệm về CentOS server – thì MYSQL đuợc cài đặt sẵn ở đây có một chút lỗi khi ta restart. Để sửa lỗi ta dùng vi edit file này
vi /etc/init.d/mysqld
restart(){
stop
start
}
Ta thêm 1 dòng sleep 3 vào giữa stop và start. )
Sau đó cho MySQL tự động bắt đầu khi khởi dộng linux (boot linux):
Và start
chkconfig --levels 235 mysqld on
/etc/init.d/mysqld start
check thử xem chạy chưa nèo
netstat -tap
(hoặc áp dụng thử lệnh grep để tìm kiếm)
netstat –tap | grep my
Note: nếu nó ko chạy thì ta phải làm thêm 1 bước nữa
vi /etc/my.cnf
#skip-networking
/etc/init.d/mysqld restart
Đặt password root:
mysqladmin -u root password yourrootsqlpassword
mysqladmin -h server1.example.com -u root password yourrootsqlpassword
3. BONUS: hướng dẫn cấu hình ISPConfig (disable PHP Globally).
ISPConfig được sử dụng đối với nhiều site cấu hình khác nhau chạy trên cùng một server.
Ví dụ bạn tạo 1 alias của img.sannhac.com tại server này, như vậy mặc định của nó là … cũng chạy PHP luôn. Điều này rất nguy hiểm nếu quá trình upload check không kỹ type extensions. Chính vì thế, Apache có nhiều option – site sẽ không đc chạy PHP chẳng hạn – là do cấu hình của ISPConfig ^_^
Đầu tiên
vi /etc/httpd/conf.d/php.conf
#
# PHP is an HTML-embedded scripting language which attempts to make it
# easy for developers to write dynamically generated webpages.
#
LoadModule php4_module modules/libphp4.so
#
# Cause the PHP interpreter to handle files with a .php extension.
#
#AddType application/x-httpd-php .php
# AddType application/x-httpd-php-source .phps
#
# Add index.php to the list of files that will be served as directory
# indexes.
#
DirectoryIndex index.php
Sau đó Restart Apache:
/etc/init.d/httpd restart
Creating and Removing Index
Database indexes help to speed the retrieval of data from MySQL database server faster. When retrieving the data, MySQL first check whether the indexes exists; If yes it will use index to select exact physical corresponding rows without scanning the whole table.
In general, it is suggested that you should put indexes on columns you usually use in retrieval such as primary key columns and columns used in join and sorts. Why not index every column? The most significant is that building and maintaining an indexes tables take time and storage space on database.
Usually you create indexes when creating tables. Any column in creating table statement declared as PRIMARY KEY, KEY, UNIQUE or INDEX will be indexed by MySQL. In addition, you can add indexes to the tables which has data. The statement to create index in MySQL as follows:
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
USING [BTREE | HASH | RTREE]
ON table_name (column_name [(length)] [ASC | DESC],...)
First you specify the index based on the table types or storage engine:
UNIQUE means MySQL will create a constraint that all values in the index must be distinct. Duplicated NULL is allowed in all storage engine except BDB.
FULLTEXT index is supported only by MyISAM storage engine and only accepted columns which have data type is CHAR,VARCHAR or TEXT.
SPATIAL index supports spatial column and available in MyISAM storage engine. In addition, the column value must not be NULL.
Then you name the index using index types such as BTREE, HASH or RTREE also based on storage engine. Here are the list:
Storage Engine Allowable Index Types
MyISAM BTREE, RTREE
InnoDB BTREE
MEMORY/HEAP HASH, BTREE
NDB HASH
Finally you declare which column on which table using the index.
In our sample database you can add index to officeCode column on employees table to make the join operation with office table faster as follows:
CREATE INDEX officeCode ON employees(officeCode)
Removing Indexes
Beside creating index you can also removing index by using DROP INDEX statement in MySQL. Interestingly, DROP INDEX statement is also mapped to ALTER TABLE statement. Here is the syntax:
DROP INDEX index_name ON table_name
For example, if you want to drop index officeCode which we have added to the employees table, just execute following query:
DROP INDEX officeCode ON employees
Các cách đánh index cho trường trong CSDL MySQL
Việc Database quá tải còn dẫn đến nhiều thiệt hại khác, các hàng đợi (Queuie) dài ra, file logs lớn lên chiếm hết không gian đĩa và user khi kết nối sẽ bị từ chối. Rõ ràng là câu báo lỗi “Too many connections” không phải là hiếm gặp trong các website trên Internet. Những lỗi trên thông thường bắt nguồn từ khâu định nghĩa Database (define) hay không sử dụng Indexes. Khắc phục những thiếu sót trên, Database của bạn sẽ “nhẹ nhàng” và nhanh chóng đáng kể. Hãy xem xét ví dụ sau:
CREATE TABLE tblUsers (
user_id int(11) NOT NULL,
user_name vachar(25),
user_pwd vachar(50),
user_firstname varchar(40),
user_surname varchar(40),
user_address text,
user_tel varchar(25),
user_goal int(11),
);
Và để tìm thông tin Điểm của Nguyễn Văn A (mã số 120956), bạn sẽ query như sau:
SELECT user_goal FROM tblUsers WHERE user_id = ‘120956′;
MySQL biết rằng phải tìm ở table tblUsers nhưng nó sẽ không biết bắt đầu từ đâu. Thậm chí nó cũng không biết trước rằng có bao nhiêu kết quả . Do đó nó sẽ duyệt qua tất cả danh sách (vd Hơn 300.000 người) để tìm thông tin về Nguyễn Văn A.
Index là 1 file riêng biệt được lưu trữ ở máy chủ và chỉ chứa những Fields mà bạn muốn nó chứa. Nếu bạn tạo 1 Index cho Field user_id (mã số người dùng), MySQL sẽ dễ dàng tìm ra được mã số 1 cách nhanh chóng. Trở lại ví dụ quyển sách, khi cần tìm 1 thông tin, ta thường lật ngay tới phần “Mục Lục” và tìm từ đó để tăng tốc độ tìm. Và việc tạo ra Index này sẽ làm bạn thấy Database của bạn chạy nhanh 1 cách khác thường.
Nhưng trước khi sửa lại cấu trúc của table ở trên, tôi sẽ hướng dẫn bạn 1 chút về cách theo dõi kết quả “Tăng tốc MySQL” mà bạn đang làm. Hãy sử dụng lệnh EXPLAIN
Cú pháp: EXPLAIN Query;
Bằng lệnh này bạn sẽ nhận ra được với câu Query của bạn, điều gì đang xảy ra và kiểu kết hợp (Join) nào đang diễn ra bên trong.
Xem ví dụ sau:
mysql>EXPLAIN SELECT user_id,user_firstname,user_surname FROM tblUsers WHERE user_id= ‘120956‘;
+———-+——+—————+——+———+——+——+————+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+———-+——+—————+——+———+——+——+————+
| tblUsers | ALL | NULL | NULL | NULL | NULL | 86792| where used |
+———-+——+—————+——+———+——+——+————+
Giải thích:
- table : Table nào đang liên quan đến output data
- type : Đây là thông tin quan trọng, nó cho chúng ta biết kiểu query nào nó đang sử dụng. Mức độ từ tốt nhất đến chậm nhất như sau: system, const, eq_ref, ref, range, index, all
- possible_keys : Đưa ra những Index có thể sử dụng để query
- key : và Index nào đang được sử dụng
- key_len : Chiều dài của từng mục trong Index
- ref : Cột nào đang sử dụng
- rows : Số hàng (rows) mà MySQL dự đoán phải tìm
- extra : Thông tin phụ, thật tệ nếu tại cột này là “using temporary” hay “using filesort”
Wow, nhìn lại câu query của chúng ta mới thật khủng khiếp. Không có Possible_keys nào được sử dụng, MySQL phải duyệt qua 86792 bản ghi mới tìm ra cái ta cần (Hãy tưởng tượng 1 Forum sẽ có đến hơn 500.000 bản ghi).
Bây giờ chúng ta sẽ thêm Index vào và query lại
mysql>ALTER TABLE tblUsers ADD INDEX idx_userid(user_id);
mysql>EXPLAIN SELECT user_id,user_firstname,user_surname FROM tblUsers WHERE user_id= ‘120956‘;
+———-+——-+—————+———+———+——-+——+——-+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+———-+——-+—————+———+———+——-+——+——-+
| tblUsers | const | PRIMARY | PRIMARY | 10 | const | 1 | |
+———-+——-+—————+———+———+——-+——+——-+
Tốt hơn nhiều rồi, kiểu TYPE = Const có nghĩa rằng MYSQL hiểu ra chỉ có 1 hàng đúng với ý ta, và thể hiện qua cột Rows = 1, kiểu key= PRIMARY được sử dụng và chiều dài key_len là 10.Chỉ tìm 1 hàng tất nhiên rằng tốt hơn nhiều so với tìm 86792 hàng
Vậy câu hỏi đặt ra là, nếu tôi muốn thêm Index cho những cột mà có thể có nhiều hơn 1 kết quả khi query thì sao?
Vẫn add index như bình thường,giả sử bạn cần tìm những người có họ là Nguyễn Văn, tên là A
mysql>ALTER TABLE tblUsers ADD INDEX idxSFname (user_surname, user_firstname);
mysql>EXPLAIN SELECT user_goal FROM tblUsers WHERE user_surname=’Nguyễn Văn‘ AND user_firstname=”A“;
+——–+——+——————-+———+———+——-+——+———–+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+——–+——+——————-+———+———+——-+——+———–+
|tblUsers| ref | user_surname,user_firstname | idxSFname | 41 | const | 1 |where used |
+——–+——+——————-+———+———+——-+——+———–+
Tuy nhiên, nếu chỉ cần user_firstname
mysql>EXPLAIN SELECT user_goal FROM tblUsers WHERE user_firstname=’Name’;
+———-+——+—————+——+———+——+——+————+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+———-+——+—————+——+———+——+——+————+
| tblUsers | ALL | NULL | NULL | NULL | NULL | 86792 | where used |
+———-+——+—————+——+———+——+——+————+
thì MySQL sẽ tìm hết vì không hề có Index cho user_firstname mà chỉ có Index cho (user_surname, user_firstname).
Khi nào thì cần Add Index ? Bất cứ khi nào bạn thay đổi Table bạn đều cần Add Index lại, giống như khi bạn thay đổi nội dung quyển sách, bạn cần phải làm lại mục lục. Vậy hãy cân nhắc, nếu Database của bạn sử dụng INSERT hay UPDATE nhiều hơn là SELECT thì Index chỉ làm chậm thêm mà thôi.
Có thể nhanh hơn nữa không ? Câu trả lời là Có! Bạn không cần phải làm Index cho cả Field mà chỉ cần 1 phần. Giống như chi tiết Mục Lục của sách mà quá dài cũng làm bạn khá vất vả, do đó họ chỉ trích dẫn 1 tựa đề. Quay lại với table của chúng ta, user_surname và user_firstname chỉ maximum là 40 chars, nếu chúng ta index nó, chúng ta tạo ra mỗi record đến 80 chars . Có thể tiết kiệm bằng cách sau
mysql>ALTER TABLE tblUsers ADD INDEX(user_surname(20),user_firstname(20));
Bây giờ thì bạn tiết kiệm được đến 50% mà vẫn đảm bảo được tốc độ rồi đó (trừ phi bạn làm Index quá ngắn). Có thể bạn nói đĩa cứng server tôi “vô tư” nhưng hãy nhớ rằng “Nhỏ hơn là nhanh hơn”.
ĐIỀU KÌ DIỆU VỚI OPTIMIZE VÀ ANALYZE
“Ma thuật” của MySQL là biết cách chọn khoá (key) nào để query(nếu có). Quá trình này gọi là “query optimizer”, nó sẽ “liếc” qua những Index đang có để quyết định sẽ dùng Index nào để tìm. Hãy tưởng tượng bạn đang tìm 1 dĩa CD của “Maria Carrey” có tên là “I Love You”, có nghĩa là có 2 Indexes ở đây, 1 cho tên tác giả và 1 cho tên CD. Bạn nhận thấy rằng danh mục có 20.000 tên tác giả và 400.000 tên Album. Một cách đơn giản,bạn sẽ tìm theo tên tác giả. Khi có được, bạn lại thấy rằng “Maria Carrey” có 50 CDs và CD “I Love You” bắt đầu bằng chữ I. Đơn giản và dễ dàng tìm ra cái mình muốn phải không ? MySQL cũng vậy nhưng …bạn phải chỉ cho nó bằng cách:
ANALYZE TABLE tablename;
Những lệnh DELETE và UPDATE để lại rất nhiều những khoảng trống (gaps) vô nghĩa cho table (Đặc biệt là khi bạn dùng kiểu varchar hay text/blob). Điều đó có nghĩa rằng MySQL cũng phải đọc và phân tích những thứ vô nghĩa đó khi query. Điều này được khắc phục khi bạn chạy
OPTIMIZE tablename;
Do đó 2 câu lệnh trên bạn nên chạy 1 cách thường xuyên để bảo đảm tối ưu hoá Database của mình.