2个ppt: mysql与ssd, pt-online-schema-change

http://www.percona.com/files/presentations/WEBINAR-MySQL-SSD.pdf

http://www.percona.com/files/presentations/WEBINAR-zero-downtime-schema-changes.pdf

相关的视频在http://www.percona.tv/上面找找看。。。。

Posted in mysql | Tagged | Leave a comment

使用pt-table-checksum检查主从复制是否正常

使用pt-table-checksum检查主从复制是否正常

半个月前写过一篇文章,说了说《mysql主从需要注意的几个问题》。

其实对于一个小小的DBA来说,有时候是无法避免这些问题的。
于是我们就需要一个工具,来检查主从复制是否正常,是否出现了错误。

pt-table-checksum。

在主服务器上 checksum mysql数据库:

#pt-table-checksum --replicate=test.checksum --create-replicate-table --databases=mysql localhost
 
TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE
04-24T16:06:45 0 0 0 1 0 0.099 mysql.columns_priv
 
04-24T16:06:45 0 0 32 1 0 0.100 mysql.db
 
04-24T16:06:45 0 0 0 1 0 0.096 mysql.event
 
04-24T16:06:45 0 0 0 1 0 0.096 mysql.func
 
04-24T16:06:45 0 0 38 1 0 0.102 mysql.help_category
 
04-24T16:06:45 0 0 452 1 0 0.106 mysql.help_keyword
 
04-24T16:06:46 0 0 993 1 0 0.096 mysql.help_relation
 
04-24T16:06:46 0 0 506 1 0 0.100 mysql.help_topic
 
04-24T16:06:46 0 0 0 1 0 0.099 mysql.host
 
04-24T16:06:46 0 0 0 1 0 0.104 mysql.ndb_binlog_index
 
04-24T16:06:46 0 0 0 1 0 0.107 mysql.plugin
 
04-24T16:06:46 0 1 1 1 0 0.115 mysql.proc
 
04-24T16:06:46 0 0 0 1 0 0.186 mysql.procs_priv
 
04-24T16:06:46 0 1 1 1 0 0.097 mysql.proxies_priv
 
04-24T16:06:47 0 0 0 1 0 0.097 mysql.servers
 
04-24T16:06:47 0 0 0 1 0 0.096 mysql.tables_priv
 
04-24T16:06:47 0 0 0 1 0 0.098 mysql.time_zone
 
04-24T16:06:47 0 0 0 1 0 0.097 mysql.time_zone_leap_second
 
04-24T16:06:47 0 0 0 1 0 0.100 mysql.time_zone_name
 
04-24T16:06:47 0 0 0 1 0 0.100 mysql.time_zone_transition
 
04-24T16:06:47 0 0 0 1 0 0.095 mysql.time_zone_transition_type
 
04-24T16:06:47 0 1 38 1 0 0.100 mysql.USER

只有在第一次运行的时候,需要 –create-replicate-table 选项,以后重复运行就不必了。
每个表的checksum值会保存到 test.checksum中,然后会被replicate到所有的从服务器。

然后就可以检测从服务器是否正常了。不过下面的命令依然是在主服务器上运行的:

$ pt-table-checksum --replicate=test.checksum --replicate-check-only --databases=mysql localhost

如果数据都一致的话,就不会有什么输出。否则可能会有下面的输出:

Differences ON ip-10-15-27-19
TABLE CHUNK CNT_DIFF CRC_DIFF CHUNK_INDEX LOWER_BOUNDARY UPPER_BOUNDARY
 
mysql.USER 1 1 1
Posted in mysql | Tagged , | Leave a comment

Ext3 Ext4 磁盘空间不足的一个应急解决办法

Ext3 Ext4这两种文件系统有一个特点,如果用的默认安装,
它会保留每个分区5%的空间,不允许非root用户使用。
事实上,我经手这么多服务器,从来都是保留5%,没有人会去改这个设置。

如果某个分区满了,可以释放这5%的空间,救个急总是OK的。

[root@db4 ~]# df -h
Filesystem            SIZE  Used Avail Use% Mounted ON
/dev/mapper/vg_centos-lv_root
                       30G   25G  3.4G  89% /
tmpfs                 3.9G     0  3.9G   0% /dev/shm
/dev/sda1             243M   47M  183M  21% /boot
/dev/mapper/vg_centos-lv_mysql
                      145G  145G  5.7M 100% /vol/mysql
 
[root@db4 ~]# mount
[..]
/dev/mapper/vg_centos-lv_mysql ON /vol/mysql TYPE ext4 (rw,noatime,nodiratime)
 
 
可以看到是ext4的文件系统
[root@db4 ~]# dumpe2fs /dev/mapper/vg_centos-lv_mysql | grep 'Reserved block count'
dumpe2fs 1.41.12 (17-May-2010)
Reserved block COUNT: 1927884
 
 
保留了1927884个4KB的block。 正好是分区大小的5%。
 
[root@db4 ~]# tune2fs -m 0 /dev/mapper/vg_centos-lv_mysql
tune2fs 1.41.12 (17-May-2010)
Setting reserved blocks percentage TO 0% (0 blocks)
 
[root@db4 ~]# df -h
Filesystem            SIZE  Used Avail Use% Mounted ON
/dev/mapper/vg_centos-lv_root
                       30G   25G  3.4G  89% /
tmpfs                 3.9G     0  3.9G   0% /dev/shm
/dev/sda1             243M   47M  183M  21% /boot
/dev/mapper/vg_centos-lv_mysql
                      145G  145G  7.3G  95% /vol/mysql
 
 
一下子又出来7个G的空间。

不过这种办法只能用一次~~
下次分区再满了,就去想其它办法吧。

另外,也应该搞个监控软件去监视分区的使用情况,尽早做出预警。

Posted in linux | Tagged , | Leave a comment

不太常见但是却很好用的linux工具

不太常见但是却很好用的linux工具

工具见这里:

http://kkovacs.eu/cool-but-obscure-unix-tools

最后一个cowsay 笑死人了。

还有dstat, 聚集了load average, network transfer, disk operation:

----total-cpu-usage---- ---paging-- ---load-avg--- ------memory-usage----- -net/total- ---procs--- --io/total- ---system-- ----tcp-sockets----
usr sys idl wai hiq siq|  IN   OUT | 1m   5m  15m | used  buff  cach  free| recv  send|run blk NEW| READ  writ| INT   csw |lis act syn tim clo
  0   0 100   0   0   0|   0     0 |0.07 0.25 0.25| 866M  249M  537M  387M|1314B  180B|  0   0   0|   0     0 |  70    80 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.07 0.25 0.25| 866M  249M  537M  387M|1779B 1004B|  0   0   0|   0     0 |  84    78 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.07 0.25 0.25| 866M  249M  537M  387M| 904B  362B|1.0   0 1.0|   0     0 |  75    86 | 13   9   0   0   5
  0   0 100   0   0   0|   0     0 |0.07 0.25 0.25| 866M  249M  537M  386M|2203B 1559B|  0   0   0|   0     0 | 180   127 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.07 0.25 0.25| 866M  249M  537M  386M| 260B  130B|  0   0   0|   0     0 |  53    66 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.07 0.25 0.25| 866M  249M  537M  387M|  52B  114B|  0   0   0|   0     0 |  54    77 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.07 0.25 0.25| 866M  249M  537M  387M|2271B  872B|  0   0   0|   0     0 |  94    79 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.07 0.25 0.25| 866M  249M  537M  387M|  52B  130B|  0   0   0|   0     0 |  54    74 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.07 0.25 0.25| 866M  249M  537M  387M|1126B 1254B|  0   0   0|   0  24.0 |  80    87 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.07 0.25 0.25| 866M  249M  537M  387M|1030B  130B|  0   0   0|   0     0 |  88    82 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.06 0.24 0.25| 866M  249M  537M  387M| 578B  114B|  0   0   0|   0     0 |  53    64 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.06 0.24 0.25| 866M  249M  537M  387M|1597B  890B|  0   0   0|   0     0 |  85    79 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.06 0.24 0.25| 866M  249M  537M  387M| 552B  114B|  0   0   0|   0     0 |  63    77 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.06 0.24 0.25| 866M  249M  537M  387M|1624B 1254B|  0   0   0|   0     0 |  81    75 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.06 0.24 0.25| 866M  249M  537M  387M| 478B  114B|  0   0   0|   0     0 |  67    73 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.06 0.24 0.25| 866M  249M  537M  387M| 418B  114B|  0   0   0|   0     0 |  59    74 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.06 0.24 0.25| 866M  249M  537M  387M|1265B  874B|  0   0   0|   0     0 |  82    73 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.06 0.24 0.25| 866M  249M  537M  387M| 758B  114B|  0   0   0|   0     0 |  60    80 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.06 0.24 0.25| 866M  249M  537M  387M|1236B 1255B|  0   0   0|   0  4.00 |  93    79 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.06 0.24 0.25| 866M  249M  537M  387M|  52B  130B|  0   0   0|   0     0 |  71    70 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.05 0.23 0.25| 866M  249M  537M  387M| 214B  114B|  0   0   0|   0     0 |  55    73 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.05 0.23 0.25| 866M  249M  537M  387M|1201B  890B|  0   0   0|   0     0 |  80    80 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.05 0.23 0.25| 866M  249M  537M  387M| 108B  114B|  0   0   0|   0     0 |  53    66 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.05 0.23 0.25| 866M  249M  537M  387M|1344B 1254B|  0   0   0|   0  10.0 | 119    85 | 13   7   0   0   5
  0   0 100   0   0   0|   0     0 |0.05 0.23 0.25| 866M  249M  537M  387M| 172B  130B|  0   0   0|   0  8.00 |  80    82 | 13   7   0   0   5

dstat的更详细教程看这里:

http://dag.wieers.com/home-made/dstat/

Posted in linux, shell | Leave a comment

SQL Injection at Reddit

[MODIFY@H209 ~]$ curl --head www.reddit.com
HTTP/1.1 200 OK
Content-TYPE: text/html; charset=UTF-8
Set-Cookie: reddit_first=%7B%22organic_pos%22%3A%201%2C%20%22firsttime%22%3A%20%22first%22%7D; DOMAIN=reddit.com; expires=Thu, 31 DEC 2037 23:59:59 GMT; Path=/
Server: '; DROP TABLE servertypes; --
Date: Thu, 17 May 2012 03:05:54 GMT
Connection: keep-alive

看Server那一行。。。不知道是怎么搞出来的。

Posted in mysql | Tagged | Leave a comment

apache mod_cgi 可能导致php文件源码泄露

If you are using Apache mod_cgi to run PHP you may be vulnerable.
To see if you are, just add ?-s to the end of any of your URLs.
If you see your source code, you are vulnerable. If your site renders normally, you are not.

To fix this, update to PHP 5.3.12 or PHP 5.4.2.

据说这个bug存在至少8年了。。。

http://www.php.net/archive/2012.php#id2012-05-03-1

Posted in 花荣在写PHP代码 | Tagged , | Leave a comment

从mysqldump的备份中只恢复一张表

从mysqldump的备份中只恢复一张表

全部恢复当然简单了。
只恢复某个数据库的话,之前也总结过几个方法。
今天只讲如何从mysqldump的备份中恢复某张表:

先取出表结构:

# EXTRACT TABLE STRUCTURE FOR TABLE 'customer'
sed -ne '1,/^-- \(Current\|Database\)/{/^\(--.*\)*\?$/d;p};/^-- Table.*`customer`/,/^-- \(Dumping\|Table\|Temporary\)/{/^\(--.*\)*\?$/d;/^DROP/d;p}' dump.SQL

取出数据:

# EXTRACT DATA dump FOR TABLE 'customer'
sed -ne '1,/^-- \(Current\|Database\)/{/^\(--.*\)*\?$/d;p};/^-- Dumping.*`customer`/,/^-- \(Dumping\|Table\|Temporary\)/{/^\(--.*\)*\?$/d;p}' dump.SQL

还有一个shell脚本,既可以恢复某个库,也可以只恢复某张表:

http://www.dbasquare.com/downloads/

garfield ~ # ./extract.sh -f dump.sql -d redmine > redmine.sql
garfield ~ # ./extract.sh -f dump.sql -d redmine -t workflows > redmine-workflows.sql
Posted in mysql | Tagged | Leave a comment

mysql主从需要注意的几个问题

mysql主从需要注意的几个问题

1. 尽量不要使用stored procedures和triggers。
Stored procedures can behave strangely with statement based replication

2. 尽量不要使用temporary tables。
比如memory类型的表。有些程序就特别喜欢动态地创建和删除memory表。。
设想一下,某个slave挂掉了,重启服务器,memory类型的表都被清空了。。。
可以再看一下这篇文章:

http://scale-out-blog.blogspot.com/2012/04/replication-is-bad-for-mysql-temp.html

3. 尽量不要使用MyISAM类型的表。
InnoDB多好啊。
MyISAM不支持事务,表空间经常损坏,而且读写并发性能很低。
没有理由继续使用MyISAM啊。

4. 避免使用某些函数
比如 UUID() rand() 之类的函数,它们的结果都是不确定的。

5. 避免使用UPDATE … LIMIT …
以及 DELETE … LIMIT …

否则有可能死得很惨。 可以看看这篇文章:

http://www.dbasquare.com/2012/04/17/why-a-statement-can-be-unsafe-when-it-uses-limit-clause/

Posted in mysql | Leave a comment

使用php class来处理htpasswd

使用php class来处理htpasswd

在apache中可以使用.htpasswd文件来保护某些网页,只有登陆用户才可以访问到。
直接使用shell来创建 htpasswd文件,对于某些新手来说,确实有一点点难度。
今天找到一个php class,可以自动创建.htpasswd文件,哦,还有.htgroup。

/home/myuser/.htpasswd

user1:{SHA}kGPaD671VNU0OU5lqLiN/h6Q6ac=
user2:{SHA}npMqPEX3kPQTo+x/+ZckHDrIcQI=
user3:{SHA}q1Fh2LTUjjkncp11m0M9WUH5Zrw=

/home/myuser/.htgroup

admin: user2
editor: user1 user3
writer: user3

/home/myuser/public_html/example.com/member/.htaccess

AuthName "Members Area"
AuthType Basic
AuthUserFile /home/myuser/.htpasswd
AuthGroupFile /home/myuser/.htgroup
<Limit GET POST>
require GROUP admin
require GROUP writer
</Limit>

只有user1 和 user3 可以访问到 http://example.com/member/。

下面是这两个class的代码:

class Htpasswd {
 
	private $file = '';
	private $salt = 'AynlJ2H.74VEfI^BZElc-Vb6G0ezE9a55-Wj';
 
	private function write($pairs = array()) {
		$str = '';
		foreach ($pairs as $username => $password) {
			$str .= "$username:{SHA}$password\n";
		}
		file_put_contents($this -> file, $str);
	}
 
	private function read() {
		$pairs = array();
		$fh = fopen($this -> file, 'r');
		while (!feof($fh)) {
			$pair_str = str_replace("\n", '', fgets($fh));
			$pair_array = explode(':{SHA}', $pair_str);
			if (count($pair_array) == 2) {
				$pairs[$pair_array[0]] = $pair_array[1];
			}
		}
		return $pairs;
	}
 
	private function getHash($clear_password = '') {
		if (!empty($clear_password)) {
			return base64_encode(sha1($clear_password, true));
		} else {
			return false;
		}
	}
 
	public function __construct($file) {
		if (file_exists($file)) {
			$this -> file = $file;
		} else {
			die($file." doesn't exist.");
			return false;
		}
	}
 
	public function addUser($username = '', $clear_password = '') {
		if (!empty($username) && !empty($clear_password)) {
			$all = $this -> read();
			if (!array_key_exists($username, $all)) {
				$all[$username] = $this -> getHash($clear_password);
				$this -> write($all);
			}
		} else {
			return false;
		}
	}
 
	public function deleteUser($username = '') {
		$all = $this -> read();
		if (array_key_exists($username, $all)) {
			unset($all[$username]);
			$this -> write($all);
		} else {
			return false;
		}
	}
 
	public function doesUserExist($username = '') {
		$all = $this -> read();
		if (array_key_exists($username, $all)) {
			return true;
		} else {
			return false;
		}
	}
 
	public function getClearPassword($username) {
		return strtolower(substr(sha1($username.$this -> salt), 4, 12));
	}
 
}
class Htgroup {
 
	private $file = '';
 
	private function write($groups = array()) {
		$str = '';
		foreach ($groups as $group => $users) {
			$users_str = '';
			foreach ($users as $user) {
				if (!empty($users_str)) {
					$users_str .= ' ';
				}
				$users_str .= $user;
			}
			$str .= "$group: $users_str\n";
		}
		file_put_contents($this -> file, $str);
	}
 
	private function read() {
		$groups = array();
		$groups_str = file($this -> file, FILE_IGNORE_NEW_LINES);
		foreach ($groups_str as $group_str) {
			if (!empty($group_str)) {
				$group_str_array = explode(': ', $group_str);
				if (count($group_str_array) == 2) {
					$users_array = explode(' ', $group_str_array[1]);
					$groups[$group_str_array[0]] = $users_array;
				}
			}
		}
		return $groups;
	}
 
	public function __construct($file) {
		if (file_exists($file)) {
			$this -> file = $file;
		} else {
			die($file." doesn't exist.");
			return false;
		}
	}
 
	public function addUserToGroup($username = '', $group = '') {
		if (!empty($username) && !empty($group)) {
			$all = $this -> read();
			if (isset($all[$group])) {
				if (!in_array($username, $all[$group])) {
					$all[$group][] = $username;
				}
			} else {
				$all[$group][] = $username;
			}
			$this -> write($all);
		} else {
			return false;
		}
	}
 
	public function deleteUserFromGroup($username = '', $group = '') {
		$all = $this -> read();
		if (array_key_exists($group, $all)) {
			$user_index = array_search($username, $all[$group]);
			if ($user_index !== false) {
				unset($all[$group][$user_index]);
				if (count($all[$group]) == 0) {
					unset($all[$group]);
				}
				$this -> write($all);
			}
		} else {
			return false;
		}
	}
 
}

使用方法:

初始化:

$passwdHandler = new Htpasswd('/home/myuser/.htpasswd');
$groupHandler = new Htgroup('/home/myuser/.htgroup');

创建和删除用户:

// Add a user with name 'user1' and password 'I prefer to use passphrase rather than password.' if it doesn't exist in .htpasswd.
$passwdHandler -> addUser('user1', 'I prefer to use passphrase rather than password.');
// Delete the user 'user1' if it exists in .htpasswd.
$passwdHandler -> deleteUser('user1');

检测某用户是否存在于.htpasswd中:

// Check if user 'user1' exists in .htpasswd.
if ($passwdHandler -> doesUserExist('user1')) {
	// User 'user1' exists.
}

把某用户加入某组:

// Add user 'user1' to group 'admin' in .htgroup. Group will be automatically created if it doesn't exist.
$groupHandler -> addUserToGroup('user1', 'admin');

从某组中删除某用户:

// Delete user 'user1' from group 'admin' in .htgroup. Group will be automatically removed if it doesn't contain any users.
$groupHandler -> deleteUserFromGroup('user1', 'admin');

欢迎测试。

Posted in 花荣在写PHP代码 | Leave a comment

mysql中的线程threads简介

mysql中的线程threads简介

mysql使用多线程threads来做各种工作,比如mysql_install_db, flush myisam tables, replication, TCP/IP sockets,等等。
下面简单介绍几种线程:

1. main thread.

2. bootstrap thread
只用于mysql_install_db。
3. maintenance thread
occasionally flushes MyISAM tables to Disk.
Innodb也有自己的maintenance thread.
4. handle TCP/IP sockets threads

5. handle shared memory/named pipes connections threads
for Windows ONLY.
6. signal handler thread

7. shutdown thread
shutdown thread 由signal handler thread创建,在mysqld关闭的时候,它通过close_connections()函数关闭所有的连接。

8. delayed thread
用于MyISAM的delayed inserts.

9. two slave threads
用于replication, 其中一个线程连接到master并获取数据(IO线程), 另一个线程从relay log中读取到sql语句并执行(SQL线程)。

Posted in mysql | Leave a comment