测试环境:rhel3.5,drbd 8.0.7,mysql5.0.51-rc-log

1、首先从www.drbd.org下载了源代码包(我下载的8.0.7版本的包)

2、检查主机上面有没有linux的内核源代码,如果没有,需要找到相对应版本的源代码包安装上去。

3、开始安装drbd:

1) 解压:tar -zxvf drbd-8.0.7.tar.gz

2) 进入drbd源码目录,根据kernel源码位置来编译drbd:

make KDIR=/usr/src/kernel/ (如果没有更改过内核,可以直接运行make,编译程序会到/lib/module里面去自己根据相关配置寻找到kernel源码)

make install

如果没有报错,应该基本install好了,检查是否生成了相应的文件:/etc/drbd.conf ; /etc/init.d/drbd ; 以及./drbd/drbd.ko

同时系统应该至少多了以下两个命令:drbdadm和drbdsetup

不要删除此源码目录,后面还会用到里面的./scripts/drbd.conf 和 ./drbd/drbd.ko

4、现在可以加载安装drbd模块了

insmod drbd.ko 或者 modprobe drbd

通过lsmod检查是否已经成功

#lsmod |grep drbd

如果有,则表示成功了

5、更改drbd配置文件:

/etc/drbd.conf

[root@mysql1 ha.d]# cat /etc/drbd.conf

on mysql1 {
device /dev/drbd0;
disk /dev/i2o/hda9;
address 10.0.65.45:8888;
flexible-meta-disk internal;
}

on mysql2 {
device /dev/drbd0;
disk /dev/sde2;
address 10.0.65.106:8888;
meta-disk internal;
}

6、primary node设置:

1) 创建matadata:

#drbdadm create-md all

2) 启动drbd:

#/etc/init.d/drbd start

3) 设置为主节点:

#drbdadm — –overwrite-data-of-peer primary all

4) 在新设备上面创建文件系统

#mkfs.ext3 /dev/drbd0

5) 将文件系统mount上

#mkdir /drbddata

#mount /dev/drbd0 /drbddata

7、secondary node设置:

1) 创建matadata:

#drbdadm create-md all

2) 启动drbd:

#/etc/init.d/drbd start

注:这里不要创建文件系统(因为这些信息都会从主节点同步过来的)。

8、primary和secondary节点都配置完并且都启动后,开始检查配置是否成功

1) 检查进程:

a) primary :
[root@mysql1 /]# ps -auxf |grep drbd
Warning: bad syntax, perhaps a bogus ‘-’? See /usr/share/doc/procps-3.2.3/FAQ
root 5454 0.0 0.0 3744 672 pts/0 S+ 17:36 0:00 \_ grep drbd
root 5389 0.6 0.0 0 0 ? S 17:16 0:07 [drbd0_worker]
root 5403 1.1 0.0 0 0 ? S 17:16 0:14 [drbd0_receiver]
root 5448 0.3 0.0 0 0 ? S 17:35 0:00 [drbd0_asender]

b) secondary:
root@mysql2:/>ps -auxf |grep drbd
Warning: bad syntax, perhaps a bogus ‘-’? See /usr/share/doc/procps-3.2.3/FAQ
root 5272 0.0 0.0 4752 640 pts/1 S+ 16:27 0:00 \_ grep drbd
root 5168 0.0 0.0 0 0 ? S 16:07 0:00 [drbd0_worker]
root 5182 2.3 0.0 0 0 ? S 16:07 0:29 [drbd0_receiver]
root 5270 1.9 0.0 0 0 ? S 16:25 0:03 [drbd0_asender]

可以看到两个节点的进程都起来了,每个drbd设备会有三个进程:drbd0_worker是drbd0的主要进城,drbd0_asender是 primary上drbd0的数据发送进程,drbd0_receiver是secondary上drbd0的数据接收进程。

2) 查看/dev/drbd文件的输出:

[root@mysql1 /]# cat /proc/drbd
version: 8.0.7 (api:86/proto:86)
GIT-hash: cf14288833afe95db396075f8530a5960d29e498 build by root@mysql1, 2008-03-01 17:02:58
0: cs:SyncSource st:Primary/Secondary ds:UpToDate/Inconsistent C r—
ns:6575584 nr:36 dw:289636 dr:6298278 al:142 bm:515 lo:1 pe:227 ua:30 ap:0
[====>...............] sync’ed: 21.8% (9336/11932)M
finish: 0:52:36 speed: 3,024 (4,176) K/sec
resync: used:1/31 hits:454805 misses:514 starving:0 dirty:0 changed:514
act_log: used:0/257 hits:72258 misses:154 starving:0 dirty:12 changed:142

root@mysql2:/>cat /proc/drbd
version: 8.0.7 (api:86/proto:86)
GIT-hash: cf14288833afe95db396075f8530a5960d29e498 build by root@mysql2, 2008-02-29 21:21:46
0: cs:SyncTarget st:Secondary/Primary ds:Inconsistent/UpToDate C r—
ns:36 nr:5550548 dw:5550552 dr:89 al:2 bm:326 lo:2 pe:97 ua:1 ap:0
[==>.................] sync’ed: 13.5% (10330/11932)M
finish: 0:28:37 speed: 6,148 (4,248) K/sec
resync: used:2/31 hits:391148 misses:451 starving:0 dirty:0 changed:451
act_log: used:0/257 hits:7 misses:2 starving:0 dirty:0 changed:2

输出文件上面最开始是drbd的版本信息,然后就是数据同步的一些状态信息,从mysql的文档上介绍了每一个状态的意思如下:

cs — connection state
st — node state (local/remote)
ld — local data consistency
ds — data consistency
ns — network send
nr — network receive
dw — disk write
dr — disk read
pe — pending (waiting for ack)
ua — unack’d (still need to send ack)
al — access log write count

3) 更进一步验证数据是否同步正确了:

a) 在mysql1上将该文件系统umount,然后执行drbdadm secondary all,改成secondary模式

[root@mysql1 /]# umount /drbddata

[root@mysql1 /]# drbdadm secondary all

b) 在原mysql2 执行drbdadm primary all 改成primary模式,再mount文件系统

root@mysql2:/>drbdadm primary all

root@mysql2:/>mount /dev/drbd0 /drbddata

检查之前在mysql1下写入的文件是否已经完全同步到mysql2下面,经验证,数据已经同步好了

4) 最后连同mysql一起手工测试一次切换:

a) 主节点mysql1下关闭mysql,释放资源,将资源切换成secondary模式:

[root@mysql1 ha.d]# mysqladmin -u root shutdown
[root@mysql1 ha.d]# umount /drbddata
[root@mysql1 ha.d]# drbdadm secondary all

b) 次节点mysql2下获取资源,mount上,切换成primary模式,并启动mysql:

root@mysql2:/root/mysql-5.0.51a>drbdadm primary all
root@mysql2:/root/mysql-5.0.51a>mount /dev/drbd0 /drbddata
root@mysql2:/usr/local/mysql/bin>./mysqld_safe –user=mysql &
[1] 27900
root@mysql2:/usr/local/mysql/bin>Starting mysqld daemon with databases from /drbddata/mysqldata
root@mysql2:/usr/local/mysql/bin>
root@mysql2:/usr/local/mysql/bin>
root@mysql2:/usr/local/mysql/bin>tail -f /drbddata/mysqldata/mysql2.err
080303 13:53:25 mysqld started
080303 13:53:26 InnoDB: Started; log sequence number 0 43656
080303 13:53:26 [Note] /usr/local/mysql/libexec/mysqld: ready for connections.
Version: ‘5.0.51a-log’ socket: ‘/usr/local/mysql/sock/mysql.sock’ port: 3306 Source distribution

c) 登入数据库中检查数据,这里我同时在新的主节点上面测试了写,以便在后面切换回主节点后检查数据是否也正常:

root@mysql2:/usr/local/mysql/bin>mysql -u root
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 5.0.51a-log

Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the buffer.

mysql> show databases;
+——————–+
| Database |
+——————–+
| information_schema |
| mysql |
| test |
+——————–+
3 rows in set (0.03 sec)

mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+—————-+
| Tables_in_test |
+—————-+
| t1 |
| t2 |
| t3 |
+—————-+
3 rows in set (0.00 sec)

mysql> create table t4(id int);
Query OK, 0 rows affected (0.07 sec)

mysql> exit
Bye
root@mysql2:/usr/local/mysql/bin>

d) 再通过之前相同的切换步骤切换回各自原来的模式,启动主节点的mysql,并检查数据:

[root@mysql1 ha.d]# drbdadm primary all

[root@mysql1 ha.d]# mount /dev/drbd0 /drbddata

[root@mysql1 ha.d]# mysqld_safe –user=mysql &
[1] 8451
[root@mysql1 ha.d]# Starting mysqld daemon with databases from /drbddata/mysqldata

[root@mysql1 ha.d]#
[root@mysql1 ha.d]#
[root@mysql1 ha.d]#
[root@mysql1 ha.d]#
[root@mysql1 ha.d]# mysql -uroot
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 5.0.51a-log

Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the buffer.

mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+—————-+
| Tables_in_test |
+—————-+
| t1 |
| t2 |
| t3 |
| t4 |
+—————-+
4 rows in set (0.00 sec)

mysql> insert into t4 values(111);
Query OK, 1 row affected (0.01 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t4;
+——+
| id |
+——+
| 111 |
+——+
1 row in set (0.00 sec)

几个注意点:

1、除了primary节点的文件系统是手工创建的之外,其他的所有secondary节点的文件系统都是通过同步完成的,两边的设备大小好像并不要求完全一样的大小,在我测试的过程中,两边用于drbd设备的分区大小相差很大,但好像并没有出现错误,从drbd相关文档上看到这个并不会导致问题。但是如果主节点比备节点大,而且用的空间也超出了备节点空间大小会有问题,具体会怎样还没有测试到。

2、在mount drbd的设备之前,该节点必须已经设置为primary模式,而且如果一边没有umount,另一边是无法mount上的,直接mount会报如下错误:

root@mysql2:/>mount /dev/drbd0 /drbddata
mount: block device /dev/drbd0 is write-protected, mounting read-only

也就是说,在同步的过程中,只有一个节点的数据可见,也就是不能通过我们人直接简单的查看数据文件等方式之间验证数据是否正常。不过看文档说好像可以通过手动设置一些信息来查看是否正常(You can manually set this information for a number of reasons, including when you want to check the physical status of the secondary device (since you cannot mount a DRBD device in primary mode), or when you are temporarily moving the responsibility of keeping the data in check to a different machine (for example, during an upgrade or physical move of the normal primary node). )。这里的内容等后面再详细研究一下。

,

测试环境:

Type OS Mysql

Master rhel3.5 5.1.22-rc-log

Slave1 rhel3.5 5.1.22-rc-log

Slave2 rhel4.4 5.1.22-rc-log

切换测试过程是:1) Master down

2) Slave1 切换成新的Master

3) Slave2 更换Master配置为原Slave1

详细过程如下:

1、从slave(slave1)群众中选定一个slave,准备钱换成master;

2、检查slave1的复制状态:

mysql> SHOW PROCESSLIST ;
+—-+————-+———–+——+———+————+———————————————————————–+——————+
| Id | User | Host | db | Command | Time | State | Info |
+—-+————-+———–+——+———+————+———————————————————————–+——————+
| 1 | system user | | NULL | Connect | 54733 | Waiting for master to send event | NULL |
| 2 | system user | | NULL | Connect | 4294965772 | Has read all relay log; waiting for the slave I/O thread to update it | NULL |
| 8 | root | localhost | NULL | Query | 0 | NULL | SHOW PROCESSLIST |
+—-+————-+———–+——+———+————+———————————————————————–+——————+

这里主要是检测Slave1是否已经应用完从Master读取过来的在relay log中的操作,如果未应用完不能stop slave,否则数据肯定会有丢失。

3、停止slave1的slave进程,并reset称master:

mysql> STOP SLAVE ;
Query OK, 0 rows affected (0.00 sec)

mysql> RESET MASTER;
Query OK, 0 rows affected, 8 warnings (0.02 sec)

4、将slave 群中的其他slave(slave2)的Master切换成新的master(由原slave1reset成的):

1) 停slave进程:
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
2) 更换master:
mysql> CHANGE MASTER TO
-> MASTER_HOST=’10.0.65.106′,
-> MASTER_USER=’repl’,
-> MASTER_PASSWORD=’slavepass’
-> ;
Query OK, 0 rows affected (0.00 sec)
3) 开启slave:
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

5、检查slave的状态:

mysql> show slave status \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.65.106
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 106
Relay_Log_File: oindeve-relay-bin.000002
Relay_Log_Pos: 251
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 106
Relay_Log_Space: 408
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
1 row in set (0.00 sec)

6、最后变换实际数据监测新的复制是否能成功进行:

1) 在新的Master创建测试表:

mysql> create table t3 as select * from test;
Query OK, 100003 rows affected (0.11 sec)
Records: 100003 Duplicates: 0 Warnings: 0

mysql> show tables;
+—————-+
| Tables_in_test |
+—————-+
| t1 |
| t2 |
| t3 |
| test |
+—————-+
4 rows in set (0.00 sec)

mysql> select count(*) from t3;
+———-+
| count(*) |
+———-+
| 100003 |
+———-+
1 row in set (0.00 sec)
2) 在slave2上面看是否已经复制过去:

mysql> show tables;
+—————-+
| Tables_in_test |
+—————-+
| t1 |
| t2 |
| t3 |
| test |
+—————-+
4 rows in set (0.00 sec)

mysql> select count(*) from t3;
+———-+
| count(*) |
+———-+
| 100003 |
+———-+
1 row in set (0.00 sec)

7、到此确认复制正常,master切换完成。

注:整个切换测试过程时间较短,大家从每一步操作后面反馈的执行时间也可以看出,所需要的操作步骤也不太多。但是此测试并不是数据库整体环境在提供服务的压力环境下所测试进行的,该过程数据库整体环境较为空闲,所以目前还不敢确保在压力环境下也会如此的顺利,等后面还会找机会在有应用压力的情况下再测试。

, ,

做为一个开发DBA,要保障数据库应用的质量,很重要的一点就是必须在项目的每一个阶段都参与到项目组的工作中。下面就各个阶段说一下我个人认为该做的一些工作吧:

一、需求阶段

要想能在整个项目周期中能够更早的了解项目所涉及到的内容,把握项目范围,而在后面的工作中取得更多的主动权使质量能够得到有效的控制,开发DBA就需要在需求被确认之前就开始参与。

1、项目孕育阶段:

在公司目前的项目流程中,需求阶段实际上是在项目还没有确认是否要做的时候就开始了。在这个时候,一般情况下PD(或者运营)部门可能不会和我们沟通,而是和技术部门的RA或者架构师们沟通,描绘对该项目的一个大概的轮廓和需求,让技术部的同事提出一些对该项目的看法。一个项目最后是否需要做也正是在这个阶段来确定的。所以,这个时候如果RA或者架构对该项目在数据库方面的影响把握的不是很准确的话,可能就会造成后面项目的需求分析和确认的过程中DBA和 PD部门之间可能会出现较多分歧。

要解决这个问题一般只有两种办法:一是通过沟通交流或者培训加强RA和架构对我们数据库的了解和把握能力;二是通过各种途径使我们自己能参与到这个阶段。对于第一种办法,好处是可以减少我们的工作量,而坏处就是架构和RA到底能对数据库方面的影响把握到什么程度是没办法很好地控制的。第二种方法的好处是我们能够完全由我们自己把握到项目对数据库的影响,给出更准确的评估,而坏处一是增加了我们的工作量,再就是比较难获得这个阶段的项目相关信息。考虑到这两种方法各自的优劣,在国际站这边我现在实际上是两者一起使用的。平时常通过沟通交流来加强RA和架构对数据库方面的一些了解,偶尔做一点培训。同时也和他们约定,如果有较大动作(或项目)的时候都提前和我们沟通。然后也加强和pd以及运营部门沟通,多了解一些他们的想法和打算,同时也常和他们聊聊网站哪些地方的内容对数据库影响比较大哪些地方比较小,哪些核心内容的调整会影响较大哪些较小,让他们头脑中有一个大概的轮廓,也和他们约定有什么大动作或者想法的时候提前和我们打声招呼。那么,如何让架构师、RA以及PD和运营真正会提前和我们沟通呢?就要靠我们加强和他们的沟通,加强他们对我们的信任程度。我们这边也时常和他们沟通,主动去了解一些他们最近的想法,了解他们的一些困惑。而且通过沟通还可以消除运营或更前端的需求部门认为我们不够配合的误会。其实总的一点来说就是像大师所说的,增强他们对我们的信任感,让他们在有什么想法或者需求的时候就主动想和我们聊聊征求一下我们的意见,这才是最根本的目的和我们的目标。要达到这个目标,最基本也是最有效的方法就是有效的沟通,通过实际行动尽我们的能力去帮助他们解决性能上面的问题,评估项目的影响和风险。在刚开始工作的时候Jacky就和我说过,开发DBA的工作中有一项非常重要的内容,就是需要和很多不同部门不同角色去沟通,所以,沟通技巧也是我们需要很好掌握的。

2、需求分析和确认阶段:

在项目确定了开始要做的时候,一般都会有一个项目kick off会议,也就是项目启动会议,这个时候一般都会叫上我们DBA参加。会议一般主要是公布一个项目的大概时间计划和项目组成员的组成,这个时候就是一个项目真正的开始了。之后接下来就是非常关键的需求分析工作了。这项工作主要由RA来主导,同时PD(或运营)一起参与进行。这个过程中,一般来说RA都会常征求架构师的意见,有时候也会征求我们DBA的意见(主要是RA以他们对数据库的把握能力来判断是否需要我们参与需求分析过程)。一般项目在需求分析过程中都会有两次需求确认会议:商业需求确认会和最终需求确认会,也就是我们常说的BRD确认会合FRD确认会。在项目流程中,我们的开发DBA都是需要参与到这两次会议的。但是有些时候,确认会议上只是向项目开发人员,架构师以及DBA介绍一些商业需求以及在系统中大概的实现逻辑,到这时候,大部分需求其实都已经定下来了。所以,有些时候如果在项目启动前我们没有获取到关于项目足够的信息,在需求分析的过程中又没有任何的情况下,可能会遇到在这个时候才发现该项目某些地方对数据库影响很大,风险较高。而这个时候才提出,很可能就会造成之前的需求分析工作很多都需要返工重新分析重新设计,甚至某些需求根本就无法实现,造成整个项目进度延后,严重的时候还会造成和PD等部门之间误会。所以,在项目启动之后需求确认之前,一定要常和RA沟通,跟进项目进度和相关细节。有任何问题疑问都要尽早提出,表名观点。对于比较重要的问题,一定要和RA以及PD等部门的人坐在一起当面沟通,说明问题的所在,并给出我们的建议(如果有)。

二、开发阶段

1、系统设计阶段

当需求完全确定下来后,开发人员就会开始进行系统设计的工作了。一般来说开发人员都会首先设计数据库schema(如果有建新表的需求),然后才是程序的设计。这个时候我们的重点沟通对象就从RA转移到开发工程师了。有些开发工程师可能会主动来找我们,沟通schema设计方面的一些内容,而有些开发工程师可能就不会和我们沟通,而是自己直接自己完成schema设计,然后就交给我们直接要求建表了。而往往那些不会主动找我们的开发工程师大多都是一些新手,更容易出问题,相对来说一些较为资深和能力较强的开发工程师反而都会和我们沟通一下,即使是一些很简单的表,也至少会先和我们说一下。所以,在项目启动会议的时候我们就该注意一下项目中负责开发的工程师情况。通过我们对他们的了解来判断对哪些人需要多花一点精力去跟进,哪些人是可以放心少花一些精力去跟进。当交道打的多了以后,肯定对每个人的工作习惯,做事态度等都有一个大致了解。

实际上不仅仅表结构的设计我们需要关注,有些时候他们程序的实现方法也需要了解一些,尤其是在实现一些我们认为比较重要或影响比较大的功能点需求的时候,我们最好是去了解一下他们是怎么来设计实现的。不同的实现会给数据库带来不一样的压力,一个好的实现所需要的数据库资源和一个较差的设计实现相比,有些时候的差别甚至都不是一个数量级的。当遇到较差的实现的时候,我们可以适当的提出一些我们的建议,如果遇到困难,也可以向架构师来寻求帮助。这也是我们要求开发DBA最好要有一定开发经验,对开发有一定的了解的原因之一。因为如果完全不懂开发,可能就无法在设计实现上面发现问题了。而且在这个过程中,通过不断的去和他们沟通,也可以让我们自己学习到更多的系统设计方面的知识和并积累相关经验,为今后更好的处理问题以及对项目影响的把握是有很大帮助的。而且在系统设计层面的关注,对于自身能力的提高也是非常有帮助的。对于一个DBA来说,最关注的就是系统的质量,系统的性能。而对于一个开发人员或者项目经理来说,可能更关注如何快速的实现需求,完成一个可交付使用的产品。一个DBA关注较多的系统设计和架构方面的内容以后,才能有更开阔的视野,才可能从更高的层面来掌控项目的质量和性能。不论是对于自身的能力还是以后的发展,不论是开发DBA还是产品DBA抑或是以后转型架构师,都会有很大的帮助。

2、开发编码阶段

当系统设计结束后,开发工程师就开始进行编码工作了。在这个过程中,有些开发工程师可能会随时主动的将自己认为比较重要或把握不准是否有性能问题的sql 发给我们,征求我们的建议,但有些开发工程师是不会的,需求我们主动去找他们要。可能大家会说,我们可以等项目开发完成,提交测试的时候控制他们测试库的变更的时候让他们一次性的提交sql给我们,然后我们再集中review所有的sql。在项目周期不长范围较小,同时并行的项目也比较少的时候这样做确实是没有太多问题的,但是一旦同时有多个项目并行,或者项目比较大的话,就会出现问题了。最大的一个问题就是sql review的时间问题。如果一次性提交了很多的sql过来,很可能最后sql review过程就会成为项目的瓶颈,我们自己也会压力比较大,没办法尽可能的对一些sql进行较好的优化。再一个就是有些在review过程中发现的有些问题比较严重的sql的调整可能涉及到程序逻辑的改动,如果改动涉及到程序的变动比较大的话,开发工程师的返工工作量就会较大,不是很情愿配合,也会影响项目的进度。像我这边国际站,并行项目非常多,有些项目周期拉的也比较长,我一般都是在项目边开发的时候就边和他们沟通,即使有些时候并不是正式的让他们提交sql,也会和他们沟通一下他们有没有遇到数据库方面的问题或者困惑。经常这样和他们沟通后,很多人慢慢就会有了一个习惯,只要是自己觉得稍微有点拿捏不准的sql,都会直接拿来问我一下。虽然这个时候他们的判断可能并不一定准确,但是对于稍微较为复杂的sql他们肯定都会先发给我们看看,如果 sql有什么问题我们就能马上开始优化,或者调整程序实现逻辑来解决掉,而不用等到所有代码都开发好了才开始做这件事情。这样在项目最后的sql review的工作实际上是在项目进行过程中就已经在慢慢进行了,我们自己最后的review工作时间也就更宽裕一些了,同时也可以让他们养成一个好的习惯。当然,即使是这种方法,我们在最后也应该让他们整理一遍用到的所有sql并发给我们。

三、测试和最后发布阶段

一个项目进入测试阶段后也是现在项目流程中所规定的开始review sql的时间,如果在之前的开发阶段我们就已经做了较多的工作,那么在这个阶段的时候可能就会比较容易控制了,但是如果之前没有做什么工作,所有sql都在这个时候才开始review,就需要把握好review的进度了。同时,在测试过程中,可能会因为修改某些bug,开发工程师改写某些sql,而这也是开发工程师最容易忘记将sql提交给我们的时候。所以在测试阶段我们在review开发工程师之前提交的所有sql的时候,同时也要不断的和测试沟通 bug出现情况,和开发沟通有没有改动过什么sql。随时掌握sql的变动,才能随时掌控项目的性能质量。

在最后我们手上应该有一个文件,里面保存着这个项目中新增或者修改的所有sql,因为我们需要根据这份完整的sql文件来完善索引,之前sql没有完全定下来的时候你所创建的索引有些可能到这个时候有些已经不适用了。

项目测试结束了,我们也review完开发工程师给我们的sql了,这个时候我们最好再加一道保险,那就是从发布人员那边了解一下发布的文件列表,看看有没有我们没有看过的sql mapping文件的发布。像现在,国际站这边我就和配置管理员约定好了,项目发布的时候,她记下发布中需要更新哪些sql mapping文件并告诉我,随便什么方式都行,不管是mail还是贸易通都可以,这样我至少可以控制不要某个mapping文件里面的sql有变动我这边都完全不知道。当然这个工作本身并不是配置管理员的本职工作,她是否愿意帮这个忙就得靠我们自己了,呵呵。

四、发布后阶段

项目发布了,RA可能开始了一个新项目的需求分析,开发工程师可能又开始做其他项目去了,这个时候我们并不能马上就完全不去理会这个项目了,因为这个时候才是真正考验我们之前所做的工作成果的开始。我们需要多看看产品数据库上面整体压力情况,看看这个项目所涉及到的那些sql有没有冒出来成为top sql。如果一切正常,那至少说明我们之前的工作没有太多问题。如果发现里面有sql冒出来了,应该马上分析为什么会冒出来?执行计划和我们当初预想的是否一致?执行频率是否正常?之前准备的索引是否合理?然后着手优化,解决掉冒出来的sql。这个时候的优化工作必须要谨慎,对于已有系统上对象的任何改动都需要三思:是否会引起某些sql语句执行计划的改变,是否会让某些对象失效等等。

有些项目发布一段时间后会有一个项目总结会,总结项目过程中的一些经验教训,这个时候我们也应该从我们的角度提出对项目的看法,不管是好的还是不好的,这样做同时也可以让大家对数据库有更多一点的了解,更多一点的关注。

其实总的来说,要想控制好一个项目中数据库应用的质量,就必须让自己在项目的整个阶段随时了解项目当前情况,分析清楚状况,让自己处于主动的状态处理各种事情,而不是仅仅在最后看看开发工程师写出并提交给我们的sql,这只是最我们最基本的工作之一而已。

,

上个周末恐怕是我过的最郁闷的一个周末了。

上周五晚上为了将电脑上空余的一部分空间分出来给Linux用,就用pqmagic调整原有分区的大小,将里面一个存放数据的盘区分出一部分空闲空间。调整过程一切正常,没有出现任何错误。机器重启之后为了将最后的两个较小的空闲分区和到一块儿,就想直接从Windows的磁盘管理里面将两个连续的分区删除掉应该就可以了,删除最后一个分区的时候也很正常,可当删除倒数第二个分区的时候却让我及其郁闷,他没有和最后一个未分区空间合并,而直接和他前面的一个分区合并,也就是前面的分区也被自动删除成为了未分区磁盘空间。这下就搞大了,那里面可是存放着我整个电脑中最重要的数据啊。

Read the rest of this entry »

通过前面关于索引扫描还是全表扫描(Index Scan Or Full Table Scan)?的讨论又发现了自己基础概念不清晰的一个大问题:
DB block gets,Consistent gets,Physical reads与Logical reads各自具体表示的是什么以及之间的的关系到底是怎样。

官方在线文档基本的定义为如下:
DB block gets:the number of accesses to the current image of a block
Consistent gets:the number of accesses to a read-consistent image of a block
Physical reads:the number of blocks read from disk

通过官方的简要解释加上对fenng和旺旺的请教以及网上搜索了一些资料,终于加深了一些理解:

Read the rest of this entry »

,