June 24, 2004
Statspack之十-调整STATSPACK的收集门限
作者:eygle
出处:http://blog.eygle.com
Statspack有两种类型的收集选项:
级别(level):控制收集数据的类型
门限(threshold):设置收集的数据的阈值。
1.级别(level)
Statspack共有三种快照级别,默认值是5
a.level 0: 一般性能统计。包括等待事件、系统事件、系统统计、回滚段统计、行缓存、SGA、会话、锁、缓冲池统计等等。
b.level 5: 增加SQL语句。除了包括level0的所有内容,还包括SQL语句的收集,收集结果记录在stats$sql_summary中。
c.level 10: 增加子锁存统计。包括level5的所有内容。并且还会将附加的子锁存存入stats$lathc_children中。在使用这个级别时需要慎重,建议在Oracle support的指导下进行。
可以通过statspack包修改缺省的级别设置
|
SQL>execute statspack.snap(i_snap_level=>0,i_modify_parameter=>’true’);
|
通过这样的设置,以后的收集级别都将是0级。
如果你只是想本次改变收集级别,可以忽略i_modify_parameter参数。
|
SQL>execute statspack.snap(i_snap_level=>10);
|
2.快照门限
快照门限只应用于stats$sql_summary表中获取的SQL语句。
因为每一个快照都会收集很多数据,每一行都代表获取快照时数据库中的一个SQL语句,所以stats$sql_summary很快就会成为Statspack中最大的表。
门限存储在stats$statspack_parameter表中。让我们了结一下各种门限:
a. executions_th这是SQL语句执行的数量(默认值是100)
b. disk_reads_tn这是SQL语句执行的磁盘读入数量(默认值是1000)
c. parse_calls_th这是SQL语句执行的解析调用的数量(默认值是1000)
d. buffer_gets_th这是SQL语句执行的缓冲区获取的数量(默认值是10000)
任何一个门限值超过以上参数就会产生一条记录。
通过调用statspack.modify_statspack_parameter函数我们可以改变门限的默认值。
例如:
|
SQL>execute statspack.modify_statspack_parameter(i_buffer_gets_th=>100000,i_disk_reads_th=>100000;
|
Posted by eygle at 10:18 PM | Comments (1)
Statspack之九-其它重要脚本
作者:eygle
出处:http://blog.eygle.com
1.通过导出保存及共享数据
在诊断系统问题时,可能需要向专业人士提供原始数据,这时我们可以导出Statspack表数据,其中我们可能用到:spuexp.par
其内容主要为:
|
file=spuexp.dmp log=spuexp.log compress=y grants=y indexes=y rows=y constraints=y owner=PERFSTAT consistent=y
|
我们可以导出如下:
|
exp userid=perfstat/my_perfstat_password parfile=spuexp.par
|
2.删除数据
spdrop.sql在执行时主要调用两个脚本: spdtab.sql 、spdusr.sql
前者删除表及同义词等数据,后者删除用户
3.Oracle92中新增加的脚本
1.用于升级statspack对象的脚本,这些脚本需要以具有SYSDBA权限的用户运行, 升级前请先备份存在的Schema数据:
SPUP90.SQL: 用于升级9.0版本的模式至9.2版本。
SPUP817.SQL: 如果从Statspack 8.1.7升级,需要运行这个脚本
SPUP816.SQL: 从Statspack 8.1.6升级,需要运行这个脚本,然后运行SPUP817.SQL.2.sprepsql.sql 用于根据给定的SQL Hash值生成SQL报告
Posted by eygle at 10:17 PM | Comments (0)
Statspack之八-删除历史数据
作者:eygle
出处:http://blog.eygle.com
删除stats$snapshot数据表中的相应数据,其他表中的数据会相应的级连删除:
|
SQL> select max(snap_id) from stats$snapshot;
MAX(SNAP_ID) ------------ 166
SQL> delete from stats$snapshot where snap_id < = 166;
143 rows deleted |
你可以更改snap_id的范围以保留你需要的数据。
在以上删除过程中,你可以看到所有相关的表都被锁定。
|
SQL> select a.object_id,a.oracle_username ,b.object_name
OBJECT_ID ORACLE_USERNAMEOBJECT_NAME ------------------------------------- --------------------------------------------------------- 156 PERFSTATSNAP$ 39700 PERFSTATSTATS$LIBRARYCACHE 39706 PERFSTATSTATS$ROLLSTAT 39712 PERFSTATSTATS$SGA 39754 PERFSTATSTATS$PARAMETER 39745 PERFSTATSTATS$SQL_STATISTICS 39739 PERFSTATSTATS$SQL_SUMMARY 39736 PERFSTATSTATS$ENQUEUESTAT 39733 PERFSTATSTATS$WAITSTAT 39730 PERFSTATSTATS$BG_EVENT_SUMMARY 39724 PERFSTATSTATS$SYSTEM_EVENT 39718 PERFSTATSTATS$SYSSTAT 39715 PERFSTATSTATS$SGASTAT 39709 PERFSTATSTATS$ROWCACHE_SUMMARY 39703 PERFSTATSTATS$BUFFER_POOL_STATISTICS 39697 PERFSTATSTATS$LATCH_MISSES_SUMMARY 39679 PERFSTATSTATS$SNAPSHOT 39682 PERFSTATSTATS$FILESTATXS 39688 PERFSTATSTATS$LATCH 174 PERFSTATJOB$
20 rows selected |
Oracle还提供了系统脚本用于Truncate这些统计信息表,这个脚本名字是: sptrunc.sql (8i、9i都相同)
该脚本主要内容如下,里面看到的就是statspack相关的所有系统表:
|
truncate table STATS$FILESTATXS; truncate table STATS$LATCH; truncate table STATS$LATCH_CHILDREN; truncate table STATS$LATCH_MISSES_SUMMARY; truncate table STATS$LATCH_PARENT; truncate table STATS$LIBRARYCACHE; truncate table STATS$BUFFER_POOL_STATISTICS; truncate table STATS$ROLLSTAT; truncate table STATS$ROWCACHE_SUMMARY; truncate table STATS$SGA; truncate table STATS$SGASTAT; truncate table STATS$SYSSTAT; truncate table STATS$SESSTAT; truncate table STATS$SYSTEM_EVENT; truncate table STATS$SESSION_EVENT; truncate table STATS$BG_EVENT_SUMMARY; truncate table STATS$WAITSTAT; truncate table STATS$ENQUEUESTAT; truncate table STATS$SQL_SUMMARY; truncate table STATS$SQL_STATISTICS; truncate table STATS$SQLTEXT; truncate table STATS$PARAMETER;
delete from STATS$SNAPSHOT; delete from STATS$DATABASE_INSTANCE;
commit; |
如果采样了大量的数据,直接Delete是非常缓慢的,可以考虑使用上述SQL截断所有表。
Posted by eygle at 10:15 PM | Comments (0)
Statspack之三-安装statspack
作者:eygle
出处:http://blog.eygle.com
安装Statspack需要用internal身份登陆,或者拥有SYSDBA(connect / as sysdba)权限的用户登陆。
需要在本地安装或者通过telnet登陆到服务器。
在Oracle8.1.6版本中运行statscre.sql;在Oracle8.1.7版本中运行spcreate.sql。
首先登陆到数据库,最好转到$ORACLE_HOME/RDBMS/ADMIN目录,这样我们执行脚本就可以方便些。
|
D:\oracle\ora81\RDBMS\ADMIN>sqlplus internal SQL*Plus: Release 8.1.7.0.0 - Production on 星期二 12月 3 16:54:53 2002 (c) Copyright 2000 Oracle Corporation.All rights reserved.
请输入口令:
连接到: Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production With the Partitioning option JServer Release 8.1.7.0.0 - Production
SQL> select instance_name,host_name,version,startup_time from v$instance;
INSTANCE_NAMEHOST_NAME VERSIONSTARTUP_TIME ---------------------------------------------------------------- eygleAM-SERVER 8.1.7.0.022-11月-02
SQL>
|
注:在Oracle9i中,不存在internal用户,可以使用sys用户以sysdba身份连接:
|
D:\oracle\ora92\rdbms\admin>sqlplus "/ as sysdba" SQL*Plus: Release 9.2.0.3.0 - Production on 星期四 7月 10 19:18:54 2003 Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
连接到: Oracle9i Enterprise Edition Release 9.2.0.3.0 - Production With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options JServer Release 9.2.0.3.0 - Production
SQL> |
检查数据文件路径及磁盘空间,以决定创建数据文件的位置:
|
SQL> select file_name from dba_data_files; FILE_NAME -------------------------------------------------------------------------------- D:\ORACLE\ORADATA\EYGLE\SYSTEM01.DBF D:\ORACLE\ORADATA\EYGLE\TEMP01.DBF …… D:\ORACLE\ORADATA\EYGLE\HH_AM01.ORA
已选择24行。
SQL> |
创建存储数据的表空间,如果采样间隔较短,周期较长,打算长期使用,那么你可能需要一个大一点的表空间,
如果每个半个小时采样一次,连续采样一周,数据量是很大的。本例创建一个500M的测试表空间。
注意:这里创建的表空间不能太小,如果太小创建对象会失败,至少需要建立100M表空间,如果打算
长期使用,可以建立稍大的表空间,本例创建500M LMT表空间。
|
SQL> create tablespace perfstat 2datafile 'd:\oracle\oradata\eygle\perfstat.dbf' 3size 500M 4extent management local;
表空间已创建。 SQL> |
检查是否存在安装所需要的脚本文件(对于不同的版本,脚本有所不同)
|
E:\Oracle\ora92\rdbms\admin>dir /w sp* 驱动器 E 中的卷没有标签。 卷的序列号是 ACC3-4340 E:\Oracle\ora92\rdbms\admin 的目录
spauto.sqlspcpkg.sqlspcreate.sqlspctab.sqlspcusr.sqlspdoc.txt spdrop.sqlspdtab.sqlspdusr.sqlsppurge.sqlsprepins.sqlspreport.sql sprepsql.sqlsptrunc.sqlspuexp.parspup816.sqlspup817.sqlspup90.sql 18 个文件510,296 字节 0 个目录4,146,565,120 可用字节 |
接下来我们就可以开始安装Statspack了。这期间会提示你输入缺省表空间和临时表空间的位置,输入我们为
perfstat用户创建的表空间和你的临时表空间。
|
SQL> @spcreate . . Specify PERFSTAT user's defaulttablespace 输入 default_tablespace 的值:perfstat Using perfstat for the default tablespace
用户已更改。
用户已更改。
Specify PERFSTAT user's temporary tablespace 输入 temporary_tablespace 的值:temp |
注意:在statspack创建过程中,当提示输入口令时,你可以输入一个明文口令,但是如果输入口令不符
合规范(如123或以数字开头的口令),创建会失败。
输入口令时可以暂时输入:perfstat ,稍后可以更改。
|
... Creating PERFSTAT user ...
Choose the PERFSTAT user's password.
Not specifying a password will result in the installation FAILING Specify PERFSTAT password 输入 perfstat_password 的值: 123 123
PL/SQL 过程已成功完成。
create user perfstat identified by 123 * ERROR 位于第 1 行: ORA-00988: 缺少或无效口令 |
如果安装成功,你可以看到如下的输出信息:
|
…. Creating Package STATSPACK...
程序包已创建。
没有错误。 Creating Package Body STATSPACK...
程序包主体已创建。
没有错误。
NOTE: SPCPKG complete. Please check spcpkg.lis for any errors. |
你可以查看.lis文件查看安装时的错误信息。
|
SQL> host dir *.lis 驱动器 D 中的卷没有标签。 卷的序列号是 5070-5982
D:\oracle\ora81\RDBMS\ADMIN 的目录
2002-12-0317:25204 spcpkg.lis 2002-12-0317:252,276 spctab.lis 2002-12-0317:253,965 spcusr.lis 2002-12-0317:231,187 spdtab.lis 2002-12-0317:24351 spdusr.lis 5 个文件7,983 字节 0 个目录3,965,304,832 可用字节
SQL> host find “ORA-“ *.lis SQL> host find "err" *.lis
---------- SPAUTO.LIS
---------- SPCPKG.LIS SPCPKG complete. Please check spcpkg.lis for any errors.
---------- SPCTAB.LIS SPCTAB complete. Please check spctab.lis for any errors.
---------- SPCUSR.LIS SPCUSR complete. Please check spcusr.lis for any errors.
---------- SPDTAB.LIS |
在UNIX上,你可以通过以下命令查看相应的错误信息
|
$ ls *.lis spauto.lisspcpkg.lisspctab.lisspcusr.lisspdtab.lisspdusr.lis $ grep ORA- *.lis $ grep err *.lis spcpkg.lis:SPCPKG complete. Please check spcpkg.lis for any errors. spctab.lis:SPCTAB complete. Please check spctab.lis for any errors. spcusr.lis:SPCUSR complete. Please check spcusr.lis for any errors. spdtab.lis:SPDTAB complete. Please check spdtab.lis for any errors. spdusr.lis:SPDUSR complete. Please check spdusr.lis for any errors. |
在这一步,如果出现错误,那么你可以运行spdrop.sql脚本来删除这些对象。然后重新运行spcreate.sql来创
建这些对象。运行 SQL*Plus, 以具有SYSDBA 权限的用户登陆:
|
SQL> @spdrop.sql . . . 同义词已丢弃。off;
视图已丢掉。
同义词已丢弃。
视图已丢掉。
同义词已丢弃。
用户已丢弃
NOTE: SPDUSR complete. Please check spdusr.lis for any errors.
SQL> |
Posted by eygle at 10:00 PM | Comments (12)
Statspack之七-移除定时任务
作者:eygle
出处:http://blog.eygle.com
移除一个定时任务,可以如下操作:
|
SQL> select job,log_user,priv_user,last_date,next_date,interval from user_jobs;
JOB LOG_USERLAST_DATENEXT_DATEINTERVAL
---------- ----------------------------------- ------------------------------ ----------- 22 PERFSTAT 2002-12-5:14:33:26 2002-12-5 14:43:00 trunc(SYSDATE+1/144,'MI')
SQL> execute dbms_job.remove('22')
PL/SQL procedure successfully completed
|
当你完成了一个采样报告,你应该及时移除这个job任务,在生产环境中,遗漏一个无人照顾的job是非常危险的,
如果statspack运行一个星期,采样的数据量是非常惊人的。有的生产企业因疏忽而当机!
Posted by eygle at 10:00 PM | Comments (0)
Statspack之六-生成分析报告
作者:eygle
出处:http://blog.eygle.com
Statspack之六-生成分析报告
调用spreport.sql可以生成分析报告:
| SQL> @spreport DB Id DB Name Inst Num Instance Completed Snapshots Snap Snap eygle EYGLE 98 05 12月 2002 04:10 5 .... Specify the Begin and End Snapshot Ids 输入 end_snap 的值: 100 Specify the Report Name Using the report name rep1205.txt |
这样就生成了一个报告,可是如果中间停过机,那么你可能收到以下错误信息:
|
ERROR: Snapshots chosen span an instance shutdown: RESULTS ARE INVALID STATSPACK report for
DB NameDB IdInstanceInst Num ReleaseOPS Host ------------ ----------- ------------ -------- ----------- --- ------------ EYGLE1277924236 eygle1 8.1.7.0.0NOAM-SERVER :ela:=; * ERROR 位于第 4 行: ORA-06550: 第 4 行, 第 17 列: PLS-00103: 出现符号 ";"在需要下列之一时: (-+modnotnull<an identifier> <a double-quoted delimited-identifier><a bind variable>avg countcurrentexistsmaxminpriorsqlstddevsumvarianceexecute foralltimetimestampintervaldate <a string literal with character set specification> <a number><a single-quoted SQL string> 符号 "null" 被替换为 ";" 后继续。 ORA-06550: 第 6 行, 第 16 列: PLS-00103: 出现符号 ";"在需要下列之一时: (-+modnotnull<an identifier> <a double-quoted delimited-identifier><a bind variable>avg countcurrentexistsmaxminpriorsqlstddevsumvarianceexecute foralltimetimestampintervaldate <a stri |
一个statspack的报告不能跨越一次停机,但是之前或之后的连续区间,收集的信息依然有效。你可以选择之前或之后的采样声称report。
Posted by eygle at 10:00 PM | Comments (0)
Statspack之五-规划自动任务
作者:eygle
出处:http://blog.eygle.com
Statspack正确安装以后,我们就可以设置定时任务,开始收集数据了。可以使用spatuo.sql来定义自动任务。
先来看看spauto.sql的关键内容:
|
dbms_job.submit(:jobno, 'statspack.snap;', trunc(sysdate+1/24,'HH'), 'trunc(SYSDATE+1/24,''HH'')', TRUE, :instno);
|
这个job任务定义了收集数据的时间间隔:
一天有24个小时,1440分钟,那么:
| 1/24 | HH每小时一次 |
| 1/48 | MI每半小时一次 |
| 1/144 | MI每十分钟一次 |
| 1/288 | MI每五分钟一次 |
我们可以修改spauto.sql来更改执行间隔,如:
|
dbms_job.submit(:jobno, 'statspack.snap;', trunc(sysdate+1/48,'MI'), 'trunc(SYSDATE+1/48,''MI'')', TRUE, :instno);
|
然后我们执行spauto,这样我们就建立了一个每30分钟执行一次的数据收集计划。你可以查看spauto.lis来获得输出信息:
|
SQL> @spauto PL/SQL procedure successfully completed.
Job number for automated statistics collection for this instance ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Note that this job number is needed when modifying or removing the job:
JOBNO ---------- 28 Job queue process ~~~~~~~~~~~~~~~~~ Below is the current setting of the job_queue_processes init.ora parameter - the value for this parameter must be greater than 0 to use automatic statistics gathering:
NAMETYPEVALUE ------------------------------------ ----------- ------------------------------ job_queue_processesinteger 5
Next scheduled run ~~~~~~~~~~~~~~~~~~ The next scheduled run for this job is:
JOB NEXT_DATE NEXT_SEC ---------- --------- ---------------- 28 15-AUG-0316:00:00 |
关于采样间隔,我们通常建议以1小时为时间间隔,对于有特殊需要的环境,可以设置更短的,如半小时作为采样间隔,
但是不推荐更短。因为statspack的执行本身需要消耗资源,对于繁忙的生产系统,太短的采样对系统的性能会产生较
大的影响(甚至会使statspack的执行出现在采样数据中)。
Posted by eygle at 10:00 PM | Comments (0)
Statspack之四-测试安装好的Statspack
作者:eygle
出处:http://blog.eygle.com
运行statspack.snap可以产生系统快照,运行两次,然后执行spreport.sql就可以生成一个基于两个时间点的报告。
如果一切正常,说明安装成功。
|
SQL>execute statspack.snap PL/SQL procedure successfully completed. SQL>execute statspack.snap PL/SQL procedure successfully completed. SQL>@spreport.sql …
|
可是有可能你会得到以下错误:
|
SQL> exec statspack.snap; BEGIN statspack.snap; END;
* ERROR at line 1: ORA-01401: inserted value too large for column ORA-06512: at "PERFSTAT.STATSPACK", line 978 ORA-06512: at "PERFSTAT.STATSPACK", line 1612 ORA-06512: at "PERFSTAT.STATSPACK", line 71 ORA-06512: at line 1 |
这是Oracle的一个Bug,Bug号1940915。
该Bug自8.1.7.3后修正。
这个问题只会出现在多位的字符集,需要修改spcpkg.sql脚本,$ORACLE_HOME/rdbms/admin/spcpkg.sql,
将"substr" 修改为 "substrb",然后重新运行该脚本。
该脚本错误部分:
|
select l_snap_id , p_dbid , p_instance_number , substr(sql_text,1,31) ...........
|
substr 会将多位的字符, 当作一个byte.substrb 则会当作多个byte。在收集数据时, statpack 会将 top 10
的 sql 前 31 个字节存入数据表中,若在SQL的前31 个字有中文,就会出现此错误。
Posted by eygle at 10:00 PM | Comments (0)
Statspack之二-需要更改的系统参数
作者:eygle
出处:http://blog.eygle.com
为了能够顺利安装和运行Statspack你可能需要设置以下系统参数:
- job_queue_processes
为了能够建立自动任务,执行数据收集,该参数需要大于0。你可以在初试化参数文件中修改该参数(使该参数在重起后以然有效)。
该参数可以在系统级动态修改(重起后失效)。
|
SQL> alter system set job_queue_processes = 6;
System altered
|
在Oracle9i当中,可以指定范围,如 both,这样该修改在当前及之后保持有效(仅当你使用spfile时,如果在9i中仍然使用pfile,
那么更改方法同8i相同):
|
SQL> alter system set job_queue_processes = 6 scope=both;
系统已更改。
|
- timed_statistics
收集操作系统的计时信息,这些信息可被用来显示时间等统计信息、优化数据库和 SQL 语句。要防止因从操作系统请求时间而引
起的开销,请将该值设置为False。
使用statspack收集统计信息时建议将该值设置为 TRUE,否则收集的统计信息大约只能起到10%的作用,将timed_statistics
设置为True所带来的性能影响与好处相比是微不足道的。
该参数使收集的时间信息存储在在V$SESSTATS和V$SYSSTATS等动态性能视图中。
Timed_statistics参数可以在实例级进行更改
|
SQL> alter system set timed_statistics = true;
System altered
SQL>
|
如果你担心一致启用timed_statistics 对于性能的影响,你可以在使用statspack之前在system更改,采样过后把该参数动
态修改成false。
Posted by eygle at 9:54 PM | Comments (0)
如何在Oracle中发送Email
作者:eygle
出处:http://blog.eygle.com
在Oracle中发送email,以下是Oracle提供的例子,供参考.itpub link:
http://www.itpub.net/showthread.php?threadid=226086
1. CREATE PACKAGE
|
CREATE OR REPLACE PACKAGE demo_mail IS ----------------------- Customizable Section ----------------------- -- Customize the SMTP host, port and your domain name below. -- Customize the signature that will appear in the email's MIME header. --------------------- End Customizable Section --------------------- -- A unique string that demarcates boundaries of parts in a multi-part email FIRST_BOUNDARY CONSTANT VARCHAR2(256) := '--' || BOUNDARY || utl_tcp.CRLF; -- A MIME type that denotes multi-part email (MIME) messages. -- A simple email API for sending email in plain text in a single call. -- Extended email API to send email in HTML or plain text with no size limit. -- Write email body in ASCII -- Write email body in non-ASCII (including multi-byte). The email body -- Write email body in binary -- APIs to send email with attachments. Attachments are sent by sending -- Send a single text attachment. -- Send a binary attachment. The attachment will be encoded in Base-64 -- Send an attachment with no size limit. First, begin the attachment -- End the attachment. -- End the email. -- Extended email API to send multiple emails in a session for better -- Begin an email in a session. -- End an email in a session. -- End an email session. END; -- Return the next email address in the list of email addresses, separated addr VARCHAR2(256); FUNCTION lookup_unquoted_char(str IN VARCHAR2, c := substr(str, i, 1); IF (inside_quote) THEN IF (c = '"') THEN IF (instr(chrs, c) >= 1) THEN <<next_char>> END LOOP; RETURN 0; END; BEGIN addr_list := ltrim(addr_list); i := lookup_unquoted_char(addr, '<'); RETURN addr; -- Write a MIME header -- Mark a message-part boundary. Set <last> to TRUE for the last boundary. ------------------------------------------------------------------------ ------------------------------------------------------------------------ ------------------------------------------------------------------------ ------------------------------------------------------------------------ ------------------------------------------------------------------------ ------------------------------------------------------------------------ ------------------------------------------------------------------------ begin_attachment(conn, mime_type, inline, filename, 'base64'); -- Split the Base64-encoded attachment into multiple lines end_attachment(conn, last); END; ------------------------------------------------------------------------ IF (filename IS NOT NULL) THEN IF (transfer_enc IS NOT NULL) THEN utl_smtp.write_data(conn, utl_tcp.CRLF); ------------------------------------------------------------------------ ------------------------------------------------------------------------ ------------------------------------------------------------------------ ------------------------------------------------------------------------ -- Specify sender's address (our server allows bogus address -- Specify recipient(s) of the email. -- Start body of email -- Set "From" MIME header -- Set "To" MIME header -- Set "Subject" MIME header -- Set "Content-Type" MIME header -- Set "X-Mailer" MIME header -- Set priority: -- Send an empty line to denotes end of MIME headers and IF (mime_type LIKE 'multipart/mixed%') THEN END; ------------------------------------------------------------------------ ------------------------------------------------------------------------ END; |
2.发送 MAIL:
|
CREATE OR REPLACE procedure MailTest IS begin |
Posted by eygle at 9:07 PM | Comments (1)
