欢迎大家学习交流
  • 键盘实现WordPress翻页

    2011-10-27, 作者:admini | 分类目录:web技术 | 标签:
  • php调用mysql存储过程的两种方法

    2011-10-27, 作者:admini | 分类目录:服务器 | 标签:
  • session共享之mysql共享

    2011-11-30

    基于mysql的实现方式代码如下:

    <?php
    /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
    //===========================================
    // 程序:   mysql-Based Session Class
    // 功能:   基于mysql存储的 Session 功能类
    // 作者:    yejr
    // 网站:    http://imysql.cn
    // 时间:    2007-01-05
    //===========================================
    
    /**
     * 类名:    MySQL Session Class
     * 功能:    自主实现基于MySQL HEAP表存储的 Session 功能
     * 描述:    这个类就是实现Session的功能,基本上是通过设置客户端的Cookie来保存SessionID,
     *          然后把用户的数据保存在服务器端,最后通过Cookie中的Session Id来确定一个数据是否是用户的,
     *          然后进行相应的数据操作
     *
     * 注意: 本类调用了PEAR::DB类,如果有自己的DB类,则可以稍微修改一下代码
     *
     * 备注:数据表初始化SQL语句:
     * CREATE TABLE `sessions` (
     * `sid` varchar(32) NOT NULL default '',
     * `session` longtext,
     * `flush_dt` int unsigned NOT NULL default '0',
     * PRIMARY KEY  (`sid`),
     * KEY `last` (`flush_dt`)
     * ) ENGINE=HEAP;
     */
    
    //设定 SESSION 有效时间,单位是 秒
    define('SESS_LIFTTIME', 3600);
    define('DB_DSN', 'mysql://root:@localhost/test');
    define('DB_NAME','test');
    
    require_once('DB.php');
    
    $gDb    = new DB;
    $gDb    = DB::connect(DB_DSN, TRUE);
    
    if (PEAR::isError($gDb))
    {
        die($gDb->getMessage());
    }
    
    if (!defined('MySQLSession'))
    {
        define('MySQLSession',    TRUE);
    
    class Usess
    {
        static  $mSessSavePath;
        static  $mSessName;
        static  $mSessMaxTime;
        static  $mTblSess   = 'sessions';
        static  $mTblSessMap;
        static  $mDb;
    
        // {{{ 初始化构造函数
        /**
         * 构造函数
         *
         * @param string $login_user    登录用户
         * @param int $login_type       用户类型
         * @param string $login_sess    登录Session值
         * @return Esession
         */
        public function __construct()
        {
            self::$mSessMaxTime = SESS_LIFTTIME;
    
            self::$mTblSessMap  = array(
                    'sid'   => 'sid',
                    'data'  => 'session',
                    'last'  => 'flush_dt',
                    );
        }
        // }}}
    
        /** {{{ sessOpen($pSavePath, $name)
         *
         * @param   String  $pSavePath
         * @param   String  $pSessName
         *
         * @return  Bool    TRUE/FALSE
         */
        public function sessOpen($pSavePath = '', $pSessName = '')
        {
            global $gDb;
    
            self::$mDb  = $gDb;
            self::$mSessSavePath    = $pSavePath;
            self::$mSessName        = $pSessName;
    
            self::sessGc();
    
            return TRUE;
        }
        // }}}
    
        /** {{{ sessClose()
         *
         * @param   NULL
         *
         * @return  Bool    TRUE/FALSE
         */
        public function sessClose()
        {
            return TRUE;
        }
        // }}}
    
        /** {{{ sessRead($wSid)
         *
         * @param   String  $wSid
         *
         * @return  Bool    TRUE/FALSE
         */
        public function sessRead($wSid = '')
        {
            global $db;
    
            $wSql    = sprintf("SELECT * FROM `%s`.`%s` WHERE `%s` = '%s';",
                            DB_NAME,
                            self::$mTblSess,
                            self::$mTblSessMap['sid'],
                            $wSid
                    );
    
            //这里一定要用 DB_FETCHMODE_ASSOC,否则取回的数组只能用数字做下标
            if (!PEAR::isError($row = self::$mDb->getRow($wSql, null, DB_FETCHMODE_ASSOC)))
            {
                //session已经存在了
                if (is_array($row) && 1 <= count($row))
                {
                    return $row[self::$mTblSessMap['data']];
                }
                else
                {
                    $wSql    = sprintf("INSERT INTO `%s`.`%s` VALUES ('%s', '', UNIX_TIMESTAMP(NOW()));",
                                    DB_NAME,
                                    self::$mTblSess,
                                    $wSid
                            );
    
                    if (!PEAR::isError(self::$mDb->query($wSql)))
                    {
                        return TRUE;
                    }
                }
            }
    
            return FALSE;
        }
        // }}}
    
        /** {{{ sessWrite($wSid, $wData)
         *
         * @param   String  $wSid
         * @param   String  $wData
         *
         * @return  Bool    TRUE/FALSE
         */
        public function sessWrite($wSid = '', $wData = '')
        {
            $wData  = mysql_escape_string($wData);
    
            $wSql    = sprintf("UPDATE `%s`.`%s` SET `%s` = '%s', `%s` = UNIX_TIMESTAMP(NOW()) WHERE `%s` = '%s';",
                            DB_NAME,
                            self::$mTblSess,
                            self::$mTblSessMap['data'],
                            $wData,
                            self::$mTblSessMap['last'],
                            self::$mTblSessMap['sid'],
                            $wSid
                    );
    
            if (!PEAR::isError(self::$mDb->query($wSql)))
            {
                return TRUE;
            }
    
            return FALSE;
        }
        // }}}
    
        /** {{{ sessDestroy($wSid)
         *
         * @param   String  $wSid
         *
         * @return  Bool    TRUE/FALSE
         */
        public function sessDestroy($wSid = '')
        {
            $wSql    = sprintf("DELETE FROM `%s`.`%s` WHERE `%s` = '%s';",
                            DB_NAME,
                            self::$mTblSess,
                            $wSid
                    );
    
            if (!PEAR::isError(self::$mDb->query($wSql)))
            {
                return TRUE;
            }
    
            return FALSE;
        }
        // }}}
    
        /** {{{ sessGc()
         *
         * @param   NULL
         *
         * @return  Bool    TRUE/FALSE
         */
        public function sessGc()
        {
            global $db;
    
            //计算出过期时间
            $last   = time() - self::$mSessMaxTime;
    
            $wSql    = sprintf("DELETE FROM `%s`.`%s` WHERE `%s` < $last;", DB_NAME, self::$mTblSess, self::$mTblSessMap['last']);
    
            if (!PEAR::isError(self::$mDb->query($wSql)))
            {
                return TRUE;
            }
    
            return FALSE;
        }
        // }}}
    
        /** {{{ initSess()
         *
         * @param   NULL
         *
         * @return  Bool    TRUE/FALSE
         */
        public function initSess()
        {
            $domain = '';
    
            //不使用 GET/POST 变量方式
            ini_set('session.use_trans_sid',    0);
    
            //设置垃圾回收最大生存时间
            ini_set('session.gc_maxlifetime',   SESS_LIFTTIME);
    
            //使用 COOKIE 保存 SESSION ID 的方式
            ini_set('session.use_cookies',      1);
            ini_set('session.cookie_path',      '/');
    
            //多主机共享保存 SESSION ID 的 COOKIE
            ini_set('session.cookie_domain',    $domain);
    
            //将 session.save_handler 设置为 user,而不是默认的 files
            session_module_name('user');
    
            //定义 SESSION 各项操作所对应的方法名:
            session_set_save_handler(
                    array('Usess', 'sessOpen'),   //对应于静态方法 My_Sess::open(),下同。
                    array('Usess', 'sessClose'),
                    array('Usess', 'sessRead'),
                    array('Usess', 'sessWrite'),
                    array('Usess', 'sessDestroy'),
                    array('Usess', 'sessGc')
                    );
            session_start();
    
            return TRUE;
        }
        // }}}
    
    }//end class
    
    }//end define
    
    $sess   = new Usess;
    $sess->initSess();
    ?>
    
    作者:admini | 分类目录:服务器 | 标签:
  • 如何去除数据表中的重复数据

    2011-11-30

    通常情况下,一个我们在做一个产品的时候,一开始可能由于设计考虑不周或者程序写的不够严谨,某个字段上的值产生重复了,但是又必须去掉,这个时候就稍微麻烦了一点,直接加一个 UNIQUE KEY 肯定是不行了,因为会报错。
     现在,我们来采用一种变通的办法,不过可能会丢失一些数据 :)

     在这里,我们设定一个表,其结构如下:

    mysql> desc `user`;
    +-------+------------------+------+-----+---------+----------------+
    | Field | Type             | Null | Key | Default | Extra          |
    +-------+------------------+------+-----+---------+----------------+
    | id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
    | name  | char(10)         | NO   |     |         |                |
    | extra | char(10)         | NO   |     |         |                |
    +-------+------------------+------+-----+---------+----------------+
    

     原来表中的数据假定有以下几条:

    mysql> SELECT * FROM `user`;
    +----+-------+--------+
    | id | name  | extra  |
    +----+-------+--------+
    |  1 | user1 | user1  |
    |  2 | user2 | user2  |
    |  3 | user3 | user3  |
    |  4 | user4 | user4  |
    |  5 | user5 | user5  |
    |  6 | user3 | user6  |
    |  7 | user6 | user7  |
    |  8 | user2 | user8  |
    |  9 | USER2 | user9  |
    | 10 | USER6 | user10 |
    +----+-------+--------+
    

    1、将原来的数据导出

    mysql>SELECT * INTO OUTFILE '/tmp/user.txt' FROM `user`;
    

    2、清空数据表

    mysql>TRUNCATE TABLE `user`;
    

    3、创建唯一索引,并且修改 `name` 字段的类型为 BINARY CHAR 区分大小写

    mysql> ALTER TABLE `user` MODIFY `name` CHAR(10) BINARY NOT NULL DEFAULT '';
    
    mysql> TRUNCATE TABLE `user`;
    
    mysql> ALTER TABLE `user` ADD UNIQUE KEY ( `name` );
    

    现在来看看新的表结构:

    mysql> desc user;
    +-------+------------------+------+-----+---------+----------------+
    | Field | Type             | Null | Key | Default | Extra          |
    +-------+------------------+------+-----+---------+----------------+
    | id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
    | name  | char(10)         | NO   | UNI |         |                |
    | extra | char(10)         | NO   |     |         |                |
    +-------+------------------+------+-----+---------+----------------+
    

    4、把数据导回去,在这里,有两种选择:新的重复记录替换旧的记录,只保留最新的记录 或者是 新的记录略过,只保留最旧的记录

    mysql> LOAD DATA INFILE '/tmp/user.txt' REPLACE INTO TABLE `user`;
    Query OK, 10 rows affected (0.00 sec)
    Records: 8  Deleted: 2  Skipped: 0  Warnings: 0
    
    mysql> SELECT * FROM USER;
    +----+-------+--------+
    | id | name  | extra  |
    +----+-------+--------+
    |  1 | user1 | user1  |
    |  8 | user2 | user8  |
    |  6 | user3 | user6  |
    |  4 | user4 | user4  |
    |  5 | user5 | user5  |
    |  7 | user6 | user7  |
    |  9 | USER2 | user9  |
    | 10 | USER6 | user10 |
    +----+-------+--------+
    

     上面是采用 REPLACE 的方式,可以看到,导入过程中删掉了两条数据,结果验证确实是 新的重复记录替换旧的记录,只保留最新的记录
     现在,来看看用 IGNORE 的方式:

    mysql> LOAD DATA INFILE '/tmp/user.txt' IGNORE INTO TABLE `user`;
    Query OK, 6 rows affected (0.01 sec)
    Records: 8  Deleted: 0  Skipped: 2  Warnings: 0
    
    mysql> SELECT * FROM USER;
    +----+-------+--------+
    | id | name  | extra  |
    +----+-------+--------+
    |  1 | user1 | user1  |
    |  2 | user2 | user2  |
    |  3 | user3 | user3  |
    |  4 | user4 | user4  |
    |  5 | user5 | user5  |
    |  7 | user6 | user7  |
    |  9 | USER2 | user9  |
    | 10 | USER6 | user10 |
    +----+-------+--------+
    

     看到了吧,确实是 新的记录略过,只保留最旧的记录

    作者:admini | 分类目录:数据库 | 标签:
  • MySQL 备份和恢复

    2011-11-30

    目前 MySQL 支持的免费备份工具有:mysqldump、mysqlhotcopy,还可以用 SQL 语法进行备份:BACKUP TABLE 或者 SELECT INTO OUTFILE,又或者备份二进制日志(binlog),还可以是直接拷贝数据文件和相关的配置文件。MyISAM 表是保存成文件的形式,因此相对比较容易备份,上面提到的几种方法都可以使用。Innodb 所有的表都保存在同一个数据文件 ibdata1 中(也可能是多个文件,或者是独立的表空间文件),相对来说比较不好备份,免费的方案可以是拷贝数据文件备份 binlog,或者用 mysqldump

    1、mysqldump

    1.1 备份

    mysqldump 是采用SQL级别的备份机制,它将数据表导成 SQL 脚本文件,在不同的 MySQL 版本之间升级时相对比较合适,这也是最常用的备份方法。
    现在来讲一下 mysqldump 的一些主要参数:

    • –compatible=name

      它告诉 mysqldump,导出的数据将和哪种数据库或哪个旧版本的 MySQL 服务器相兼容。值可以为 ansi、mysql323、mysql40、postgresql、oracle、mssql、db2、maxdb、no_key_options、no_tables_options、no_field_options 等,要使用几个值,用逗号将它们隔开。当然了,它并不保证能完全兼容,而是尽量兼容。

    • –complete-insert,-c

      导出的数据采用包含字段名的完整 INSERT 方式,也就是把所有的值都写在一行。这么做能提高插入效率,但是可能会受到 max_allowed_packet 参数的影响而导致插入失败。因此,需要谨慎使用该参数,至少我不推荐。

    • –default-character-set=charset

      指定导出数据时采用何种字符集,如果数据表不是采用默认的 latin1 字符集的话,那么导出时必须指定该选项,否则再次导入数据后将产生乱码问题。

    • –disable-keys

      告诉 mysqldumpINSERT 语句的开头和结尾增加 /*!40000 ALTER TABLE table DISABLE KEYS */;/*!40000 ALTER TABLE table ENABLE KEYS */; 语句,这能大大提高插入语句的速度,因为它是在插入完所有数据后才重建索引的。该选项只适合 MyISAM 表。

    • –extended-insert = true|false

      默认情况下,mysqldump 开启 --complete-insert 模式,因此不想用它的的话,就使用本选项,设定它的值为 false 即可。

    • –hex-blob

      使用十六进制格式导出二进制字符串字段。如果有二进制数据就必须使用本选项。影响到的字段类型有 BINARY、VARBINARY、BLOB

    • –lock-all-tables,-x

      在开始导出之前,提交请求锁定所有数据库中的所有表,以保证数据的一致性。这是一个全局读锁,并且自动关闭 --single-transaction--lock-tables 选项。

    • –lock-tables

      它和 --lock-all-tables 类似,不过是锁定当前导出的数据表,而不是一下子锁定全部库下的表。本选项只适用于 MyISAM 表,如果是 Innodb 表可以用 --single-transaction 选项。

    • –no-create-info,-t

      只导出数据,而不添加 CREATE TABLE 语句。

    • –no-data,-d

      不导出任何数据,只导出数据库表结构。

    • –opt

      这只是一个快捷选项,等同于同时添加 --add-drop-tables --add-locking --create-option --disable-keys --extended-insert --lock-tables --quick --set-charset 选项。本选项能让 mysqldump 很快的导出数据,并且导出的数据能很快导回。该选项默认开启,但可以用 --skip-opt 禁用。注意,如果运行 mysqldump 没有指定 --quick--opt 选项,则会将整个结果集放在内存中。如果导出大数据库的话可能会出现问题。

    • –quick,-q

      该选项在导出大表时很有用,它强制 mysqldump 从服务器查询取得记录直接输出而不是取得所有记录后将它们缓存到内存中。

    • –routines,-R

      导出存储过程以及自定义函数。

    • –single-transaction

      该选项在导出数据之前提交一个 BEGIN SQL语句,BEGIN 不会阻塞任何应用程序且能保证导出时数据库的一致性状态。它只适用于事务表,例如 InnoDBBDB
      本选项和 --lock-tables 选项是互斥的,因为 LOCK TABLES 会使任何挂起的事务隐含提交。
      要想导出大表的话,应结合使用 --quick 选项。

    • –triggers

      同时导出触发器。该选项默认启用,用 --skip-triggers 禁用它。

    其他参数详情请参考手册,我通常使用以下 SQL 来备份 MyISAM 表:

    /usr/local/mysql/bin/mysqldump -uyejr -pyejr \
    --default-character-set=utf8 --opt --extended-insert=false \
    --triggers -R --hex-blob -x db_name > db_name.sql
    

    使用以下 SQL 来备份 Innodb 表:

    /usr/local/mysql/bin/mysqldump -uyejr -pyejr \
    --default-character-set=utf8 --opt --extended-insert=false \
    --triggers -R --hex-blob --single-transaction db_name > db_name.sql
    

     

    1.2 还原

    mysqldump 备份出来的文件是一个可以直接倒入的 SQL 脚本,有两种方法可以将数据导入。

    • 直接用 mysql 客户端

      例如:

      /usr/local/mysql/bin/mysql -uyejr -pyejr db_name < db_name.sql
      

       

    • 用 SOURCE 语法

      其实这不是标准的 SQL 语法,而是 mysql 客户端提供的功能,例如:

      SOURCE /tmp/db_name.sql;
      

      这里需要指定文件的绝对路径,并且必须是 mysqld 运行用户(例如 nobody)有权限读取的文件。

    2、 mysqlhotcopy

    2.1 备份

    mysqlhotcopy 是一个 PERL 程序,最初由Tim Bunce编写。它使用 LOCK TABLES、FLUSH TABLEScpscp 来快速备份数据库。它是备份数据库或单个表的最快的途径,但它只能运行在数据库文件(包括数据表定义文件、数据文件、索引文件)所在的机器上。mysqlhotcopy 只能用于备份 MyISAM,并且只能运行在 类UnixNetWare 系统上。

    mysqlhotcopy 支持一次性拷贝多个数据库,同时还支持正则表达。以下是几个例子:

    root#/usr/local/mysql/bin/mysqlhotcopy -h=localhost -u=yejr -p=yejr \
    db_name /tmp (把数据库目录 db_name 拷贝到 /tmp 下)
    root#/usr/local/mysql/bin/mysqlhotcopy -h=localhost -u=yejr -p=yejr \
    db_name_1 ... db_name_n /tmp
    root#/usr/local/mysql/bin/mysqlhotcopy -h=localhost -u=yejr -p=yejr \
    db_name./regex/ /tmp
    

    更详细的使用方法请查看手册,或者调用下面的命令来查看 mysqlhotcopy 的帮助:

    perldoc /usr/local/mysql/bin/mysqlhotcopy
    

    注意,想要使用 mysqlhotcopy,必须要有 SELECT、RELOAD(要执行 FLUSH TABLES) 权限,并且还必须要能够有读取 datadir/db_name 目录的权限。

    2.2 还原

    mysqlhotcopy 备份出来的是整个数据库目录,使用时可以直接拷贝到 mysqld 指定的 datadir (在这里是 /usr/local/mysql/data/)目录下即可,同时要注意权限的问题,如下例:

    root#cp -rf db_name /usr/local/mysql/data/
    root#chown -R nobody:nobody /usr/local/mysql/data/ (将 db_name 目录的属主改成 mysqld 运行用户)
    

     

    3、 SQL 语法备份

    3.1 备份

    BACKUP TABLE 语法其实和 mysqlhotcopy 的工作原理差不多,都是锁表,然后拷贝数据文件。它能实现在线备份,但是效果不理想,因此不推荐使用。它只拷贝表结构文件和数据文件,不同时拷贝索引文件,因此恢复时比较慢。
    例子:

    BACK TABLE tbl_name TO '/tmp/db_name/';
    

    注意,必须要有 FILE 权限才能执行本SQL,并且目录 /tmp/db_name/ 必须能被 mysqld 用户可写,导出的文件不能覆盖已经存在的文件,以避免安全问题。

    SELECT INTO OUTFILE 则是把数据导出来成为普通的文本文件,可以自定义字段间隔的方式,方便处理这些数据。
    例子:

    SELECT * INTO OUTFILE '/tmp/db_name/tbl_name.txt' FROM tbl_name;
    

    注意,必须要有 FILE 权限才能执行本SQL,并且文件 /tmp/db_name/tbl_name.txt 必须能被 mysqld 用户可写,导出的文件不能覆盖已经存在的文件,以避免安全问题。

    3.2 恢复

    BACKUP TABLE 方法备份出来的文件,可以运行 RESTORE TABLE 语句来恢复数据表。
    例子:

    RESTORE TABLE FROM '/tmp/db_name/';
    

    权限要求类似上面所述。

    SELECT INTO OUTFILE 方法备份出来的文件,可以运行 LOAD DATA INFILE 语句来恢复数据表。
    例子:

    LOAD DATA INFILE '/tmp/db_name/tbl_name.txt' INTO TABLE tbl_name;
    

    权限要求类似上面所述。倒入数据之前,数据表要已经存在才行。如果担心数据会发生重复,可以增加 REPLACE 关键字来替换已有记录或者用 IGNORE 关键字来忽略他们。

    4、 启用二进制日志(binlog)

    采用 binlog 的方法相对来说更灵活,省心省力,而且还可以支持增量备份。

    启用 binlog 时必须要重启 mysqld。首先,关闭 mysqld,打开 my.cnf,加入以下几行:

    server-id	= 1
    log-bin		= binlog
    log-bin-index	= binlog.index
    

    然后启动 mysqld 就可以了。运行过程中会产生 binlog.000001 以及 binlog.index,前面的文件是 mysqld 记录所有对数据的更新操作,后面的文件则是所有 binlog 的索引,都不能轻易删除。关于 binlog 的信息请查看手册。

    需要备份时,可以先执行一下 SQL 语句,让 mysqld 终止对当前 binlog 的写入,就可以把文件直接备份,这样的话就能达到增量备份的目的了:

    FLUSH LOGS;

    如果是备份复制系统中的从服务器,还应该备份 master.inforelay-log.info 文件。

    备份出来的 binlog 文件可以用 MySQL 提供的工具 mysqlbinlog 来查看,如:

    /usr/local/mysql/bin/mysqlbinlog /tmp/binlog.000001
    

    该工具允许你显示指定的数据库下的所有 SQL 语句,并且还可以限定时间范围,相当的方便,详细的请查看手册。

    恢复时,可以采用类似以下语句来做到:

    /usr/local/mysql/bin/mysqlbinlog /tmp/binlog.000001 | mysql -uyejr -pyejr db_name
    

    mysqlbinlog 输出的 SQL 语句直接作为输入来执行它。

    如果你有空闲的机器,不妨采用这种方式来备份。由于作为 slave 的机器性能要求相对不是那么高,因此成本低,用低成本就能实现增量备份而且还能分担一部分数据查询压力,何乐而不为呢?

    5、 直接备份数据文件

    相较前几种方法,备份数据文件最为直接、快速、方便,缺点是基本上不能实现增量备份。为了保证数据的一致性,需要在靠背文件前,执行以下 SQL 语句:

    FLUSH TABLES WITH READ LOCK;

    也就是把内存中的数据都刷新到磁盘中,同时锁定数据表,以保证拷贝过程中不会有新的数据写入。这种方法备份出来的数据恢复也很简单,直接拷贝回原来的数据库目录下即可。

    注意,对于 Innodb 类型表来说,还需要备份其日志文件,即 ib_logfile* 文件。因为当 Innodb 表损坏时,就可以依靠这些日志文件来恢复。

    6、 备份策略

    对于中等级别业务量的系统来说,备份策略可以这么定:第一次全量备份,每天一次增量备份,每周再做一次全量备份,如此一直重复。而对于重要的且繁忙的系统来说,则可能需要每天一次全量备份,每小时一次增量备份,甚至更频繁。为了不影响线上业务,实现在线备份,并且能增量备份,最好的办法就是采用主从复制机制(replication),在 slave 机器上做备份。

    7、 数据维护和灾难恢复

    作为一名DBA(我目前还不是,呵呵),最重要的工作内容之一是保证数据表能安全、稳定、高速使用。因此,需要定期维护你的数据表。以下 SQL 语句就很有用:

    CHECK TABLE 或 REPAIR TABLE,检查或维护 MyISAM 表
    OPTIMIZE TABLE,优化 MyISAM 表
    ANALYZE TABLE,分析 MyISAM 表
    

    当然了,上面这些命令起始都可以通过工具 myisamchk 来完成,在这里不作详述。

    Innodb 表则可以通过执行以下语句来整理碎片,提高索引速度:

    ALTER TABLE tbl_name ENGINE = Innodb;
    

    这其实是一个 NULL 操作,表面上看什么也不做,实际上重新整理碎片了。

    通常使用的 MyISAM 表可以用上面提到的恢复方法来完成。如果是索引坏了,可以用 myisamchk 工具来重建索引。而对于 Innodb 表来说,就没这么直接了,因为它把所有的表都保存在一个表空间了。不过 Innodb 有一个检查机制叫 模糊检查点,只要保存了日志文件,就能根据日志文件来修复错误。可以在 my.cnf 文件中,增加以下参数,让 mysqld 在启动时自动检查日志文件:

    innodb_force_recovery	= 4
    

    关于该参数的信息请查看手册。

    8、 总结

    做好数据备份,定只好合适的备份策略,这是一个DBA所做事情的一小部分,万事开头难,就从现在开始吧!

    作者:admini | 分类目录:数据库 | 标签:
  • MySQL优化

    2011-11-30

    缓存优化
    在 my.cnf 中添加/修改以下选项:

     #取消文件系统的外部锁
     skip-locking
    
     #不进行域名反解析,注意由此带来的权限/授权问题
     skip-name-resolve
    
     #索引缓存,根据内存大小而定,如果是独立的db服务器,可以设置高达80%的内存总量
     key_buffer = 512M
    
     #连接排队列表总数
     back_log = 200
     max_allowed_packet = 2M
    
     #打开表缓存总数,可以避免频繁的打开数据表产生的开销
     table_cache = 512
    
     #每个线程排序所需的缓冲
     sort_buffer_size = 4M
    
     #每个线程读取索引所需的缓冲
     read_buffer_size = 4M
    
     #MyISAM表发生变化时重新排序所需的缓冲
     myisam_sort_buffer_size = 64M
    
     #缓存可重用的线程数
     thread_cache = 128
    
     #查询结果缓存
     query_cache_size = 128M
    
     #设置超时时间,能避免长连接
     set-variable = wait_timeout=60
    
     #最大并发线程数,cpu数量*2
     thread_concurrency = 4
    
     #记录慢查询,然后对慢查询一一优化
     log-slow-queries = slow.log
     long_query_time = 1
    
     #关闭不需要的表类型,如果你需要,就不要加上这个
     skip-innodb
     skip-bdb
     

    以上参数根据各自服务器的配置差异进行调整,仅作为参考.

    作者:admini | 分类目录:数据库 | 标签:
  • Service Unavailable解决

    2011-11-30

    解决w2003 服务器虚拟主机上数据库型站点访问时出现“Service Unavailable”的提示

     解决windows server 2003 服务器虚拟主机上数据库型站点访问时出现“Service Unavailable”的提示:
     1、IIS应用程序池–属性–回收工作进程为设置15分钟-60分钟;
     2、内存回收下面的两个选项前全部打勾;
     3、运行状况–启用快速失败保护的选项将勾去掉!

    解决windows server 2003 服务器虚拟主机上数据库型站点用户登陆后几分钟内自动退出,需要重登陆的问题:
    IIS应用程序池–属性–回收工作进程为设置15分钟-60分钟.

    作者:admini | 分类目录:服务器 | 标签:
  • 三种禁用FileSystemObject组件的方法

    2011-11-30

    众所周知,FileSystemObject组件的强大功能及破坏性是它屡屡被免费主页
    提供商(那些支持ASP)的禁用的原因,我整理了一下,本来只找到两种方法,后来
    被某人一刺激,硬是想到第三种不为人所知的方法,呵呵,也不知道是不是这样的。

    第一种:用RegSrv32 /u C:\WINDOWS\SYSTEM\scrrun.dll(win98路径)来注销该组
    件。此方法过于狠毒,属于同归于尽的方法,大家都没得用,是下招

    第二种:修改Progid的值,在ASP里调用组件的方式通常是 Set 对象名=Server.
    CreateObject("Progid"),这时候我们就可以通过修改注册表中的Progid值从达
    到禁用该组件的方法。在 开始-运行中敲入regedit,然后找到HKEY_CLASSES_ROO
    T\Scripting.FileSystemObject,这时候我们就可以更改该Progid的值了,如改
    成Scripting.FileSystemObject8。这样在ASP页里就这样调用了:
    <%@ Language=Vbscript%>
    <%
    Set Fs=Server.CreateObject("Scripting.FileSystemObject8")
    %>
    (如果你前面没有调用过该组件的话,则无须重启,就可以看到效果了,否则请重
    启后看效果。)
    这时候我们看看还是用原来的调用方法的结果:
    <%@ Language=Vbscript%>
    <%
    Set Fs=Server.CreateObject("Scripting.FileSystemObject")
    %>
    这时候的运行结果为:
    服务器对象 错误 ‘ASP 0177 : 800401f3′

    Server.CreateObject 失败

    /aspimage/testfile2.asp, 行3

    800401f3
    (OK,达到我们的要求)
    该方法由于本人迟了两步,结果就让别人抢着回答了,这样极大的刺激了我,结
    果就产生了第三种方法。

    第三种:细心的高手们会想,既然能通过修改Progid值来禁用该组件,那Clsid是
    否也可以来修改呢?(OK,你想得和我一样)我们知道,除了CreateObject方法以
    外,也可以使用一般的<object>标注建立一个组件,我们可以在ASP里面使用HTM
    L的<object>标注,以便在网页中加入一个组件。方法是:
    <object runat=server id=fs1 scope=page progid="Scripting.FileSystemObj
    ect"></object>
    Runat表示是在服务端执行,Scope表示组件的生命周期,可以选用Session,Appl
    ication或page(表示当前页面,也可缺省)
    这种写法对我们没用,还有一种写法是:
    <object runat=server id=fs1 scope=page classid="clsid:clsid的值"></obj
    ect>
    我们也可以通过修改该Clsid的值而禁用该组件,如将注册表中HKEY_CLASSES_RO
    OT\Scripting.FileSystemObject\CLSID的值0D43FE01-F093-11CF-8940-00A0C90
    54228改成0D43FE01-F093-11CF-8940-00A0C9054229(改了最后面一位),这时候的
    写法为:
    <object runat=server id=fs1 scope=page classid="clsid:0D43FE01-F093-11
    CF-8940-00A0C9054229"></object>
    看运行结果,没问题,OK。这时候我们再用
    <object runat=server id=fs1 scope=page classid="clsid:0D43FE01-F093-11
    CF-8940-00A0C9054228"></object>
    这时候就出错了。

    新建一用户:iusr_domain
    IIS里设置对应站点的匿名用户IUSR_DOMAIN
    CACLS: 设置目录权限

    这样FSO可用,但不会影响别人

    作者:admini | 分类目录:服务器 | 标签:
  • 安全配置NT/2000 SERVER(IIS)

    2011-11-30

    1.端口:
    端口是计算机和外部网络相连的逻辑接口,也是计算机的第一道屏障,端口配置正确与否直接影响到主机的安全,一般来说,仅打开你需要使用的端口会比较安全,配置的方法是在网卡属性-TCP/IP-高级-选项-TCP/IP筛选中启用TCP/IP筛选,不过对于win2000的端口过滤来说,有一个不好的特性:只能规定开哪些端口,不能规定关闭哪些端口,这样对于需要开大量端口的用户就比较痛苦。

    2.IIS:
    IIS是微软的组件中漏洞最多的一个,平均两三个月就要出一个漏洞,而微软的IIS默认安装又实在不敢恭维,所以IIS的配置是我们的重点,现在大家跟着我一起来:

    首先,把C盘那个什么Inetpub目录彻底删掉,在D盘建一个Inetpub(要是你不放心用默认目录名也可以改一个名字,但是自己要记得)在IIS管理器中将主目录指向D:\Inetpub;

    其次,那个IIS安装时默认的什么scripts等虚拟目录一概删除,如果你需要什么权限的目录可以自己慢慢建,需要什么权限开什么。(特别注意写权限和执行程序的权限,没有绝对的必要千万不要给)

    第三,应用程序配置:在IIS管理器中删除必须之外的任何无用映射,必须指的是ASP,ASA和其他你确实需要用到的文件类型,例如你用到stml等(使用server side include),实际上90%的主机有了上面两个映射就够了,其余的映射几乎每个都有一个凄惨的故事:htw, htr, idq,ida……想知道这些故事?去查以前的漏洞列表吧。在IIS管理器中右击主机->属性->WWW服务 编辑->主目录配置->应用程序映射,然后就开始一个个删吧(里面没有全选的,嘿嘿)。接着在刚刚那个窗口的应用程序调试书签内将脚本错误消息改为发送文本(除非你想ASP出错的时候用户知道你的程序/网络/数据库结构)错误文本写什么?随便你喜欢,自己看着办。点击确定退出时别忘了让虚拟站点继承你设定的属性。安装新的Service Pack后,IIS的应用程序映射应重新设置。(说明:安装新的Service Pack后,某些应用程序映射又会出现,导致出现安全漏洞。这是管理员较易忽视的一点。)

    IIS安全配置精华
      1.如何让asp脚本以system权限运行?

      修改你asp脚本所对应的虚拟目录,把"应用程序保护"修改为"低"….

      2.如何防止asp木马?

      基于FileSystemObject组件的asp木马

      cacls %systemroot%\system32\scrrun.dll /e /d guests //禁止guests使用

      regsvr32 scrrun.dll /u /s //删除

      基于shell.application组件的asp木马

      cacls %systemroot%\system32\shell32.dll /e /d guests //禁止guests使用

      regsvr32 shell32.dll /u /s //删除

      3.如何加密asp文件?

      从微软免费下载到sce10chs.exe 直接运行即可完成安装过程。

      安装完毕后,将生成screnc.exe文件,这是一个运行在DOS PROMAPT的命令工具。

      运行screnc – l vbscript source.asp destination.asp

      生成包含密文ASP脚本的新文件destination.asp

      用记事本打开看凡是""之内的,不管是否注解,都变成不可阅读的密文了

      但无法加密中文。

      4.如何从IISLockdown中提取urlscan?

      iislockd.exe /q /c /t:c:\urlscan

      5.如何防止Content-Location标头暴露了web服务器的内部IP地址?

      执行

      cscript c:\inetpub\adminscripts\adsutil.vbs set w3svc/UseHostName True

      最后需要重新启动iis

      6.如何解决HTTP500内部错误?

      iis http500内部错误大部分原因

      主要是由于iwam账号的密码不同步造成的。

      我们只要同步iwam_myserver账号在com+应用程序中的密码即可解决问题。

      执行

      cscript c:\inetpub\adminscripts\synciwam.vbs -v
      7.如何增强iis防御SYN Flood的能力?

      Windows Registry Editor Version 5.00

      [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]
    ‘启动syn攻击保护。缺省项值为0,表示不开启攻击保护,项值为1和2表示启动syn攻击保护,设成2之后

      ’安全级别更高,对何种状况下认为是攻击,则需要根据下面的TcpMaxHalfOpen和TcpMaxHalfOpenRetried值

      ’设定的条件来触发启动了。这里需要注意的是,NT4.0必须设为1,设为2后在某种特殊数据包下会导致系统重启。

      "SynAttackProtect"=dword:00000002

      ’同时允许打开的半连接数量。所谓半连接,表示未完整建立的TCP会话,用netstat命令可以看到呈SYN_RCVD状态

      ’的就是。这里使用微软建议值,服务器设为100,高级服务器设为500。建议可以设稍微小一点。

      "TcpMaxHalfOpen"=dword:00000064

      ’判断是否存在攻击的触发点。这里使用微软建议值,服务器为80,高级服务器为400。

      "TcpMaxHalfOpenRetried"=dword:00000050

      ’设置等待SYN-ACK时间。缺省项值为3,缺省这一过程消耗时间45秒。项值为2,消耗时间为21秒。

      ’项值为1,消耗时间为9秒。最低可以设为0,表示不等待,消耗时间为3秒。这个值可以根据遭受攻击规模修改。

      ’微软站点安全推荐为2。

      "TcpMaxConnectResponseRetransmissions"=dword:00000001

      ’设置TCP重传单个数据段的次数。缺省项值为5,缺省这一过程消耗时间240秒。微软站点安全推荐为3。

      "TcpMaxDataRetransmissions"=dword:00000003

      ’设置syn攻击保护的临界点。当可用的backlog变为0时,此参数用于控制syn攻击保护的开启,微软站点安全推荐为5。

      "TCPMaxPortsExhausted"=dword:00000005

      ’禁止IP源路由。缺省项值为1,表示不转发源路由包,项值设为0,表示全部转发,设置为2,表示丢弃所有接受的

      ’源路由包,微软站点安全推荐为2。

      "DisableIPSourceRouting"=dword:0000002

      ’限制处于TIME_WAIT状态的最长时间。缺省为240秒,最低为30秒,最高为300秒。建议设为30秒。

      "TcpTimedWaitDelay"=dword:0000001e
      8.如何避免*mdb文件被下载?

      安装ms发布的urlscan工具,可以从根本上解决这个问题。

      同时它也是一个强大的安全工具,你可以从ms的网站上获取更为详细的信息。

      9.如何让iis的最小ntfs权限运行?

      依次做下面的工作:

      a.选取整个硬盘:

      system:完全控制

      administrator:完全控制

      (允许将来自父系的可继承性权限传播给对象)

      b.\program files\common files:

      everyone:读取及运行

      列出文件目录

      读取

      (允许将来自父系的可继承性权限传播给对象)

      c.\inetpub\wwwroot:

      iusr_machine:读取及运行

      列出文件目录

      读取

      (允许将来自父系的可继承性权限传播给对象)

      e.\winnt\system32:

      选择除inetsrv和centsrv以外的所有目录,

      去除“允许将来自父系的可继承性权限传播给对象”选框,复制。

      f.\winnt:

      选择除了downloaded program files、help、iis temporary compressed files、

      offline web pages、system32、tasks、temp、web以外的所有目录

      去除“允许将来自父系的可继承性权限传播给对象”选框,复制。

      g.\winnt:

      everyone:读取及运行

      列出文件目录

      读取

      (允许将来自父系的可继承性权限传播给对象)

      h.\winnt\temp:(允许访问数据库并显示在asp页面上)

      everyone:修改

      (允许将来自父系的可继承性权限传播给对象)

      10.如何隐藏iis版本?

      一个黑客可以可以轻易的telnet到你的web端口,发送get命令来获取很多信息

      iis存放IIS BANNER的所对应的dll文件如下:

      WEB:C:\WINNT\SYSTEM32\INETSRV\W3SVC.DLL

      FTP:C:\WINNT\SYSTEM32\INETSRV\FTPSVC2.DLL

      SMTP:C:\WINNT\SYSTEM32\INETSRV\SMTPSVC.DLL
    你可以用16进制编辑器去修改那些dll文件的关键字,比如iis的Microsoft-IIS/5.0

      具体过程如下:

      1.停掉iis iisreset /stop

      2.删除%SYSTEMROOT%\system32\dllcache目录下的同名文件

      3.修改

    为了对付日益增多的cgi漏洞扫描器,还有一个小技巧可以参考,在IIS中将HTTP404 Object Not Found出错页面通过URL重定向到一个定制HTM文件,可以让目前绝大多数CGI漏洞扫描器失灵。其实原因很简单,大多数CGI扫描器在编写时为了方便,都是通过查看返回页面的HTTP代码来判断漏洞是否存在的,例如,著名的IDQ漏洞一般都是通过取1.idq来检验,如果返回HTTP200,就认为是有这个漏洞,反之如果返回HTTP404就认为没有,如果你通过URL将HTTP404出错信息重定向到HTTP404.htm文件,那么所有的扫描无论存不存在漏洞都会返回HTTP200,90%的CGI扫描器会认为你什么漏洞都有,结果反而掩盖了你真正的漏洞,让入侵者茫然无处下手,不过从个人角度来说,我还是认为扎扎实实做好安全设置比这样的小技巧重要的多。

    最后,为了保险起见,你可以使用IIS的备份功能,将刚刚的设定全部备份下来,这样就可以随时恢复IIS的安全配置。还有,如果你怕IIS负荷过高导致服务器满负荷死机,也可以在性能中打开CPU限制,例如将IIS的最大CPU使用率限制在70%。
    3.帐号策略:
    ?牐牐?1)帐号尽可能少,且尽可能少用来登录;
    ?牐犓得鳎和?站帐号一般只用来做系统维护,多余的帐号一个也不要,因为多一个帐号就会多一份被攻破的危险。
    ?牐牐?2)除过Administrator外,有必要再增加一个属于管理员组的帐号
    ?牐犓得鳎毫礁龉芾碓弊榈?帐号,一方面防止管理员一旦忘记一个帐号的口令还
    ?牐犛幸桓霰赣?帐号;另方面,一旦黑客攻破一个帐号并更改口令,我们还有
    ?牐犛谢?会重新在短期内取得控制权。
    ?牐牐?3)所有帐号权限需严格控制,轻易不要给帐号以特殊权限;
    ?牐牐?4)将Administrator重命名,改为一个不易猜的名字。其他一般帐号也应尊循这一原则。
    ?牐犓得鳎赫庋?可以为黑客攻击增加一层障碍。
    ?牐牐?5)将Guest帐号禁用,同时重命名为一个复杂的名字,增加口令,并将它从
    ?牐燝uest组删掉;
    ?牐犓得鳎河械?黑客工具正是利用了guest 的弱点,可以将帐号从一般用户提
    ?牐犐?到管理员组。
    ?牐牐?6)给所有用户帐号一个复杂的口令(系统帐号出外),长度最好在12位以上(我朋友的是16位)且必须同时包含字母、数字、特殊字符。同时不要使用大家熟悉的单词(如microsoft)、熟悉的键盘顺序(如qwert)、熟悉的数字(如2000)等。
    ?牐犓得鳎嚎诹钍?黑客攻击的重点,口令一旦被突破也就无任何系统安全可言了,而这往往是不少网管所忽视的地方,据我们的测试,仅字母加数字的5位口令在几分钟内就会被攻破,而所推荐的方案则要安全的多。
    ?牐牐?7)口令必须定期更改(建议至少两周该一次),且最好记在心里,除此以外不要在任何地方做记录;另外,如果在日志审核中发现某个帐号被连续尝试,则必须立刻更改此帐号(包括用户名和口令);
    ?牐牐?8)在帐号属性中设立锁定次数,比如改帐号失败登录次数超过5次即锁定改帐号。这样可以防止某些大规模的登录尝试,同时也使管理员对该帐号提高警惕。
       (9)不让系统显示上次登陆的用户名
      默认情况下,终端服务接入服务器时,登陆对话框中会显示上次登陆的帐户明,本地的登陆

    对话框也是一样。这使得别人可以很容易的得到系统的一些用户名,进而作密码猜测。修改注册表可以不让对话框里显
    示上次登陆的用户名,具体是:
    Local_Machine\Software\Microsoft\WindowsNT\CurrentVersion\Winlogon\DontDisplayLastUserName把 REG_SZ 的键值改成 1
       (10)禁止建立空连接
      默认情况下,任何用户通过通过空连接连上服务器,进而枚举出帐号,猜测密码。我们可以通过修改注册表来禁止建立空连接:
    Local_Machine\System\CurrentControlSet\Control\Lsa\restrictanonymous 的值改成"1"即可。

     

    4.安全日志:

    Win2000的默认安装是不开任何安全审核的!
    那么请你到本地安全策略->审核策略中打开相应的审核,推荐的审核是:
    账户管理 成功 失败
    登录事件 成功 失败
    对象访问 失败
    策略更改 成功 失败
    特权使用 失败
    系统事件 成功 失败
    目录服务访问 失败
    账户登录事件 成功 失败
    审核项目少的缺点是万一你想看发现没有记录那就一点都没辙;审核项目太多不仅会占用系统资源而且会导致你根本没空去看,这样就失去了审核的意义。 与之相关的是:
    在账户策略->密码策略中设定:
    密码复杂性要求 启用
    密码长度最小值 6位
    强制密码历史 5次
    最长存留期 30天
    在账户策略->账户锁定策略中设定:
    账户锁定 3次错误登录
    锁定时间 30分钟
    复位锁定计数 30分钟
    同样,Terminal Service的安全日志默认也是不开的,我们可以在Terminal Service Configration(远程服务配置)-权限-高级中配置安全审核,一般来说只要记录登录、注销事件就可以了。 
    5.目录和文件权限:

    为了控制好服务器上用户的权限,同时也为了预防以后可能的入侵和溢出,我们还必须非常小心地设置目录和文件的访问权限,NT的访问权限分为:读取、写入、读取及执行、修改、列目录、完全控制。在默认的情况下,大多数的文件夹对所有用户(Everyone这个组)是完全敞开的(Full Control),你需要根据应用的需要进行权限重设。
    在进行权限控制时,请记住以下几个原则:
    1>权限是累计的:如果一个用户同时属于两个组,那么他就有了这两个组所允许的所有权限;
    2>拒绝的权限要比允许的权限高(拒绝策略会先执行)如果一个用户属于一个被拒绝访问某个资源的组,那么不管其他的权限设置给他开放了多少权限,他也一定不能访问这个资源。所以请非常小心地使用拒绝,任何一个不当的拒绝都有可能造成系统无法正常运行;
    3>文件权限比文件夹权限高
    4>利用用户组来进行权限控制是一个成熟的系统管理员必须具有的优良习惯之一;
    5>仅给用户真正需要的权限,权限的最小化原则是安全的重要保障;

    6.关于补丁:在NT下,如果安装了补丁程序,以后如果要从NT光盘上安装新的Windows程序,都要重新安装一次补丁程序, 2000下不需要这样做。
    ?牐犓得鳎?
    ?牐?
    ?牐牐?1) 最新的补丁程序,表示系统以前有重大漏洞,非补不可了,对于局域网内服务器可以不是最新的,但站点必须安装最新补丁,否则黑客可能会利用低版本补丁的漏洞对系统造成威胁。这是一部分管理员较易忽视的一点;
    ?牐牐?2) 安装NT的SP5、SP6有一个潜在威胁,就是一旦系统崩溃重装NT时,系统将不会认NTFS分区,原因是微软在这两个补丁中对NTFS做了改进。只能通过Windows 2000安装过程中认NTFS,这样会造成很多麻烦,建议同时做好数据备份工作。
    ?牐牐?3) 安装Service Pack前应先在测试机器上安装一次,以防因为例外原因导致机器死机,同时做好数据备份。
    ?牐?
    ?牐牼×坎话沧坝隬EB站点服务无关的软件;
    ?牐犓得鳎浩渌?应用软件有可能存在黑客熟知的安全漏洞

    ?牐?
    ?牐?
    7.解除NetBios与TCP/IP协议的绑定

    ?牐犓得鳎篘etBois在局域网内是不可缺少的功能,在网站服务器上却成了黑客扫描工具的首选目标。方法:NT:控制面版——网络——绑定——NetBios接口——禁用 2000:控制面版——网络和拨号连接——本地网络——属性——TCP/IP——属性——高级——WINS——禁用TCP/IP上的NETBIOS
    ?牐?
    10.删除所有的网络共享资源,在网络连接的设置中删除文件和打印共享,只留下TCP/IP协议

    ?牐犓得鳎篘T与2000在默认情况下有不少网络共享资源,在局域网内对网络管理和网络通讯有用,在网站服务器上同样是一个特大的安全隐患。(卸载"Microsoft 网络的文件和打印机共享"。当查看"网络和拨号连接"中的任何连接属性时,将显示该选项。单击"卸载"按钮删除该组件;清除"Microsoft 网络的文件和打印机共享"复选框将不起作用。)
    方法:
    ?牐?(1)NT:管理工具——服务器管理器——共享目录——停止共享;
    ?牐?2000:控制面版——管理工具——计算及管理——共享文件夹———停止共享
    ?牐牭?上述两种方法太麻烦,服务器每重启一次,管理员就必须停止一次
    ?牐牐?2)修改注册表:
    ?牐犜诵蠷egedit,然后修改注册表在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters下增加一个键
    ?牐燦ame: AutoShareServer
    ?牐燭ype: REG_DWORD
    ?牐爒alue: 0
    ?牐犎缓笾匦缕舳?您的服务器,磁盘分区共享去掉,但IPC共享仍存在,需每次重启后手工删除或者做一个批处理。
    ?牐?
    11.改NTFS的安全权限;
    ?牐犓得鳎篘TFS下所有文件默认情况下对所有人(EveryOne)为完全控制权限,这使黑客有可能使用一般用户身份对文件做增加、删除、执行等操作,建议对一般用户只给予读取权限,而只给管理员和System以完全控制权限,但这样做有可能使某些正常的脚本程序不能执行,或者某些需要写的操作不能完成,这时需要对这些文件所在的文件夹权限进行更改,建议在做更改前先在测试机器上作测试,然后慎重更改。
    ?牐?
    12.加强数据备份;
    ?牐犓得鳎赫庖坏惴浅V匾?,站点的核心是数据数据一旦遭到破坏后果不堪设想,而这往往是黑客们真正关心的东西;遗憾的是,不少网管在这一点上作的并不好,不是备份不完全,就是备份不及时。数据备份需要仔细计划,制定出一个策略并作了测试以后才实施,而且随着网站的更新,备份计划也需要不断地调整。
    ?牐?
    ?牐?
    13.只保留TCP/IP协议,删除NETBEUI、IPX/SPX协议;
    ?牐犓得鳎和?站需要的通讯协议只有TCP/IP,而NETBEUI是一个只能用于局域网的协议,IPX/SPX是面临淘汰的协议,放在网站上没有任何用处,反而会被某些黑客工具利用。?牐?
    ?牐?
    14.不要起用IP转发功能,控制面板->网络->协议->TCP/IP协议->属性,使这个选框为空。(NT)
    ?牐犓得鳎喝笔∏榭鱿拢琋T的IP转发功能是禁止的,但注意不要启用,否则它会具有路由作用,被黑客利用来对其他服务器进行攻击。
    ?牐?
    15.安装最新的MDAC(http://www.microsoft.com/data/download.htm
    ?牐犓得鳎篗DAC为数据访问部件,通常程序对数据库的访问都通过它,但它也是黑客攻击的目标,为防止以前版本的漏洞可能会被带入升级后的版本,建议卸载后安装最新的版本。注意:在安装最新版本前最好先做一下测试,因为有的数据访问方式或许在新版本中不再被支持,这种情况下可以通过修改注册表来档漏洞,祥见漏洞测试文档。
    ?牐?
    16.设置IP拒绝访问列表
    ?牐犓得鳎憾杂赪WW服务,可以拒绝一些对站点有攻击嫌疑的地址;尤其对于FTP服务,如果只是自己公司上传文件,就可以只允许本公司的IP访问改FTP服务,这样,安全性大为提高。
    ?牐?
    17.禁止对FTP服务的匿名访问
    ?牐犓得鳎喝绻?允许对FTP服务做匿名访问,该匿名帐户就有可能被利用来获取更多的信息,以致对系统造成危害。
    ?牐?
    18.建议使用W3C扩充日志文件格式,每天记录客户IP地址,用户名,服务器端口,方法,URI字根,HTTP状态,用户代理,而且每天均要审查日志。(最好不要使用缺省的目录,建议更换一个记日志的路径,同时设置日志的访问权限,只允许管理员和system为Full Control)
    ?牐犓得鳎鹤魑?一个重要措施,既可以发现攻击的迹象,采取预防措施,也可以作为受攻击的一个证据

    19.ASP编程安全:
    ?牐?
    ?牐牥踩?不仅是网管的事,编程人员也必须在某些安全细节上注意,养成良好的安全习惯,否则,会给黑客造成可乘之机。目前,大多数网站上的ASP程序有这样那样的安全漏洞,但如果写程序的时候注意的话,还是可以避免的。
    ?牐?
    ?牐犐婕坝没?名与口令的程序最好封装在服务器端,尽量少的在ASP文件里出现,涉及到与数据库连接地用户名与口令应给予最小的权限。
    说明:用户名与口令,往往是黑客们最感兴趣的东西,如果被通过某种方式看到源代码,后果是严重的。因此要尽量减少它们在ASP文件中的出现次数。出现次数多得用户名与口令可以写在一个位置比较隐蔽的包含文件中。如果涉及到与数据库连接,理想状态下只给它以执行存储过程的权限,千万不要直接给予该用户以修改、插入、删除记录的权限。
    ?牐?
    ?牐犘枰?经过验证的ASP页面,可跟踪上一个页面的文件名,只有从上一页面转进来的会话才能读取这个页面。
    ?牐犓得鳎合衷诘男枰?经过验证的ASP程序多是在页面头部加一个判断语句,但这还不够,有可能被黑客绕过验证直接进入,因此有必要跟踪上一个页面。具体漏洞见所附漏洞文档。
    ?牐?
    ?牐牱乐笰SP主页.inc文件泄露问题
    ?牐牭贝嬖赼sp 的主页正在制作并没有进行最后调试完成以前,可以被某些搜索引擎机动追加为搜索对象,如果这时候有人利用搜索引擎对这些网页进行查找,会得到有关文件的定位,并能在浏览器中察看到数据库地点和结构的细节揭示完整的源代码。
    ?牐牻饩龇桨福撼绦蛟庇Ω迷谕?页发布前对其进行彻底的调试;安全专家需要固定asp 包含文件以便外部的用户不能看他们。 首先对 .inc 文件内容进行加密,其次也可以使用 .asp 文件代替 .inc 文件使用户无法从浏览器直接观看文件的源代码。.inc 文件的文件名不用使用系统默认的或者有特殊含义容易被用户猜测到的,尽量使用无规则的英文字母。
    ?牐?
    ?牐?
    ?牐犠⒁饽承〢SP编辑器会自动备份asp文件,会被下载的漏洞
    ?牐犜谟行┍嗉璦sp程序的工具,当创建或者修改一个asp文件时,编辑器自动创建一个备份文件,比如:UltraEdit就会备份一个..bak文件,如你创建或者修改了some.asp,编辑器自动生成一个叫some.asp.bak文件,如果你没有删除这个 bak文件,攻击有可以直接下载some.asp.bak文件,这样some.asp的源程序就会给下载。
    ?牐?
    ?牐犜诖?理类似留言板、BBS等输入框的ASP程序中,最好屏蔽掉HTML、javascript、VBScript语句,如无特殊要求,可以限定只允许输入字母与数字,屏蔽掉特殊字符。同时对输入字符的长度进行限制。而且不但在客户端进行输入合法性检查,同时要在服务器端程序中进行类似检查。
    ?牐犓得鳎菏淙肟蚴?黑客利用的一个目标,他们可以通过输入脚本语言等对用户客户端造成损坏; 如果该输入框涉及到数据查询,他们会利用特殊查询输入得到更多的数据数据,甚至是表的全部。因此必须对输入框进行过滤。但如果为了提高效率仅在客户端进行输入合法性检查,仍有可能被绕过,因此必须在服务器端再做一次检查。
    20.防止ACCESS mdb 数据库有可能被下载的漏洞
    ?牐犜谟肁CCESS做后台数据库时,如果有人通过各种方法知道或者猜到了服务器的ACCESS数据库的路径和数据库名称,那么他能够下载这个ACCESS数据库文件,这是非常危险的。
    ?牐牻饩龇椒ǎ?
    ?牐?(1) 为你的数据库文件名称起个复杂的非常规的名字,并把他放在几目录下。所谓 "非常规",打个比方:比如有个数据库要保存的是有关书籍的信息,可不要把他起个"book.mdb"的名字,起个怪怪的名称,比如d34ksfslf.mdb, 再把他放在如./kdslf/i44/studi/ 的几层目录下,这样黑客要想通过猜的方式得到你的ACCESS数据库文件就难上加难了。
    ?牐?(2)不要把数据库名写在程序中。有些人喜欢把DSN写在程序中,比如:
    ?牐燚BPath = Server.MapPath("cmddb.mdb")
    ?牐燾onn.Open "driver={Microsoft Access Driver (*.mdb)};dbq=" & DBPath
    ?牐牸偃缤蛞桓?人拿到了源程序,你的ACCESS数据库的名字就一览无余。因此建议你在ODBC里设置数据源,再在程序中这样写:
    ?牐燾onn.open "shujiyuan"
    ?牐?(3)使用ACCESS来为数据库文件编码及加密。首先在选取 "工具->安全->加密/解密数据库,选取数据库(如:employer.mdb),然后接确定,接着会出现 "数据库加密后另存为"的窗口,存为:employer1.mdb。 接着employer.mdb就会被编码,然后存为employer1.mdb..
    要注意的是,以上的动作并不是对数据库设置密码,而只是对数据库文件加以编码,目的是为了防止他人使用别的工具来查看数据库文件的内容。
    ?牐牻酉吕次颐俏?数据库加密,首先以打开经过编码了的 employer1.mdb, 在打开时,选择"独占"方式。然后选取功能表的"工具->安全->设置数据库密码", 接着 输入密码即可。这样即使他人得到了employer1.mdb文件,没有密码他是无法看到 employer1.mdb的。

     

    21.SQL SERVER的安全
    ?牐?
    ?牐燬QL SERVER是NT平台上用的最多的数据库系统,但是它的安全问题也必须引起重视。数据库中往往存在着最有价值的信息,一旦数据被窃后果不堪设想。
    ?牐?
    ?牐牸笆备?新补丁程序。
    ?牐犓得鳎河隢T一样,SQL SERVER的许多漏洞会由补丁程序来弥补。建议在安装补丁程序之前先在测试机器上做测试,同时提前做好目标服务器的数据备份。
    ?牐?
    ?牐牳鳶A一个复杂的口令。
    ?牐犓得鳎篠A具有对SQL SERVER数据库操作的全部权限。遗憾的是,一部分网管对数据库并不熟悉,建立数据库的工作由编程人员完成,而这部分人员往往只注重编写SQL 语句本身,对SQL SERVER数据库的管理不熟悉,这样很有可能造成SA口令为空。这对数据库安全是一个严重威胁。目前具有这种隐患的站点不在少数。
    ?牐?
    ?牐犙细窨刂?数据库用户的权限,轻易不要给让用户对表有直接的查询、更改、插入、删除权限,可以通过给用户以访问视图的权限,以及只具有执行存储过程的权限。
    ?牐犓得鳎河没?如果对表有直接的操作权限,就会存在数据被破坏的危险。
    ?牐?
    ?牐犞贫┩暾?的数据库备份与恢复策略。

    22. PCANYWHERE的安全:
    ?牐?
    ?牐犇壳埃琍CANYWHERE是最流行的基于NT与2000的远程控制工具,同样也需要注意安全问题。建议采用单独的用户名与口令,最好采用加密手段。千万不要采用与NT管理员一样的用户名与口令,也不要使用与NT集成的口令。同时在服务器端的设置时务必采用security options中的强加密方式,拒绝低加密水平的连接,同时采用口令加密与传输过程中的用户名与口令加密,以防止被嗅探到,还要限制连接次数,另外很重要的一点就是一定在protect item中设置高强度的口令,同时一定限制不能够让别人看到你的host端的任何设置,即便是要察看主机端的相关设置也必须要输入口令!
    ?牐犓得鳎篜CANYWHERE 口令是远程控制的第一个关口,如果与NT的一样, 就失去了安全屏障。被攻破后就毫无安全可言。而如果采用单独的口令,即使攻破了PCANYWHERE,NT还有一个口令屏障。
    ?牐牸笆卑沧敖闲碌陌姹尽?

    作者:admini | 分类目录:服务器 | 标签:
  • C/C++头文件一览

    2011-11-30

    C、传统 C++

    #include <assert.h>    //设定插入点
    #include <ctype.h>     //字符处理
    #include <errno.h>     //定义错误码
    #include <float.h>     //浮点数处理
    #include <fstream.h>    //文件输入/输出
    #include <iomanip.h>    //参数化输入/输出
    #include <iostream.h>   //数据流输入/输出
    #include <limits.h>    //定义各种数据类型最值常量
    #include <locale.h>    //定义本地化函数
    #include <math.h>     //定义数学函数
    #include <stdio.h>     //定义输入/输出函数
    #include <stdlib.h>    //定义杂项函数及内存分配函数
    #include <string.h>    //字符串处理
    #include <strstrea.h>   //基于数组的输入/输出
    #include <time.h>     //定义关于时间的函数
    #include <wchar.h>     //宽字符处理及输入/输出
    #include <wctype.h>    //宽字符分类

    //////////////////////////////////////////////////////////////////////////

    标准 C++ (同上的不再注释)

    #include <algorithm>    //STL 通用算法
    #include <bitset>     //STL 位集容器
    #include <cctype>
    #include <cerrno>
    #include <clocale>
    #include <cmath>
    #include <complex>     //复数类
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <deque>      //STL 双端队列容器
    #include <exception>    //异常处理类
    #include <fstream>
    #include <functional>   //STL 定义运算函数(代替运算符)
    #include <limits>
    #include <list>      //STL 线性列表容器
    #include <map>       //STL 映射容器
    #include <iomanip>
    #include <ios>       //基本输入/输出支持
    #include <iosfwd>     //输入/输出系统使用的前置声明
    #include <iostream>
    #include <istream>     //基本输入流
    #include <ostream>     //基本输出流
    #include <queue>      //STL 队列容器
    #include <set>       //STL 集合容器
    #include <sstream>     //基于字符串的流
    #include <stack>      //STL 堆栈容器    
    #include <stdexcept>    //标准异常类
    #include <streambuf>    //底层输入/输出支持
    #include <string>     //字符串类
    #include <utility>     //STL 通用模板类
    #include <vector>     //STL 动态数组容器
    #include <cwchar>
    #include <cwctype>

    using namespace std;

    //////////////////////////////////////////////////////////////////////////

    C99 增加

    #include <complex.h>   //复数处理
    #include <fenv.h>    //浮点环境
    #include <inttypes.h>  //整数格式转换
    #include <stdbool.h>   //布尔环境
    #include <stdint.h>   //整型环境
    #include <tgmath.h>   //通用类型数学宏

    作者:admini | 分类目录:应用程序 | 标签:
  • IIS的HTTPERR错误日志解决

    2011-11-30

    解决方案
    如果您检查 C:\Windows\system32\LogFiles\HTTPERR\httperr*.log 文件在父 SUS 服务器, 您会将可能看到 Timer_MinBytesPerSecond 错误或 Timer_ConnectionIdle 错误。 这些是由 IIS 默认设置, 内其元数据库, 定义用于连接到保持活动小通信流速率和最大空闲时间之前连接中断允许。

    1) 从 IIS 管理器右键单击 Internet Information Server (IIS) 管理器级别根目录上并转到属性。 选中要启用直接编辑元数据库框。 单击确定。
    在记事本中打开 C:\Windows\system32\inetsrv\MetaBase.xml 文件 2)。 要搜索有关 " MinFileBytesPerSec "。 将用于 MinFileBytesPerSec 设置从 240 更改为 0。 执行其他搜索, 该时间将 600 " ConnectionTimeout "。 保存更改并退出。
    3) 重新启动 IISAdmin 服务以更改生效。

    作者:admini | 分类目录:服务器 | 标签:
  • 让Iframe自适应高度

    2011-11-30

    iframe,尤其是不带边框的iframe因为能和网页无缝的结合从而不刷新页面的情况下更新页面的部分数据成为可能,可是iframe的大小却不像层那样可以“伸缩自如”,所以带来了使用上的麻烦,给iframe设置高度的时候多了也不好,少了更是不行,现在,让我来告诉大家一种iframe动态调整高度的方法,主要是以下JS函数:
     程序代码
    function SetWinHeight(obj)
    {
     var win=obj;
     if (document.getElementById)
     {
      if (win && !window.opera)
      {
       if (win.contentDocument && win.contentDocument.body.offsetHeight)

        win.height = win.contentDocument.body.offsetHeight;
       else if(win.Document && win.Document.body.scrollHeight)
        win.height = win.Document.body.scrollHeight;
      }
     }
    }
    最后,加入iframe,不能丢掉onload属性,当然了,id也必须也函数中的win匹配
     程序代码
    <iframe width="778" align="center" height="200" id="win" name="win" onload="Javascript:SetWinHeight(this)" frameborder="0" scrolling="no"></iframe>

    另一种情况的iframe解决方案(超简单)
    重要提示:src=中你必须填写的网页地址,一定要和本页面在同一个站点上,否则,会抱错,说“拒绝访问!”(实际上这是因为Js的跨域问题导致拒绝访问的)
    之前自己也碰到过这个问题,为了得到答案去网上搜索,发现有不少人也遇到了这样的问题,现在就把解决方法共享一下

    1、建立一个bottom.js的文件,然后输入下面的代码(只有两行哦)
    parent.document.all("框架ID名").style.height=document.body.scrollHeight;
    parent.document.all("框架ID名").style.width=document.body.scrollWidth;
    这里的 框架ID名 就是Iframe的ID,比如:
    <IFRAME id="框架ID名" name="left" frameBorder=0 scrolling=no src="XXX.asp" width="100%"></IFRAME>

    2、给你网站里所有的被包含文件里面每个都加入
    <script language = "JavaScript" src = "bottom.js"/></script>
    3、OK,收工!
    在WINXP、IE6下面测试通过。很简单吧!

    实现 iframe 的自适应高度
    实现 iframe 的自适应高度,能够随着页面的长度自动的适应以免除页面和 iframe 同时出现滚动条的现象。
     程序代码
    <script type="text/javascript">
    //** iframe自动适应页面 **//

    //输入你希望根据页面高度自动调整高度的iframe的名称的列表
    //用逗号把每个iframe的ID分隔. 例如: ["myframe1", "myframe2"],可以只有一个窗体,则不用逗号。

    //定义iframe的ID
    var iframeids=["test"]

    //如果用户的浏览器不支持iframe是否将iframe隐藏 yes 表示隐藏,no表示不隐藏
    var iframehide="yes"

    function dyniframesize()
    {
    var dyniframe=new Array()
    for (i=0; i<iframeids.length; i++)
    {
    if (document.getElementById)
    {
    //自动调整iframe高度
    dyniframe[dyniframe.length] = document.getElementById(iframeids);
    if (dyniframe && !window.opera)
    {
    dyniframe.style.display="block"
    if (dyniframe.contentDocument && dyniframe.contentDocument.body.offsetHeight) //如果用户的浏览器是NetScape
    dyniframe.height = dyniframe.contentDocument.body.offsetHeight;
    else if (dyniframe.Document && dyniframe.Document.body.scrollHeight) //如果用户的浏览器是IE
    dyniframe.height = dyniframe.Document.body.scrollHeight;
    }
    }
    //根据设定的参数来处理不支持iframe的浏览器的显示问题
    if ((document.all || document.getElementById) && iframehide=="no")
    {
    var tempobj=document.all? document.all[iframeids] : document.getElementById(iframeids)
    tempobj.style.display="block"
    }
    }
    }

    if (window.addEventListener)
    window.addEventListener("load", dyniframesize, false)
    else if (window.attachEvent)
    window.attachEvent("onload", dyniframesize)
    else
    window.onload=dyniframesize
    </script>

    作者:admini | 分类目录:web技术 | 标签: