Mysql Explain 详解

Mysql Explain 详解

一.语法

explain < table_name >

例如: explain select * from t3 where id=3952602;

二.explain输出解释

+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys     | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+

1.id
  我的理解是SQL执行的顺利的标识,SQL从大到小的执行.

例如:
mysql> explain select * from (select * from ( select * from t3 where id=3952602) a) b;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table      | type   | possible_keys     | key     | key_len | ref  | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
|  1 | PRIMARY     | <derived2> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  2 | DERIVED     | <derived3> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  3 | DERIVED     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

很显然这条SQL是从里向外的执行,就是从id=3 向上执行.

2. select_type

就是select类型,可以有以下几种

(1) SIMPLE
简单SELECT(不使用UNION或子查询等) 例如:
mysql> explain select * from t3 where id=3952602;
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys     | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | t3    | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 |       |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+

(2). PRIMARY

我的理解是最外层的select.例如:

mysql> explain select * from (select * from t3 where id=3952602) a ;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table      | type   | possible_keys     | key     | key_len | ref  | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
|  1 | PRIMARY     | <derived2> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  2 | DERIVED     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

(3).UNION

UNION中的第二个或后面的SELECT语句.例如
mysql> explain select * from t3 where id=3952602 union all select * from t3 ;
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type  | table      | type  | possible_keys     | key     | key_len | ref   | rows | Extra |
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+
|  1 | PRIMARY      | t3         | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 |       |
|  2 | UNION        | t3         | ALL   | NULL              | NULL    | NULL    | NULL  | 1000 |       |
|NULL | UNION RESULT | <union1,2> | ALL   | NULL              | NULL    | NULL    | NULL  | NULL |       |
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+

(4).DEPENDENT UNION

UNION中的第二个或后面的SELECT语句,取决于外面的查询

mysql> explain select * from t3 where id in (select id from t3 where id=3952602 union all select id from t3)  ;
+----+--------------------+------------+--------+-------------------+---------+---------+-------+------+--------------------------+
| id | select_type        | table      | type   | possible_keys     | key     | key_len | ref   | rows | Extra                    |
+----+--------------------+------------+--------+-------------------+---------+---------+-------+------+--------------------------+
|  1 | PRIMARY            | t3         | ALL    | NULL              | NULL    | NULL    | NULL  | 1000 | Using where              |
|  2 | DEPENDENT SUBQUERY | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 | Using index              |
|  3 | DEPENDENT UNION    | t3         | eq_ref | PRIMARY,idx_t3_id | PRIMARY | 4       | func  |    1 | Using where; Using index |
|NULL | UNION RESULT       | <union2,3> | ALL    | NULL              | NULL    | NULL    | NULL  | NULL |                          |
+----+--------------------+------------+--------+-------------------+---------+---------+-------+------+--------------------------+

(4).UNION RESULT

UNION的结果。

mysql> explain select * from t3 where id=3952602 union all select * from t3 ;
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type  | table      | type  | possible_keys     | key     | key_len | ref   | rows | Extra |
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+
|  1 | PRIMARY      | t3         | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 |       |
|  2 | UNION        | t3         | ALL   | NULL              | NULL    | NULL    | NULL  | 1000 |       |
|NULL | UNION RESULT | <union1,2> | ALL   | NULL              | NULL    | NULL    | NULL  | NULL |       |
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+

(5).SUBQUERY

子查询中的第一个SELECT.

mysql> explain select * from t3 where id = (select id from t3 where id=3952602 )  ;
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------------+
| id | select_type | table | type  | possible_keys     | key     | key_len | ref   | rows | Extra       |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------------+
|  1 | PRIMARY     | t3    | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 |             |
|  2 | SUBQUERY    | t3    | const | PRIMARY,idx_t3_id | PRIMARY | 4       |       |    1 | Using index |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------------+

(6).  DEPENDENT SUBQUERY

子查询中的第一个SELECT,取决于外面的查询

mysql> explain select id from t3 where id in (select id from t3 where id=3952602 )  ;
+----+--------------------+-------+-------+-------------------+---------+---------+-------+------+--------------------------+
| id | select_type        | table | type  | possible_keys     | key     | key_len | ref   | rows | Extra                    |
+----+--------------------+-------+-------+-------------------+---------+---------+-------+------+--------------------------+
|  1 | PRIMARY            | t3    | index | NULL              | PRIMARY | 4       | NULL  | 1000 | Using where; Using index |
|  2 | DEPENDENT SUBQUERY | t3    | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 | Using index              |
+----+--------------------+-------+-------+-------------------+---------+---------+-------+------+--------------------------+

(7).DERIVED

派生表的SELECT(FROM子句的子查询)

mysql> explain select * from (select * from t3 where id=3952602) a ;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table      | type   | possible_keys     | key     | key_len | ref  | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
|  1 | PRIMARY     | <derived2> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  2 | DERIVED     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

3.table

显示这一行的数据是关于哪张表的.
有时不是真实的表名字,看到的是derivedx(x是个数字,我的理解是第几步执行的结果)

mysql> explain select * from (select * from ( select * from t3 where id=3952602) a) b;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table      | type   | possible_keys     | key     | key_len | ref  | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
|  1 | PRIMARY     | <derived2> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  2 | DERIVED     | <derived3> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  3 | DERIVED     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

4.type

这列很重要,显示了连接使用了哪种类别,有无使用索引.
从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALL

(1).system

这是const联接类型的一个特例。表仅有一行满足条件.如下(t3表上的id是 primary key)

mysql> explain select * from (select * from t3 where id=3952602) a ;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table      | type   | possible_keys     | key     | key_len | ref  | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
|  1 | PRIMARY     | <derived2> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  2 | DERIVED     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

(2).const

表最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读取一次!

const用于用常数值比较PRIMARY KEY或UNIQUE索引的所有部分时。在下面的查询中,tbl_name可以用于const表:
SELECT * from tbl_name WHERE primary_key=1;
SELECT * from tbl_name WHERE primary_key_part1=1和 primary_key_part2=2;

例如:
mysql> explain select * from t3 where id=3952602;
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys     | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | t3    | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 |       |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+

(3). eq_ref

对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联接使用并且索引是UNIQUE或PRIMARY KEY。

eq_ref可以用于使用= 操作符比较的带索引的列。比较值可以为常量或一个使用在该表前面所读取的表的列的表达式。

在下面的例子中,MySQL可以使用eq_ref联接来处理ref_tables:

SELECT * FROM ref_table,other_table
  WHERE ref_table.key_column=other_table.column;

SELECT * FROM ref_table,other_table
  WHERE ref_table.key_column_part1=other_table.column
    AND ref_table.key_column_part2=1;

例如
mysql> create unique index  idx_t3_id on t3(id) ;
Query OK, 1000 rows affected (0.03 sec)
Records: 1000  Duplicates: 0  Warnings: 0

mysql> explain select * from t3,t4 where t3.id=t4.accountid;
+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+
| id | select_type | table | type   | possible_keys     | key       | key_len | ref                  | rows | Extra |
+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+
|  1 | SIMPLE      | t4    | ALL    | NULL              | NULL      | NULL    | NULL                 | 1000 |       |
|  1 | SIMPLE      | t3    | eq_ref | PRIMARY,idx_t3_id | idx_t3_id | 4       | dbatest.t4.accountid |    1 |       |
+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+

(4).ref

对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是UNIQUE或PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话),则使用ref。如果使用的键仅仅匹配少量行,该联接类型是不错的。

ref可以用于使用=或<=>操作符的带索引的列。

在下面的例子中,MySQL可以使用ref联接来处理ref_tables:

SELECT * FROM ref_table WHERE key_column=expr;

SELECT * FROM ref_table,other_table
  WHERE ref_table.key_column=other_table.column;

SELECT * FROM ref_table,other_table
  WHERE ref_table.key_column_part1=other_table.column
    AND ref_table.key_column_part2=1;

例如:

mysql> drop index idx_t3_id on t3;
Query OK, 1000 rows affected (0.03 sec)
Records: 1000  Duplicates: 0  Warnings: 0

mysql> create index idx_t3_id on t3(id) ;
Query OK, 1000 rows affected (0.04 sec)
Records: 1000  Duplicates: 0  Warnings: 0

mysql> explain select * from t3,t4 where t3.id=t4.accountid;
+----+-------------+-------+------+-------------------+-----------+---------+----------------------+------+-------+
| id | select_type | table | type | possible_keys     | key       | key_len | ref                  | rows | Extra |
+----+-------------+-------+------+-------------------+-----------+---------+----------------------+------+-------+
|  1 | SIMPLE      | t4    | ALL  | NULL              | NULL      | NULL    | NULL                 | 1000 |       |
|  1 | SIMPLE      | t3    | ref  | PRIMARY,idx_t3_id | idx_t3_id | 4       | dbatest.t4.accountid |    1 |       |
+----+-------------+-------+------+-------------------+-----------+---------+----------------------+------+-------+
2 rows in set (0.00 sec)

(5).  ref_or_null

该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行。在解决子查询中经常使用该联接类型的优化。

在下面的例子中,MySQL可以使用ref_or_null联接来处理ref_tables:

SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;

(6). index_merge

该联接类型表示使用了索引合并优化方法。在这种情况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。

例如:
mysql> explain select * from t4 where id=3952602 or accountid=31754306 ;
+----+-------------+-------+-------------+----------------------------+----------------------------+---------+------+------+------------------------------------------------------+
| id | select_type | table | type        | possible_keys              | key                        | key_len | ref  | rows | Extra                                                |
+----+-------------+-------+-------------+----------------------------+----------------------------+---------+------+------+------------------------------------------------------+
|  1 | SIMPLE      | t4    | index_merge | idx_t4_id,idx_t4_accountid | idx_t4_id,idx_t4_accountid | 4,4     | NULL |    2 | Using union(idx_t4_id,idx_t4_accountid); Using where |
+----+-------------+-------+-------------+----------------------------+----------------------------+---------+------+------+------------------------------------------------------+
1 row in set (0.00 sec)

(7). unique_subquery

该类型替换了下面形式的IN子查询的ref:

value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。

(8).index_subquery

该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引:

value IN (SELECT key_column FROM single_table WHERE some_expr)

(9).range

只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引。key_len包含所使用索引的最长关键元素。在该类型中ref列为NULL。

当使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比较关键字列时,可以使用range

mysql> explain select * from t3 where id=3952602 or id=3952603 ;
+----+-------------+-------+-------+-------------------+-----------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys     | key       | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+-------------------+-----------+---------+------+------+-------------+
|  1 | SIMPLE      | t3    | range | PRIMARY,idx_t3_id | idx_t3_id | 4       | NULL |    2 | Using where |
+----+-------------+-------+-------+-------------------+-----------+---------+------+------+-------------+
1 row in set (0.02 sec)

(10).index

该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。

当查询只使用作为单索引一部分的列时,MySQL可以使用该联接类型。

(11). ALL

对于每个来自于先前的表的行组合,进行完整的表扫描。如果表是第一个没标记const的表,这通常不好,并且通常在它情况下很差。通常可以增加更多的索引而不要使用ALL,使得行能基于前面的表中的常数值或列值被检索出。

5.possible_keys

possible_keys列指出MySQL能使用哪个索引在该表中找到行。注意,该列完全独立于EXPLAIN输出所示的表的次序。这意味着在possible_keys中的某些键实际上不能按生成的表次序使用。

如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查WHERE子句看是否它引用某些列或适合索引的列来提高你的查询性能。如果是这样,创造一个适当的索引并且再次用EXPLAIN检查查询

6. key

key列显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。

7.key_len

key_len列显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。
使用的索引的长度。在不损失精确性的情况下,长度越短越好

8. ref

ref列显示使用哪个列或常数与key一起从表中选择行。

9. rows

rows列显示MySQL认为它执行查询时必须检查的行数。

10. Extra

该列包含MySQL解决查询的详细信息,下面详细.

(1).Distinct
一旦MYSQL找到了与行相联合匹配的行,就不再搜索了

(2).Not exists
MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,

就不再搜索了

(3).Range checked for each

Record(index map:#)
没有找到理想的索引,因此对于从前面表中来的每一个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一

(4).Using filesort
看到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行

(5).Using index
列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候

(6).Using temporary
看到这个的时候,查询需要优化了。这里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上

(7).Using where
使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index,这就会发生,或者是查询有问题

发表在 db | 标签为 | Mysql Explain 详解已关闭评论

2的64次幂

0               1               0x1
1               2               0x2
2               4               0x4
3               8               0x8
4               16              0x10
5               32              0x20
6               64              0x40
7               128             0x80
8               256             0x100
9               512             0x200
10              1024            0x400
11              2048            0x800
12              4096            0x1000
13              8192            0x2000
14              16384           0x4000
15              32768           0x8000
16              65536           0x10000
17              131072          0x20000
18              262144          0x40000
19              524288          0x80000
20              1048576         0x100000
21              2097152         0x200000
22              4194304         0x400000
23              8388608         0x800000
24              16777216                0x1000000
25              33554432                0x2000000
26              67108864                0x4000000
27              134217728               0x8000000
28              268435456               0x10000000
29              536870912               0x20000000
30              1073741824              0x40000000
31              2147483648              0x80000000
32              4294967296              0x100000000
33              8589934592              0x200000000
34              17179869184             0x400000000
35              34359738368             0x800000000
36              68719476736             0x1000000000
37              137438953472            0x2000000000
38              274877906944            0x4000000000
39              549755813888            0x8000000000
40              1099511627776           0x10000000000
41              2199023255552           0x20000000000
42              4398046511104           0x40000000000
43              8796093022208           0x80000000000
44              17592186044416          0x100000000000
45              35184372088832          0x200000000000
46              70368744177664          0x400000000000
47              140737488355328         0x800000000000
48              281474976710656         0x1000000000000
49              562949953421312         0x2000000000000
50              1125899906842624                0x4000000000000
51              2251799813685248                0x8000000000000
52              4503599627370496                0x10000000000000
53              9007199254740992                0x20000000000000
54              18014398509481984               0x40000000000000
55              36028797018963968               0x80000000000000
56              72057594037927936               0x100000000000000
57              144115188075855872              0x200000000000000
58              288230376151711744              0x400000000000000
59              576460752303423488              0x800000000000000
60              1152921504606846976             0x1000000000000000
61              2305843009213693952             0x2000000000000000
62              4611686018427387904             0x4000000000000000
63              9223372036854775808             0x8000000000000000

发表在 technologys | 2的64次幂已关闭评论

Newtonsoft.Json序列化和反序列

这里下载:http://www.newtonsoft.com/products/json/
安装:
   1.解压下载文件,得到Newtonsoft.Json.dll
   2.在项目中添加引用..
 序列化和反序列在.net项目中:
 

Product product = new Product();
 
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
 
string output = javascriptConvert.SerializeObject(product);
//{
//  "Name": "Apple",
//  "Expiry": new Date(1230422400000),
//  "Price": 3.99,
//  "Sizes": [
//    "Small",
//    "Medium",
//    "Large"
//  ]
//}
 
Product deserializedProduct = (Product)javascriptConvert.DeserializeObject(output, typeof(Product));

 
读取JSON

string jsonText = "['JSON!',1,true,{property:'value'}]";
 
JsonReader reader = new JsonReader(new StringReader(jsonText));
 
Console.WriteLine("TokenType\t\tValueType\t\tValue");
 
while (reader.Read())
{
    Console.WriteLine(reader.TokenType + "\t\t" + WriteValue(reader.ValueType) + "\t\t" + WriteValue(reader.Value))
}

结果显示:

TokenType ValueType Value
StartArray null null
String System.String JSON!
Integer System.Int32 1
Boolean System.Boolean True
StartObject null null
PropertyName System.String property
String System.String value
EndObject null null
EndArray null null

JSON写入

StringWriter sw = new StringWriter();
JsonWriter writer = new JsonWriter(sw);
 
writer.WriteStartArray();
writer.WriteValue("JSON!");
writer.WriteValue(1);
writer.WriteValue(true);
writer.WriteStartObject();
writer.WritePropertyName("property");
writer.WriteValue("value");
writer.WriteEndObject();
writer.WriteEndArray();
 
writer.Flush();
 
string jsonText = sw.GetStringBuilder().ToString();
 
Console.WriteLine(jsonText);
// ['JSON!',1,true,{property:'value'}]

这里会打印出: ['JSON!',1,true,{property:'value'}].

发表在 article | 标签为 | Newtonsoft.Json序列化和反序列已关闭评论

解决fileSystemWatcher的onChanged的事件触发多次的问题

Q:

FileSystemWatcher 的Changed事件,在我保存某个文本文件的时候,该事件可能会被出发多次,如何使他触发一次?

 

A:

解决fileSystemWatcher的onChanged的事件触发多次的WorkAround方法就是尝试在监视的文件或文件夹发生变化时通知Framework, 具体的代码如下:

 

My best guess is the FileWatcher fires the Create event once the file is opened for 
write and then again when it completes. I've added a test for file existence in the 
Event Handler and it does indeed FAIL on the first callback. The code below produced
 a series of debug prints showing every other callback has the OS reporting the file
 exists, i.e., 2,4,6,...


namespace MyExample
{
    class Program
    {
        private static FileSystemWatcher watcher;
        private static string mailbox = @"c:\Mailbox";
        private static int callbacks = 0;

        static void Main(string[] args)
        {
            watcher = new FileSystemWatcher();
            watcher.Path = mailbox;
            watcher.NotifyFilter = NotifyFilters.FileName;
            watcher.Created += new FileSystemEventHandler(OnChanged);
            watcher.EnableRaisingEvents = true;
        

            Console.WriteLine("Press Enter to quit\r\n");
            Console.ReadLine();    
        }



        public static void OnChanged(object source, FileSystemEventArgs e)
        {
            try
            {
                watcher.EnableRaisingEvents = false;
                callbacks++;
                FileInfo objFileInfo = new FileInfo(e.FullPath);
                if (!objFileInfo.Exists) return;   
// ignore the file open, wait for complete write
                ProcessAllFiles(e.FullPath);

            }
            catch (Exception ex)
            {
                string msg = ex.Message;
                // do something?
            }
            finally
            {
                watcher.EnableRaisingEvents = true;
            }
        }




        public static void ProcessAllFiles(string FullPath)
        {
            // stub

	    string directory = FullPath.Substring(0, FullPath.LastIndexOf(@"\"));
            string filename = FullPath.Substring(FullPath.LastIndexOf(@"\"));
            Console.WriteLine("file: {0} Callback # {1} ", filename, callbacks);  
        }

 

关于解决fileSystemWatcher的onChanged的事件触发多次的WorkAround方法的详细信息,请参考下述文章:http://www.codeproject.com/useritems/FileWatcher.asp
发表在 article | 解决fileSystemWatcher的onChanged的事件触发多次的问题已关闭评论

aooshi.dll

aooshi.dll   更名为  adf.dll

详见: /adf/347.html

发表在 adf | 标签为 | aooshi.dll已关闭评论

NPOI简介

作者:Tony Qu

========================================

[更新] NPOI 1.2.4 新教程地址:http://tonyqus.sinaapp.com

========================================

NPOI 微博: http://weibo.com/npoi

NPOI QQ交流群: 

群1:189925337

群2:124527967

群3: 116053476

 

更新

2009.3.24  把npoi 1.2 alpha的链接换成NPOI 1.2 beta

2009.11.18  把npoi 1.2 beta的链接换成NPOI 1.2.1; 增加NPOI教程链接

2009.12.1 增加QQ群

===================================================

本文将通过问答的方式帮助你了解NPOI。

 

什么是NPOI?

NPOI,顾名思义,就是POI的.NET版本。那POI又是什么呢?POI是一套用Java写成的库,能够帮助开发者在没有安装微软Office的情况下读写Office 97-2003的文件,支持的文件格式包括xls, doc, ppt等。目前POI的稳定版本中仅支持Excel文件格式xls,其他的都属于不稳定版本(放在poi的scrachpad目录中)。NPOI是构建在POI 3.x版本之上的,本月发布的NPOI 1.2是对应于POI 3.2 final的,所以它支持Excel文件读写,但由于人手和精力原因,还没有实现读写Word, PowerPoint, Visio的文件格式。

 

NPOI的官方网站是啥?

npoi.codeplex.com

 

为什么用NPOI?

因为它能够帮助你生成真正的Office文件格式,比如说Excel文件格式。我曾经看到好几个园友发过有关如何生成Excel报表的帖子,大家确实花了很多心思,具体的帖子如下:

生成Excel高级报表(用的是Office PIA库)

http://www.cnblogs.com/xiaobier/archive/2008/10/13/1310399.html

Datagrid数据导出到excel文件的三种方法

http://www.cnblogs.com/xieduo/articles/606202.html

其中提到了的2种方法分别是:cvs法、html法

.net 操作 EXCEL

http://www.cnblogs.com/jhobo/archive/2009/02/17/1392423.html

其中提到了Office PIA法、OLEDB法、OPENXML法

 

特别是其中的cvs法和html法值得提一下,这得感谢Microsoft Office对于格式的强大兼容性,貌似国产某某Office软件就无法正常显示基于html的xls文件。

好了,回到我们的问题上,为什么要用NPOI呢?

第一点,你不需要在服务器上安装微软的Office,可以避免版权问题。

第二点,使用起来比Office PIA的API更加方便,更人性化。

第三点,你不用去花大力气维护NPOI,NPOI Team会不断更新、改善NPOI,绝对省成本。

第四点,很多事情是html和cvs法做不到的,比如说公式计算[Cell C1]=A1+B1*A2、单元格高级样式(如文本旋转、对齐、宽度)等,其中公式计算可以适当减轻服务器端的计算压力

第五点,你很难保证你的客户机器上都安装了Office 2007或Office Compatiblity Pack for Office 2003,出于向前兼容的考虑,还是生成Office 97-2003格式比较可靠

 

当然有人要说了,那我用myXls等同类产品可不可以?当然可以,纯属个人喜好,这就好比你愿意用NHibernate还是NBear,完全可以自由选择。

 

NPOI由哪些东西组成?

NPOI目前主要由以下部分组成

NPOI.POIFS OLE2 Document File System Library
NPOI.DDF Microsoft Office Drawing format Library
NPOI.HPSF OLE2 Propertyset library (包括SummaryInformation和DocumentSummaryInformation)
NPOI.HSSF Microsoft Excel BIFF library
NPOI.SS Formula Evaluation library
NPOI.Util 基础类库,提供了很多实用功能,可用于其他读写文件格式项目的开发

 

NPOI目前的版本如何?包括哪些功能?

目前NPOI的最新版是NPOI 1.2.1,其中包括了以下功能:

a. 读写OLE2文档

b. 读写DocummentSummaryInformation和SummaryInformation

c. 基于LittleEndian的字节读写

d. 读写Excel BIFF格式

e. 识别并读写Excel BIFF中的常见Record,如RowRecord, StyleRecord, ExtendedFormatRecord

f. 支持设置单元格的高、宽、样式等

g. 支持调用部分Excel内建函数,比如说sum, countif以及计算符号

h. 支持在生成的Xls内嵌入打印设置,比如说横向/纵向打印、缩放、使用的纸张等

i. ……  (功能太多,无法一一例举,大家自己研究吧)

下载地址:http://npoi.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=19351

 

在开发中哪些地方可以使用NPOI

a. 生成Excel报表

b. Excel中的文本提取(主要用于搜索引擎)

c. 批量生成Excel文件

d. 基于Excel文件模板生成新的Excel

e. 研究Excel BIFF文件格式及OLE2文件格式

 

NPOI的最终目标是什么?

a. 能够读写几乎所有的Office 97-2003文件格式,至少能够支持Word, PowerPoint, Excel, Visio的格式,其他的会根据实际需求而定。

b. 作为教学Office文件格式的“活”教材,也可作为研究生阶段研究数据结构的教材。

即使是目前的1.2版本也很不完善,支持的Excel功能还很有限,没有搞过NPOI的研发,包括我在内的很多人很难想象微软这样一个Excel软件的开发量,其中除了我们常用的基本功能以外,还有很多内置函数的实现、对行进行分组、行的锁定、表单的保护等。说实话有些功能我也是第一次听说,是在开发中一边看Excel界面一边实现的(呵呵,是不是很土)。由于Office 2007为了兼容Office 97-2003,在其基础上增加了很多新的Record,所以要生成真正意义上的全新的Excel BIFF很难(话说微软的开发速度贼快)。

在NPOI以后的版本中还会支持Pivot表和图表(Chart),其实你在poi的svn中已经可以看到最新的pivot和chart的代码了,只是还在开发中,没有发布正式版本,估计今年中旬会发一个新的版本。

 

我也想研究Office文件格式,有没有相关的文档和工具可供参考?

首先是文件格式的说明文档,你可以去微软的官方网站下载:http://www.microsoft.com/interop/docs/officebinaryformats.mspx

接着是,我和Huseyin共同开发了POIFS Browser,目前的版本是1.2,已经能够识别Excel BIFF了。

你可以去http://npoi.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=23409下载。

 

我可以参加NPOI开发组吗?

当然可以,我非常欢迎大家加入NPOI Team,因为目前狂缺人手,很多事情要做,比如说实现读写Word格式的库,即HWPF;还需要有人帮忙一起写文档、写范例、写教程。目前团队中只有2个人,我和Huseyin(土耳其人),最近Huseyin也很忙,没时间维护NPOI,所以我很需要你的加入。大家有兴趣可以到http://npoi.codeplex.com/Thread/View.aspx?ThreadId=36157回帖,或者直接发邮件给我(具体邮件地址见我blog的左边栏)。

 

NPOI有教程吗?

有,该教程是为NPOI 1.2写的,详细目录请见http://www.cnblogs.com/tonyqus/archive/2009/04/12/1434209.html

 

NPOI Team下一步准备干嘛?

上一个问题中提到事情真的很多,下面罗列一下:

a. 使Excel读写库(HSSF)更加稳定

b. 开发HSSF对Pivot Table和Chart的支持

c. 开发Word读写库(HWPF)、PowerPoint读写库(HSLF)

d. 把HSSF的注释补全,把java的注释转成.NET的,便于用NDoc生成文档和智能感知

e. 写NPOI 1.2的范例(目前只有10个左右,目标是>50个,类似于微软的SDK,这样方便大家学习和理解)

f.  写NPOI 1.2的教程

 

引用:http://www.cnblogs.com/tonyqus/archive/2009/03/16/1409966.html

发表在 article | 标签为 , , | NPOI简介已关闭评论

分布式系统邮件服务器架设

来源:拓波软件 技术支持部

 

设计目标

邮件系统在当今社会,作为一种基础通讯平台,已经不单纯是简单收发邮件,而是成为互联网各种应用的核心,承载越来越重要的应用。中国人口众多,上网人数逐年剧增,使用邮件也日益频繁。邮件系统从建成的那一天起,就面临升级的压力。如何设计一个结构良好的大容量邮件系统,对于系统稳定性、可靠性,对于日后的升级维护有着至关重要的作用。

拓波公司作为一个在邮件领域默默耕耘的公司,以小用户量的企业邮件系统立身,最终希望打造一个坚固的、高度可扩展的、容易管理维护的大容量分布式邮件系统。在设计时,我们主要考虑如下方面:

1. 底层坚固、高度稳定。

为保证系统的稳定可靠,需要在硬件、操作系统、核心MTA、应用层在内的每一个环节都稳定可靠才行。硬件通常选取知名品牌服务器,稳定性、可靠性都有保障,差别不大。操作系统选择Linux 或者FreeBSD, 针对邮件系统的特点,内核需要特殊调整:如打开文件数(open files)、stack size 、max user processes 等。除了操作系统核心外,系统只加载必须的软件,屏蔽一切不不要的服务端口。

在操作系统之上,处理smtp、pop3 请求的MTA 的稳定性、效率也至关重要。当今世界上使用比较多的是qmail 和postfix, 都有分布世界各地的大批用户。相比较而言,qmail有着更好的模块化设计、更好的安全性,更高的投递效率、更可靠的队列设计。Postfix 优势在于和sendmail 有着很好的兼容性,部署容易,集成程度比较高,也是一个非常不错的MTA 软件。

应用层我们选取Apache+tomcat。Apache 久负盛名、久经考验,tomcat 背后有SUN 支持,最重要的是tomcat5 支持应用层负载均衡(Load Balance)。另外,java 作为一种面向对象的编程语言,最能体现软件工程思想,有一系列的UML 设计工具、集成开发环境、应用服务器可以选择。很多学校也开设JAVA 课程,以后JAVA 会像c 语言那样普及,变成程序员必备的技能之一。邮件系统应用层会根据用户的反馈增加信的增值服务品种,如果基于

java 开发,很容找到相关人才。这样缩短开发周期、节省开发成本、降低维护难度。Google很多服务是基于java 开发的。当然,java 也有执行效率低的缺点,但随着硬件速度的提升,单只程序运行速度的劣势很容易被良好的设计模式优势取代。

2. 容易管理、维护。

系统结构复杂之后,必然会带来管理维护上的麻烦。我们的设计思想是希望通过统一的一个管理控制界面,让系统管理员对每台服务器的运行状况、负载情况、流量了如指掌;同时通过一个管控界面,可以远程控制服务器启动、关闭,对服务进程远程启动、停止,对流量调配。当出现异常时,系统自动通过短信通知到管理人员的手机上。

3. 增加设备简单、有效。

系统扩展性是衡量系统设计好坏的一个重要指标。好的系统能够通过简单添置硬件、软件做少许配置即可满足需要。我们设计的是让用户数量的增长和邮件服务器数量呈线性关系。由于PC 服务器的硬件成本比较低,以一台高性能PC 服务器3 万元人民币计算,如果作为SMTP 服务器可以支撑15 万用户,作为POP 服务器可以支撑30 万用户,作为存储服务器,可以支撑3 万用户。平均每用户为0.2 元、0.1 元、1 元。

在保证系统稳定可靠的同时,能够最大地降低成本。降低成本有2 个途径,一是最大限度利用硬件,二是避免使用高端的存储备份设备、负载均衡设备、四层交换机等。

点击查看原图
4. 具有多级权限管理,支持个人用户、企业用户、运营商等。

大容量邮件系统,不仅仅是个人用户,还有企业用户。不同用户群体的需求是不同的。针对不同用户群,提供不同的服务套餐,无疑是市场营销重要手段。而这,需要有技术上做保障才行。TurboMail邮件应用层采用java 技术,无疑是体现用户需求的最佳技术手段。

作为运营商,要有丰富权限管理体系,使邮件系统的每一个管理环节严紧、严密。

5. 高度模块化,模块之间最小耦合。

模块化程度的高低,可以体现的系统的成熟度。充分利用开源宝库中的免费资源,将优秀的开源项目经过改良、优化,会搭建出优秀的系统。不赞成完全从底层开发。模块之间通过标准接口通讯,耦合程度尽可能小,这样,即使出问题也不会影响全局。最重要的是,系统扩展性大大增强。如可以随时将病毒扫描过滤模块升级,或者将

垃圾邮件过滤模块升级,其它模块无需做任何改动。

6. 提供与其它系统直接的接口:如计费平台、短信彩信平台、防毒网关等。

作为邮件运营,计费模块很重要。良好的设计可以为灵活的计费提供原始数据。根据这些计费数据,可以制定灵活的促销手段。随着彩信的普及,邮件系统与彩信会逐渐融合。其它的扩展平台,如防病毒网关、
反垃圾网关、反黄网关都可以灵活对接。

7. 应用层二次开发、部署简单方便。

邮件系统的生命力来自客户的需求,只有不断满足客户需求,推陈出新,与时俱进,才会不断有新的用户加入。根据用户需求进行二次开发,这是必不可少的。二次开发必须简单,方便。TurboMail邮件通过统一的二次开发接口Jindi-Mailet 实现服务端应用的扩展。

邮件系统架构上的演化和优劣比较

大容量邮件系统按照存储方式不同,大致可以分为2 类:
1. 统一存储

邮件队列和邮件数据集中放在存储设备上。前端smtp 服务器多台,POP 服务器多台,随机选择一台smtp 服务器或者POP 服务器(这个过程一般采用DNS 轮询方式完成)。选定某台服务器后,与该服务器建立连接,通过认证系统确认用户身份后,发送或者接收邮件数据。因为是统一存储,数据都是放在磁盘阵列上,通过NFS 方式挂在

每台服务器上。不论是通过哪台功能服务器,都可以完成邮件收发。
用户对Webmail 的请求和smtp/pop3 类似,也是通过多台机器随机选取实现负载分布。
2. 分布式存储

邮件数据分布在每一台服务器上,每台服务器都提供完整的邮件服务:smtp/pop3/imap/webmail/数据库。用户请求过来之后,首先查询目录服务器,验证用户身份,然后找到对应的服务器,建立连接,收取或者发送邮件。

这种方式最大的优点是用户数量和邮件服务器数量可以保持线性增长。每台服务器支持10 万邮箱,当一台服务器用户已达这个数字时,启用另外一台。可以通过管理程序在不同服务器直接迁移用户。动态管理服务器。

从早期UNIX 几十用户的简单邮件系统,到现在几百万、上千万邮件系统,中间经历很多变化。不妨把这些梳理一下,比较邮件系统各种技术的优劣。

1. 一机一域、一机多域(虚拟域)

一机一域代表用户是企业用户。一台服务器作为邮件服务器。一机多域象新网、万网,给很多企业提供邮箱。所有的服务,如smtp,pop3,imap 都在一台服务器上,对方邮件服务器通过查询DNS 即可唯一锁定收件方服务IP,直接投递过去。

这种单机邮件系统,由于受cpu、内存、硬盘的制约,用户最多一般不超过10 万用户。考虑可靠性,一般采用HA,将用户数据存放磁盘阵列上,正常只有一台服务器工作,异常时自动切换到另外一台。对于一般的企业用户,这种单机邮件系统已经够用。但对于大型邮件系统,这种单机系统显然无法满足。

2. 多机一域,功能分割,集中存储。
点击查看原图

邮件服务器smtp、pop3、imap、webmail 服务分布在不同的服务器上,通过NFS 统一访问同一存储区域。

这种做法,实现一个简单功能分布,使每一台服务器功能单一,几台服务器各司其职,处理能力大大增强。这种简单的功能分散,实现起来比较简单,只要在不同的服务器其上部署相关服务即可,将存储服务器通过NFS mount 到每一个服务器上,然后在DNS 中做相关配置。

当用户增大到一定数量,并发量会比较大,单台smtp 可以到256 并发量,最多不会超

过1000 并发量。因此smtp 很容易成为瓶颈。

3. 多机一域,负载均衡,集中存储。
点击查看原图 

当邮件用户并发量大时,smtp 很容易成为瓶颈,在系统中出现瓶颈的地方可以多增加几台服务器,然后更新DNS,通过 DNS 查询解析不同的smtp 服务器地址,可以使请求平均分配到每一台服务器上。

现在许多大容量邮件系统都脱胎于此,特点是部署容易,简单易行。缺点是当访问量增

大后,数据访问全部通过NFS,也很容易出现磁盘IO 瓶颈。

4. 多机一域,功能分布,存储分布。

该系统前端(front-end)是一个邮件交换器和目录服务器LDAP,后端是多台独立的存储服务器,通过管理中心调度,将存储服务器通过NFS 挂在相应的smtp 服务器或者pop 服务上。

在目录服务器上,会保存用户名、密码、smtpserver、popserver、storeserver 等信息,当用户请求过来是,先查询LDAP,如果是收信,找到该用户对应的smtp, 通过直接路由方式连接smtpserver,发信;如果是收信,找到对应的pop,连接popserver 下载邮件。

该架构解决了服务器处理瓶颈、数据存储IO 瓶颈。缺点是主要的任务分发通过邮件交换器完成。一但邮件交换器出问题,整个系统都将无法运行。

点击查看原图
5. 多机一域,双层负载均衡,存储分布。

为避免出现单点故障,将4 改良,增加多台邮件交换器和LDAP 服务器。邮件交换器通过DNS 轮询实现负载均衡,LDAP 服务器做成双机热备,任何一台有故障,另一台接替。存储服务器通过DRBD 实现两两镜像,避免出现存储故障。

这样一套系统,可以支持千万用户级。以2000 万用户为例,4000 并发量测算,按照处理能力:

Smtp:15 万用户/台,pop:30 万/台

需要:smtp:133 台,pop:66 台,共计约199 台PC 服务器。

这个方案的优点是没有瓶颈,可以无限扩充,缺点是需要很多存储服务器,资源上有些浪费。 点击查看原图
6. 多机一域,邮件功能服务器。

这种方案将以邮件服务器为单位,形成邮件服务器阵列。每台邮件服务器具有完整的邮件服务功能:smtp/pop3/imap/webmail 等。用户认证信息集中存放于LDAP 服务器,通过LDAP查找用户所在邮件服务器。

系统管理通过集中管控界面可以控制用户数据在服务器之间进行移动、复制、删除。邮件服务器进行两两互备。

设置独立的过滤服务器,主要过滤病毒、垃圾邮件和黄色图片。过滤服务器与邮件服务器之间通过socket 通讯,所有处理在内存完成,大大加快了处理速度。

该系统有如下特点:
(1) 这种方案系统造价比较低。以每台服务15 万用户计算,100 台服务器可以承
载1500 万用户。100 台服务器大约200 万-300 万人民币左右。
(2) 结构简单,布置方便,容易维护。
(3) 用户容量与服务器数量保持线性增长,扩容只需要增加服务器即可。
(4) 帐户在服务器直接动态可调,可迁移。
(5) 没有瓶颈,应付突发事件的能力强。
(6) 小面积的故障,不会影响整理系统。
基于以上优点,我们推荐优先考虑此方案。
点击查看原图

功能设计

功能上我们遵循如下设计理念:
1. 集中管控。
管理一个大型邮件系统,就象管理一台服务器那样简单。在单一管理界面下,通过web浏览器即可监控任何环节,完成大部分操作。
2. 自动化、智能化。
通过自动装置,如SMS 监控系统流量、内存、进程、磁盘空间等,设定报警阀值,超过阀值就会自动报警,防范于未然。
3. 最简化、最优化。
用简单办法完成简单的事情。简单意味着效率、稳定、可靠。

1
.主要功能:

基本功能:

Smtp,pop3,imap,webmail

增值模块:

SMS,MMS,NETFile,Photo,largeFile, Schedule,AntiSPAM,Anti-Virus, Anti-pronography, …

可选模块

语音邮件、视频邮件、邮件传真服务


2
.功能清单:

系统管理员

域管理员

普通用户(见263 需求)

1.统计、审计功能:

域用户管理

认证登录WebMail

2.监控功能:

邮件广播

用户session 信息初始化

3.服务器管理:远程开机、关机、启动服务、停止服务

域级过滤规则设定

显示首页

4.域管理:添加、变更、转移、删除

域级黑名单

保存图标位置

5.过滤服务器管理

用户邮箱大小、附件大小、邮件大小控制

邮件索引显示

6.DNS 管理

功能服务定制:sms/防病毒等

邮件移动

 

 

邮件排序

 

 

显示页码

 

 

回复信件

 

 

转发信件

 

 

删除信件

 

 

永久删除信件

 

 

显示信件原文

 

 

显示邮件内容

 

 

加入到地址本

 

 

加入到拒收列表

 

 

保存邮件

 

 

pop 取信

 

 

文件夹显示

 

 

文件夹删除

 

 

文件夹添加

 

 

文件夹重命名

 

 

查找邮件

 

 

发邮件页面显示

 

 

立即发送邮件

 

 

定时发送邮件

 

 

保存草稿

 

 

发送短信邮件

 

 

添加附件

 

 

删除附件

 

 

个人地址本显示

 

 

团体地址本显示

 

 

添加个人地址本

 

 

删除个人地址本

 

 

修改个人地址本

 

 

添加团体地址本

 

 

删除团体地址本

 

 

修改团体地址本

 

 

地址本排序

 

 

导出地址本

 

 

导入地址本

 

 

显示自动转发

 

 

修改自动转发

 

 

显示自动回复

 

 

修改自动回复

 

 

显示签名档

 

 

删除签名档

 

 

增加签名档

 

 

修改签名档

 

 

显示pop 收信设置

 

 

pop 收信设置修改

 

 

pop 收信设置增加

 

 

pop 收信设置删除

 

 

修改密码

 

 

显示参数设置

 

 

参数设置修改

 

 

显示多风格设置

 

 

多风格设置修改

 

 

显示反垃圾级别设置

 

 

反垃圾级别设置

 

 

显示杀毒状态

 

 

修改杀毒状态

 

 

显示过滤设置

 

 

邮件过滤设置添加

 

 

邮件过滤设置修改

 

 

邮件过滤设置删除

 

 

显示拒收设置

 

 

拒收设置修改

 

 

外挂一次认证

 

 

session 维护进程


3
.后端统计

统计类别

?统计项目

描述

系统资源

负载情况

5 分钟采样一次,自动绘制统计图

计图

CPU 使用情况

User,system,nice and idel

 

内存

Totoal,used,free

 

交换分区

Used ,free,cached,shared

 

硬盘

Total,used,free, inode

 

网络状况

收到字节数,发送字节数

邮件总量统计

邮件数量,总流量

统计每域、每用户收发邮件总量和字节数。

投递失败统计

统计投递失败的记录

按照每域、每用户统计

隔离邮件统计

邮件感染病毒,或者认定为垃圾邮件的

按照每域、每用户统计

短信统计

短信发送数统计

按照每域、每用户统计


4
.后端服务器管控功能

功能

描述

服务器节点远程管理

添加

向集群中添加一台服务器

 

除去

从集群中拿掉一台服务器

 

重启

远程重启服务器

 

关机

远程关机

服务远程管理

启动

远程启动某服务器服务进程

 

停止

远程停止服务器进程

监控、报警

设定监控项目,过载报警

发送SMS 到管理员手机

负载均衡管理

LVS,RR-DNS, LDAP

负载均衡远程调控

Tomcat 集群管理

添加节点、删除、更新

管理webmail 服务器

Session 服务器管理

集中管理用户session

发表在 article | 标签为 | 分布式系统邮件服务器架设已关闭评论

小规模增值税计算

一般合同金额都是指含税的,要换算成:
    不含税金额=含税金额/(1+税率)
    应交税=不含税金额*税率
 

含税计算方式:

例:20000

公式:金额/(1+3%)*3% 

计算:20000/1.03*0.03 = 582.52

         货款:20000/1.03 = 19417.48 (19417.475728155 )

         税款:19417.48(19417.475728155) * 0.03 = 582.52 (582.52427184465) 

         计:  19417.48 + 582.52 = 20000

发表在 finance | 小规模增值税计算已关闭评论

lucene 搜索语法

Lucene提供了丰富的API来组合定制你所需要的查询器,同时也可以利用Query Parser提供的强大的查询语法解析来构造你想要的查询器。本文章详细的介绍了Lucene的查询语法。通过Java语法分析器把一个查询字符串解析成 Lucene的查询器。在你选择使用Query Parser前,请考虑以下事项:

如果你打算在程序中拼接查询语法串然后再利用Query Parser转换,那么强烈建议你利用相应的API来自己构造查询器。也就是说,Query Parser是为手工输入高级查询设计的,而不是为程序拼接语法串而设计的。不分词的字段也最好通过相应的API添加到查询器中,而不是通过Query Parser。Query Parser 使用的Analyser分析器,作用是将用户手工输入的文本转化为相应的Term。如果一个字段的值是通过程序生成的(例如日期字段,关键词字段等),那么在查询的时候也应该保持前后一致,利用程序生成相应的格式来查询。

在查询的目标中,如果字段全部是程序生成的文本,(例如补齐的日期字段等),最好使用Query Parser以便查询的时候也是一致的格式。至于其它的,例如日期范围查询,关键字查询等,最好调用相应的API来构建查询器。目标字段中如果仅仅拥有有限的枚举值时,最好通过下拉列表提供给用户选择,然后利用TermQuery添加到查询器中,而不是而其拼接到查询字符串然后利用Query Parser来解析。

Terms 
一个查询将分解为若干Term以及操作符,有两种Term,其一是单一Term,其二为短语。单一Term是经过分析器分词后的最小单元,他就是一个简单的词,例如“Test”和“Hello”。短语则是一组被双引号括起来的一组词,例如:“Hello dolly”,多个Term可以通过布尔操作合并在一个更加复杂的查询器中。
注意:一般来说,创建索引的分析器和查询的分析器最好保持一致(当然也有特殊情况,比如单字索引,分词组合查询),所以选择一个不会干扰查询词的分析器是很重要的。

Fields 
Lucene支持多字段数据,当你在查询的时候你可以指定一个字段查询,也可以使用默认的字段。你可以使用 字段名 + “:” + 查询词来指定字段名搜索。举个例子,让我们假定Lucene的索引中含有两个字段,Title字段和Text字段,其中Text字段是默认字段,当你想找到一篇文档其中标题包含“The Right Way”同时文本中包含“go”,你可以输入:
title:"The Right Way" AND text:go 
或者:
title:" The Right Way " AND go 
如果字段是默认字段的话,在查询语法中可以不需要显式指定。注意,使用默认字段有可能会造成如下的结果:
title:Do it right 
以上查询将查找标题中含有“Do”,Text字段字段中含有“it”和“right”的文档,因为Text是默认字段,所以如果想要查找Title中完整包含的很用引号引起来。

Term Modifiers
Lucene支持在Term中使用通配符来支持模糊查询。

Wildcard Searches 
Lucene支持单个或者多个字符的通配符查询,匹配单一字符使用符号“?”,匹配多个字符使用符号“*”。
“?”通配符将查找所有满足通过一个字符替换后符合条件的文档。比如:搜索“test”和“text”你可以使用:
te?t 
“*”通配符将查询0个或者多个字符替换后符合条件的。举例来说,查询test,tests或者tester,你可以使用一下字符串来搜索:
test*
当然,你也可以将“*”放在字符的中间
te*t 
注意:你不能将“*”和“?”放在第一个字符来查询。(Lucene应该是出于性能考虑,所以不支持该功能)

Fuzzy Searches 
Lucene支持基于编辑距离算法的模糊搜索,你可以使用波浪符号“~”放在查询词的后面,比如搜索一个与“roam”拼写相近的词可以使用:
roam~ 
该查询将寻找类似“foam”和“roams”等的词语。也可以说是相似度查询。

Proximity Searches 
Lucene支持指定距离查询,你可以使用波浪号“~”加数字在查询词后。举例来说搜索“apache”和“jakarta”距离10个字符以内,你可以使用如下语法:
"jakarta apache"~10 
通过这个语法支持,我们可以单字索引,分词查询,分词完后,满足每个词的单字必须间距为0。这样可以保证100%的召回率,但是在索引方面将造成索引臃肿,同时查询速度也将在某程度上降低,一般来说,在150W文章数据到200W数据的时候性能将会明显的降低。

Range Searches 
范围查询允许你指定某个字段最大值和最小值,查询在二者之间的所有文档。范围查询可以包含或者不包含最大值和最小值,排序是按照字典顺序来排序的。
mod_date:[20020101 TO 20030101] 
这个将查找满足mode_date字段在大于等于20020101,小于等于20030101范围的所有文档,注意:范围查询并不是为日期字段专设的,你也可以对非日期字段进行范围查询。
title:{Aida TO Carmen} 
这个将查找所有标题在Aida和Carmen之间但不包含Aida和Carmen的文档。包含最大值和最小值的查询使用方括号,排除则使用花括号。

Boosting a Term 
Lucene支持给不同的查询词设置不同的权重。设置权重使用“^”符号,将“^”放于查询词的尾部,同时跟上权重值,权重因子越大,该词越重要。设置权重允许你通过给不同的查询词设置不同的权重来影响文档的相关性,假如你在搜索:
jakarta apache 
如果你认为“jakarta”在查询时中更加重要,你可以使用如下语法:
jakarta^4 apache 
这将使含有Jakarta的文档具有更高的相关性,同样你也可以给短语设置权重如下:
"jakarta apache"^4 "jakarta lucene" 
在默认情况下,权重因子为1,当然权重因子也可以小于1。

Boolean operators 
布尔操作符可以将多个Term合并为一个复杂的逻辑查询。Lucene支持AND,
+,OR,NOT, -作为操作符号。注意,所有的符号必须为大写。

OR 
OR操作符默认的连接操作符。这意味着,当没有给多个Term显式指定操作符时,将使用OR,只要其中一个Term含有,则可以查询出文档,这跟逻辑符号||的意思相似。假设我们查询一个文档含有“jakarta apache”或者“jakarta”时,我们可以使用如下语法:
"jakarta apache" jakarta 
或者
"jakarta apache" OR jakarta 

AND 
AND操作符规定必须所有的Term都出现才能满足查询条件,这跟逻辑符号&&意思相似。如果我们要搜索一个文档中同时含有“jakarta apache”和“jakarta lucene”,我们可以使用如下语法:
   "jakarta apache" AND "jakarta lucene" 

+
+操作符规定在其后的Term必须出现在文档中,也就是查询词中的MUST属性。举个例子来说,当我们要查询一个文档必须包含“jakarta”,同时可以包含也可以不包含“lucene”时,我们可以使用如下语法:
+jakarta apache 

NOT 
NOT操作符规定查询的文档必须不包含NOT之后的Term,这跟逻辑符号中的!相似。当我们要搜索一篇文档中必须含有“jakarta apache”同时不能含有“Jakarta lucene”时,我们可以使用如下查询;
"jakarta apache" NOT "jakarta lucene" 
注意:NOT操作符不能使用在单独Term中,举例来说,以下查询将返回无结果:
NOT "jakarta apache" 


-操作符排除了包含其后Term的文档,跟NOT有点类似,假设我们要搜索“Jakarta apache”但不包含“Jakarta lucene”时,我们使用如下语法:
"jakarta apache" -"jakarta lucene" 

Grouping 
Lucene支持使用圆括号来将查询表达式分组,这将在控制布尔控制查询中非常有用。举例来说:当搜索必须含有“website”,另外必须含有“jakarta”和“apache”之一,我们可以用如下语法:
(jakarta OR apache) AND website 
这种语法对消除歧义,确保查询表达式的正确性具有很大的意义。

Field Grouping 
Lucene支持对字段用圆括号来进行分组,当我们要查询标题中含有“return”和“pink ranther”时,我们可以使用如下语法:
title:(+return +"pink panther") 

Escaping Special Characters 
Lucene支持转义查询中的特殊字符,以下是Lucene的特殊字符清单:
+ - && || ! ( ) { } [ ] ^ " ~ * ? : \
转义特殊字符我们可以使用符号“\”放于字符之前。比如我们要搜索(1+1):2,我们可以使用如下语法:
\(1\+1\)\:2 

转自:http://hi.baidu.com/expertsearch/blog/item/8d4f7d355a2e413c5ab5f547.html

 

发表在 search | 标签为 | lucene 搜索语法已关闭评论

如何用hash关键字提高数据库性能

本文讨论了一个应用称为hash桶(hash bucket)或hash关键字(hash key)的字符串目录的优秀方法。了解如何应用hash关键字有助于提高性能并节省磁盘空间。

普通的SQL Server应用程序要求支持一个或几个长字符串搜索。(本文中,我们称超过20个字符的字符串为长字符串。)假如前端应用程序希望允许用户提供两个字符串;你启动一个执行这两个字符串搜索任务的存储程序,然后应用两个相关列目录对搜索进行优化。在小型的表格中,你可能注意不到产生的效果。但是,如果表格包含5 000万行,它就会影响存储程序与搜索性能。

应用称为hash关键字(引用单独一个hash)或hash桶(一个hash关键字集合)的字符串目录的优秀方法可大大节省磁盘空间并提高性能。

何为hashhash

hash是应用一个指定字符串算法的整数结果。有各式各样的hash算法,但最常用的是内置的SQL函数Checksum()。通常,你给这个函数一个字符串,它就返回一个整数(在大型表格中,我们不能保证这个整数的唯一性)。

数据库设计中的hash表格

假设在我们感兴趣的表格中有这些列:

列名

数据类型

名称

Varchar(50)

组名称

Varchar(50)

这两个列的多列目录每行会耗用50+50个字符,加上上面提到的5 000万行,这可是个相当大的难题。

基于这两个列的hash关键字相当的小,即每行四个字节。如果我们不将hash关键字存储在这一列的目录中,它还会更小。相反,我们应该建立一个计算列,该列的公式是这两个列的hash关键字,然后将那个列编入目录并忽视字符串对的目录。

用户(不管是人还是应用程序)查询感兴趣的值;然后我们将参数转换为hash关键字并搜索hash目录。副本集合要比引擎必须访问的行集合小得多,以便对查询值进行精确匹配。然后将hash关键字搜索与两个感兴趣的列的比较结合起来,隔离出一个小型的行子集,并对两个列进行检验,找出匹配值。基于整数列的搜索比基于长字符串关键字的搜索要快得多,同样也比复合关键字搜索快得多。

应用Checksum函数作hash关键字运算

尝试运行这段样本代码,它表明如何获得指定值或值组合的hash关键字:

USE AdventureWorks

SELECT Name, GroupName, Checksum(Name,GroupName)AS HashKey

FROM Adventureworks.HumanResources.Department

ORDER BY HashKey

所得的结果显示在下表中(为求简洁,只选用了10个结果)。

名称

组名称

hash关键字

工具设计

研究与开发

-2142514043

生产

制造

-2110292704

发货与收货

存货管理

-1405505115

购买

存货管理

-1264922199

文件控制

质量保证

-922796840

信息服务

总执行管理

-904518583

质量保证

质量保证

-846578145

销售

销售与营销

-493399545

生产控制

制造

-216183716

营销

销售与营销

-150901473

在现实环境中,你可以建立一个调用Name_GroupName_hb的计算列。假设前端传入名称(Name)与组名称(GroupName)的目标值,你就可以用下列代码来处理这一问题:

CREATE PROCEDURE DemoHash

( ?@Name Varchar(50), ?@GroupName Varchar(50)

)

AS

-- USE AdventureWorks

DECLARE @id as int SET @id = Checksum(@Name,@GroupName)

SELECT * FROM Adventureworks.HumanResources.Department

WHERE HashKey = @id

AND Name = @Name

AND GroupName = @GroupName

想象一下,在一个5 000万行的表格中,返回了100行指定的hash关键字。由于这两个列没有其它的目录,查询优化器就应用hash桶目录。这样就可以快速地隔离出100个感兴趣的行。然后我们访问这些行,检验名称(Name)与组名称(GroupName)列来进行精确匹配。这样就大大提高了性能,同时节省了大量的磁盘空间。

引例假设搜索目标存在于一个单独的表格中。假如要从多个表格中选择目标来进行搜索,也可以应用同样的技巧。只需建立一个连接表格的表格函数,然后建立一个hash不同表格列的目录即可。

结论

在相对较小的表格中,建立一个目录hash桶对于提高性能可能没有太大的作用,但这样做可节省磁盘空间。如果你使用大型的表格,本技巧就极为实用。

Arthur Fuller从事数据库应用程序开发20余年。在Access ADP、微软SQL 2000MySQL.NET方面有丰富的经验。

 

发表在 technologys | 如何用hash关键字提高数据库性能已关闭评论

索引与散列

11-1 什么是静态索引结构?什么是动态索引结构?它们各有哪些优缺点?

 

 

11-2 设有10000个记录对象, 通过分块划分为若干子表并建立索引, 那么为了提高搜索效率, 每一个子表的大小应设计为多大?

 

 

11-3如果一个磁盘页块大小为1024 (=1K) 字节,存储的每个记录对象需要占用16字节,其中关键码占4字节,其它数据占12字节。所有记录均已按关键码有序地存储在磁盘文件中,每个页块的第1个记录用于存放线性索引。另外在内存中开辟了256K字节的空间可用于存放线性索引。试问:

(1) 若将线性索引常驻内存,文件中最多可以存放多少个记录?(每个索引项8字节,其中关键码4字节,地址4字节)

(2) 如果使用二级索引,第二级索引占用1024字节(有128个索引项),这时文件中最多可以存放多少个记录?

  

 

   397

 Hello World!

    82

 XYZ

  1038

 This string is rather long

  1037

 This is Shorter

    42

 ABC

  2222

 Hello new World!

11-4 假设在数据库文件中的每一个记录是由占2个字节的整型数关键码和一个变长的数据字段组成。数据字段都是字符串。为了存放右面的那些记录,应如何组织线性索引?

 

      

11-5 设有一个职工文件:

  记录地址

  职工号

   

  性别

    

  年龄

  籍贯

 月工资()

     10032

   034

  刘激扬

  

    

   29

  山东

720.00

     10068

   064

  蔡晓莉

  

    

   32

  辽宁

1200.00

     10104

   073

   

  

   实验员

   26

  广东

480.00

     10140

   081

   

  

    

   36

  北京

1400.00

     10176

   092

  卢声凯

  

    

   28

  湖北

720.00

     10212

   123

  林德康

  

  行政秘书

   33

  江西

480.00

     10248

   140

  熊南燕

  

    

   27

  上海 

780.00

     10284

   175

   

  

   实验员

   28

  江苏

480.00

     10320

   209

  袁秋慧

  

    

   24

  广东

720.00

其中,关键码为职工号。试根据此文件,对下列查询组织主索引和倒排索引,再写出搜索结果关键码。(1) 男性职工;(2) 月工资超过800元的职工;(3) 月工资超过平均工资的职工;(4) 职业为实验员和行政秘书的男性职工;(5) 男性教师或者年龄超过25岁且职业为实验员和教师的女性职工。

 

11-6 倒排索引中的记录地址可以是记录的实际存放地址,也可以是记录的关键码。试比较这两种方式的优缺点。

 

11-7 m = 2的平衡m路搜索树是AVL树,m = 3的平衡m路搜索树是2-3树。它们的叶结点必须在同一层吗?mB树是平衡m路搜索树,反过来,平衡m路搜索树一定是B树吗?为什么?

 

11-8 下图是一个3B树。试分别画出在插入65154030之后B树的变化。

点击查看原图

11-9 下图是一个3B树。试分别画出在删除5040之后B树的变化。

点击查看原图

11-10 对于一棵有1999999个关键码的199B树,试估计其最大层数(不包括失败结点)及最小层数(不包括失败结点)

 

11-11 给定一组记录,其关键码为字符。记录的插入顺序为 { C, S, D, T, A, M, P, I, B, W, N, G, U, R, K, E, H, O, L, J },给出插入这些记录后的4B+树。假定叶结点最多可存放3个记录。

11-12 设有一棵B+树,其内部结点最多可存放100个子女,叶结点最多可存储15个记录。对于1, 2, 3, 4, 5层的B+树,最多能存储多少记录,最少能存储多少记录。

11-13设散列表为HT[13], 散列函数为 H (key) = key %13。用闭散列法解决冲突, 对下列关键码序列 12, 23, 45, 57, 20, 03, 78, 31, 15, 36 造表。

       (1) 采用线性探查法寻找下一个空位, 画出相应的散列表, 并计算等概率下搜索成功的平均搜索长度和搜索不成功的平均搜索长度。

       (2) 采用双散列法寻找下一个空位, 再散列函数为 RH (key) = (7*key) % 10 + 1, 寻找下一个空位的公式为 Hi = (Hi-1 + RH (key)) % 13, H1 = H (key)。画出相应的散列表, 并计算等概率下搜索成功的平均搜索长度。

 

11-14 设有150个记录要存储到散列表中, 要求利用线性探查法解决冲突, 同时要求找到所需记录的平均比较次数不超过2次。试问散列表需要设计多大? a是散列表的装载因子,则有

                    

 

11-15 若设散列表的大小为m,利用散列函数计算出的散列地址为h = hash(x)

       (1) 试证明:如果二次探查的顺序为(h + q2), (h + (q-1)2), , (h+1), h, (h-1), , (h-q2),其中, q = (m-1)/2。因此在相继被探查的两个桶之间地址相减所得的差取模(%m)的结果为

              m-2, m-4, m-6, , 5, 3, 1, 1, 3, 5, , m-6, m-4, m-2

       (2) 编写一个算法,使用课文中讨论的散列函数h(x)和二次探查解决冲突的方法,按给定值x来搜索一个大小为m的散列表。如果x不在表中,则将它插入到表中。

11-16 编写一个算法,以字典顺序输出散列表中的所有标识符。设散列函数为hash(x) = x中的第一个字符,采用线性探查法来解决冲突。试估计该算法所需的时间。

11-17 设有1000个值在110000的整数,试设计一个利用散列方法的算法,以最少的数据比较次数和移动次数对它们进行排序。

11-18 设有15000个记录需放在散列文件中,文件中每个桶内各页块采用链接方式连结,每个页块可存放30个记录。若采用按桶散列,且要求搜索到一个已有记录的平均读盘时间不超过1.5次,则该文件应设置多少个桶?  

 

11-19 用可扩充散列法组织文件时,若目录深度为d,指向某个页块的指针有n个,则该页块的局部深度有多大?

 

11-20 设一组对象的关键码为 { 69, 115, 110, 255, 185, 143, 208, 96, 63, 175, 160, 99, 171, 137, 149, 229, 167, 121, 204, 52, 127, 57, 1040 }。要求用散列函数将这些对象的关键码转换成二进制地址,存入用可扩充散列法组织的文件里。定义散列函数为hash(key) = key % 64, 二进制地址取6位。设每个页块可容纳4个对象。要求按10 .4节介绍的方法设置目录表的初始状态,使目录表的深度为3。然后按题中所给的顺序,将各个对象插入的可扩充散列文件中。试画出每次页块分裂或目录扩充时的状态和文件的最后状态。

 

发表在 technologys | 索引与散列已关闭评论

bind nsupdate动态dns更新

注: 可用 ixfr+nsupdate+rndc 更新域

    rndc reconfig;

    rndc reload

 

nsupdate是一个动态DNS更新工具.可以向DNS服务器提交更新记录的请求.它可以从区文件中添加或删除资源记录,而不需要手动进行编辑区文件.
下面是使用方法:

nsupdate [ -d ] [ [ -y keyname:secret ] [ -k keyfile ] ] [ -v ]
[ filename ]

-d 调试模式.

-k 从keyfile文件中读取密钥信息.

-y keyname是密钥的名称,secret是以base64编码的密钥.

-v 使用TCP协议进行nsupdate.默认是使用UDP协议.

输入格式:
nsupdate可以从终端或文件中读取命令.每个命令一行.一个空行或一个”send”命令,则会将先前
输入的命令发送到DNS服务器上.

命令格式:
server servername [ port ]
发送请求到servername服务器的port端口.如果不指定servername,nsupdate将把请求发送给
当前去的主DNS服务器.
如:
> server 192.168.0.1 53

local address [ port ]
发送nsupdate请求时,使用的本地地址和端口.

zone zonename
指定需要更新的区名.

class classname
指定默认类别.默认的类别是IN.

key name secret
指定所有更新使用的密钥.

prereq nxdomain domain-name
要求domain-name中不存在任何资源记录.

prereq yxdomain domain-name
要求domain-name存在,并且至少包含有一条记录.

prereq nxrrset domain-name [ class ] type
要求domain-name中没有指定类别的资源记录.

prereq yxrrset domain-name [ class ] type
要求存在一条指定的资源记录.类别和domain-name必须存在.

update delete domain-name [ ttl ] [ class ] [ type [ data... ] ]
删除domain-name的资源记录.如果指定了type和data,仅删除匹配的记录.

update add domain-name ttl [ class ] type data…
添加一条资源记录.

show
显示自send命令后,所有的要求信息和更新请求.

send
将要求信息和更新请求发送到DNS服务器.等同于输入一个空行.

nsupdate示例:
# nsupdate
> server 127.0.0.1
> update delete www.centos.bz A
>
> update add www.centos.bz 80000 IN A 192.168.0.2
> update add 2.0.168.192.in-addr.arpa 80000 PTR A www.centos.bz
> send
> quit

 

---------------------------------------------------------------------------------------------

LAMP+bind9下实现DDNS

生成文件,并调用命令nsuodate -v filename来实现ddns。
1 lamp安装
这个就不用多说了,我安装的是ubuntu的6.0.6.1server+mysql+php
apt-get到最新版
2 webmin
俺linux刚刚入门,好多命令行还不熟。服务器不安装gui,用用webmin算是gui吧。
3 php-cli
没有安装?用apt-get 安装。
4 bind9及配置
用webmin配置bind
4.1 创建新的主区域(zone)比如cags.org.cn
4.2 修改named.conf.local 在zone cags.org.cn添加这么一行:

allow-update {127.0.0.1;};

意思是这个zone在本地可以update。
5 mysql建表
用5个字段实现最基本的功能
id 自增类型,当主键也当dns的序号用
user 用户名
pass 密码
time 更新的时间
ip 客户端的ip
sql语句如下:
CREATE TABLE `ddns` (
`id` int(11) unsigned NOT NULL auto_increment,
`user` char(4) NOT NULL,
`password` char(41) NOT NULL,
`time` bigint(20) NOT NULL default '0',
`ip` char(15) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `user` (`user`),
KEY `password` (`password`),
KEY `time` (`time`),
KEY `ip` (`ip`)
) ENGINE=MyISAM DEFAULT
6 php网页文件ddns.php(这个就不用注释了吧,跟大白话似的)
<?php
$user= $_REQUEST["user"];
$pass= $_REQUEST["pass"];
$time= time();
$ip = $_SERVER["REMOTE_ADDR"];

$link = @mysql_connect('localhost', 'root', '');
@mysql_select_db('ddns');

$query="select count(user) from ddns where user='";
$query.=$user;
$query.="' and password=password('";
$query.=$pass;
$query.="') group by user";

$result=@mysql_query($query);
$row = mysql_fetch_array($result,MYSQL_NUM);
if ($row[0]==1){
$query="update ddns set time=$time,ip='$ip' where user='$user'";
@mysql_query($query);
}
@mysql_free_result($result);
@mysql_close($link);
?>
建立完文件之后用http://ddns-server-ip/ddns.php?user=XXX&pass=YYY就可以获取客户端ip地址并记录到ddns表中,并且记下了客户端访问的时间。
7 php-cli文件
这个多废话几句:
7.1 所需要的记录都在ddns表中。在这里规定每隔60秒更新一次。
7.2 如果60秒客户端没有刷新的话,就更改其ip为127.0.0.1
7.3 生成nsupdate所需的文件。文件包括两部分:
7.3.1 失效的用户即ip为127.0.0.1的
7.3.2 有效的用户:更新时间在60秒之内并且ip不为127.0.0.1的
7.4 调用nsupdate命令
文件如下update.php:
#!/usr/bin/php
<?php
$time=time();

$link = @mysql_connect('localhost', 'root', '');
@mysql_select_db('ddns');

$handle = fopen("/tmp/file.txt", "w");
$str="server 127.0.0.1\r\n";
$str.="zone cags.org.cn\r\n";
@fwrite($handle,$str);

$query="select user,id,ip from ddns where $time-time>0 and $time-time<=60";
$result=@mysql_query($query);
while($row = @mysql_fetch_array($result,MYSQL_NUM)){
$str="update delete $row[0].cags.org.cn A\r\n";
$str.="update add $row[0].cags.org.cn $row[1] IN A $row[2] \r\n";
@fwrite($handle, $str);
}

$query="update ddns set ip='127.0.0.1' where $time-time>60";
@mysql_query($query);

$query="select user,id,ip from ddns where ip='127.0.0.1'";
$result=@mysql_query($query);
while($row = @mysql_fetch_array($result,MYSQL_NUM)){
$str="update delete $row[0].cags.org.cn A\r\n";
$str.="update add $row[0].cags.org.cn $row[1] IN A $row[2] \r\n";
@fwrite($handle, $str);
}

$str="send \r\n";
@fwrite($handle,$str);
@fclose($handle);
exec('nsupdate -v /tmp/file.txt');

@mysql_free_result($result);
@mysql_close($link);
?>

8 定时执行文件php-cli
用webmin 添加corn 任务调度每分钟执行一次

9 用dig命令查看更新是否有效:
dig @127.0.0.1 cags.org.cn axfr

 

另一调用示例:

nsupdate -v << EOF
server 127.0.0.1
zone test.com
update delete test2.test.com
update delete test3.test.com
send
EOF

nsupdate -v << EOF
server 127.0.0.1
zone test.com
update add test2.test.com 30 IN A 127.0.0.2
update add test3.test.com 30 IN A 127.0.0.3
show
send
EOF

发表在 technologys | 标签为 , | bind nsupdate动态dns更新已关闭评论

VNC 安装

1、安装
yum install vnc*
2、启动
/etc/init.d/vncserver start
Starting VNC server: no displays configured [ OK ]
3、配置用户名
CODE:[root@localhost ~]# vi /etc/sysconfig/vncservers
# The VNCSERVERS variable is a list of display:user pairs.
#
# Uncomment the line below to start a VNC server on display :1
# as my 'myusername' (adjust this to your own). You will also
# need to set a VNC password; run 'man vncpasswd' to see how
# to do that.
#
# DO NOT RUN THIS SERVICE if your local area network is
# untrusted! For a secure way of using VNC, see
# URL:http://www.uk.research.att.com/vnc/sshvnc.html

# VNCSERVERS="1:myusername"
VNCSERVERS="1:root" (注意:root是CentOS用户名)
如果建2个,可以用VNCSERVERS="1:root 2:linglong"来配置
3.用vncpasswd创建一个vnc的口令

注意这将同时在你的home目录下,创建一个隐藏的目录.vnc,其中有一个文件passwd保存着你的vnc口令.
CODE:
[root@localhost ~]# vncpasswd
Password:
Verify:
[root@localhost ~]# ls -d .vnc
.vnc
[root@localhost ~]# ls .vnc
passwd

 
----------------------------------------------------------------------

VNCServer配置
redhat 一般都自动安装了vncserver了 只要在服务列表中选中启动一下就可以.
通过编辑文件$HOME/.vnc/xstartup来启动你喜欢的窗口管理器。使用
startkde & 来启动KDE,使用 gnome-session & 来启动GNOME.

首次创建 ~/.vnc/xstartup 时,指定的窗口管理器是 twm ,它是一个极小的窗口管理器,几乎每台 X Window 系统机器上都有 twm。twm 不具备完整“桌面管理器”(象 KDE、GNOME 或 WindowMaker)的大部分花哨功能。下面是修改过的示例:

#!/bin/sh

[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/ .Xresources ]&& xrdb $HOME/.Xresources
xsetroot - solid grey
vncconfig - iconic &
#xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
#twm &
#exec wmaker
#exec startkde

gnome-session &

上面的示例中,注释掉了缺省 twm 和 xterm 的缺省启动。配置了这个桌面来避免背景和标题栏上的颜色渐变,并使用极少的动画效果。

关闭服务器上自己的vnc连接
vncserver -kill :桌面号

开机自动运行vncserver
1.设置vncserver启动脚本(/etc/init.d/vncserver)实现系统自启动时启动vncserver.

2.编辑/etc/sysconfig/vncservers

VNCSERVERS="1:user1"
ARGS="-geometry 800x600 -alwaysshared "

在ARGS 中修改"800x600"来适应自己的X桌面实际参数配置。可以在这里添加任何其他VNC服务器参数配置。在VNCSERVERS中修改 user1 为你希望运行VNC桌面的用户。VNCSERVERS中的1表示VNC以桌面1运行,如果希望添加其他的桌面,可以修改配置如下:

VNCSERVERS="1:user1 2:user2 3:user3"

3.设置vnc server的访问密码
vncpasswd

在RedHat系统上,使用以下命令启动VNC:
/etc/init.d/vncserver start

----------------------------------------------2--------------------------------------------------

Linux系统远程桌面(VNC)配置方法

Linux默认安装了VNC服务,为了以后方便使用,可在ntsysv里设置vnc服务为开机自动启动。

如果系统安装了防火墙,建议关掉或者加入vnc的访问规则。(service iptables stop)

二、开始配置

命令:vncserver

第一次使用此命令会提示你输入访问口令,两次口令后,vncserver即可正常工作。

可以使用最常用工具VNC Viewer访问远程桌面了。

三、显示图形化界面

不知是出于什么考虑,第二步后无法看到图形化界面,但改起来超简单,修改一个参数就OK了。

用第二步时的用户登录,修改一下VNC的启动文件

vi .vnc/xstartup

将最后一行“twm &”修改为“gnome-session &”

重启vnc服务,kill掉刚才的进程,再新启一个VNC即可。

service vncserver restart

vncserver -kill :1

vncserver

======================================================

Xvnc in Linux RH6.2 problem


When you unzip vnc-3.3.3r1_x86_linux_2.0.tgz a folder called
vnc_x86_linux_2.0 is created.

First of all, that folder contains a readme file that explains everything I'm
about to tell you.:-)

There is only a couple of steps that need to be taken in linux before you can
./vncserver....

#1 Make sure that /usr/local/bin is in your path.  If it isn't add it to the
PATH statement in your .bash_profile.  A portion of your .bash_profile could
look like this ....
PATH=/usr/local/bin:$PATH:$HOME/bin

After you save this file you need to have your bash re-read it.  Type su -l
root.  To verify that you path is updated type echo $PATH

#2 cd to the vnc_x86_linux_2.0 directory.  Type the following
cp vncviewer vncserver vncpasswd Xvnc /usr/local/bin

#3 If you want to use the Java VNC viewer (http, 58xx) do the following
mkdir -p /usr/local/vnc/classes
cp classes/* /usr/local/vnc/classes

That's It!

Get back to /root and type vncserver not ./vncserver you will be prompted for
a password.

At this point vnc created a .vnc folder in your root directory.

You should be able to connect with no problem.

Nathan Lenz wrote:

> when running(as root):> ./vncserver> > I get the error:> vncserver: couldn't find "Xvnc" on your PATH.> > Is there any simple instructions on installing the vnc server on a default> linux instalation...> > Nathan Lenz> ---------------------------------------------------------------------> To unsubscribe, send a message with the line: unsubscribe vnc-list> to majordomo "at" uk.research.att.com> See also: http://www.uk.research.att.com/vnc/intouch.html > --------------------------------------------------------------------- --
Regards
发表在 article | 标签为 | VNC 安装已关闭评论

CentOS/RedHat常用到的查看系统命令

# uname -a 
 
# 查看内核/操作系统/CPU信息
# head -n 1 /etc/issue   # 查看操作系统版本
# cat /proc/cpuinfo      # 查看CPU信息
# hostname               # 查看计算机名
# lspci -tv              # 列出所有PCI设备
# lsusb -tv              # 列出所有USB设备
# lsmod                  # 列出加载的内核模块
# env                    # 查看环境变量
  www.2cto.com  
资源
# free -m                # 查看内存使用量和交换区使用量
# df -h                  # 查看各分区使用情况
# du -sh <目录名>        # 查看指定目录的大小
# grep MemTotal /proc/meminfo   # 查看内存总量
# grep MemFree /proc/meminfo    # 查看空闲内存量
# uptime                 # 查看系统运行时间、用户数、负载
# cat /proc/loadavg      # 查看系统负载
 
磁盘和分区
# mount | column -t      # 查看挂接的分区状态
# fdisk -l               # 查看所有分区
# swapon -s              # 查看所有交换分区
# hdparm -i /dev/hda     # 查看磁盘参数(仅适用于IDE设备)
# dmesg | grep IDE       # 查看启动时IDE设备检测状况
 
网络
# ifconfig               # 查看所有网络接口的属性
# iptables -L            # 查看防火墙设置
# route -n               # 查看路由表
# netstat -lntp          # 查看所有监听端口
# netstat -antp          # 查看所有已经建立的连接
# netstat -s             # 查看网络统计信息
 
进程
# ps -ef                 # 查看所有进程
# top                    # 实时显示进程状态
 
用户
# w                      # 查看活动用户
# id <用户名>            # 查看指定用户信息
# last                   # 查看用户登录日志
# cut -d: -f1 /etc/passwd   # 查看系统所有用户
# cut -d: -f1 /etc/group    # 查看系统所有组
# crontab -l             # 查看当前用户的计划任务
  www.2cto.com  
服务
# chkconfig --list       # 列出所有系统服务
# chkconfig --list | grep on    # 列出所有启动的系统服务
 
程序
# rpm -qa                # 查看所有安装的软件包
发表在 technologys | 标签为 , | CentOS/RedHat常用到的查看系统命令已关闭评论

关键字高亮JS

        //高亮
        this.highlightKeys = searchData.content.split(' ');
        this.highlightLength = this.highlightKeys.length;
        this.highlights = [];
        this.highlightChilds($('tweetRegion').childNodes);
        this.highlightChilds($('searchTweetPageUserList').childNodes);
        $A(this.highlights).each(function(item) {
            var tag = document.createElement('span');
            item.tag.parentNode.replaceChild(tag, item.tag);
            tag.innerHTML = item.html;
        });



    highlightChilds: function(elements) {
        var length = elements.length;
        if (length == 0) return;
        var value = "";
        var i, j, exist;
        for (i = 0; i < length; i++) {
            if (elements[i].nodeType == 3) {
                value = elements[i].nodeValue.toString().trim();
                exist = false;
                if (value != "") {
                    for (j = 0; j < this.highlightLength; j++) {
                        if (value.indexOf(this.highlightKeys[j]) > -1) {
                            exist = true;
                            value = value.replace(this.highlightKeys[j], '<span style="color:#CA4004;">' + this.highlightKeys[j] + '</span>')
                        }
                    }
                    if (exist) {
                        this.highlights.push({ tag: elements[i], html: value });
                    }
                }
            }
            this.highlightChilds(elements[i].childNodes);
        }
    },
发表在 technologys | 标签为 | 关键字高亮JS已关闭评论