Jul
30
MySQL已经成为当前网络中使用最多的数据库之一,特别是在Web应用上,它占据了中小型应用的绝对优势。这一切都源于它的小巧易用、安全有效、开放式许可和多平台,更主要的是它与三大Web语言之一——PHP的完美结合。
但不幸的是,一个缺省安装的MySQL,会因为root密码为空及程序漏洞导致被溢出,使得安装MySQL的服务器成为被经常攻击的对象。更严重的是,被攻击之后数据库往往遭破坏,易造成灾难性的后果。下面将进入为了保护数据而进行的保卫战中。
环境要求
.系统环境:
有一台Red Hat Linux 9.0自定义安装的服务器,系统安装了GCC及一些软件包,比如Apache、PHP等。安装完系统后的第一件事就是升级系统的软件包。作为Web服务器,系统接受PHP脚本的请求,PHP则使用下面将要安装的MySQL数据库作为动态发布的接触。
分区情况的要求和一般系统差不多,惟一不同之处在于后面建立的/chroot与/tmp要求在同一个分区上。
2.安全要求:
()MySQL运行在一个独立的(Chroot)环境下;
(2)mysqld进程运行于一个独立的用户/用户组下,此用户和用户组没有根目录,没有Shell,也不能用于其它程序;
(3)修改MySQL的root账号,并使用一个复杂的密码;
(4)只允许本地连接MySQL,启动MySQL时网络连接被禁止掉;
(5)保证连接MySQL的nobody账号登录被禁止;
(6)删除test数据库。
安装MySQL
.安装准备:
安装MySQL之前,按照上述安全要求需要创建一个用于启动MySQL的用户和组。
#groupadd mysql#useradd
mysql -c "start mysqlds account" -d
dev/null -g mysql -s /sbin/nologin
2.编译和安装:
下载MySQL源代码包:
#wget http://mysql.he.net/Downloads/MySQL-4.0/mysql-4.0.6.tar.gz
解压缩:
#tar -zxvf mysql-4.0.6.tar.gz
一般把MySQL安装在/usr/local/mysql下,如果有特殊要求,也可自行调整。不过这样做意义不大,因为后面将Chrooting,到时只是使用这里的客户工具而已,比如mysql,mysqladmin,mysqldump等。下面就开始编译安装吧。
#./configure --prefix=/usr/local/mysql
\ --with-mysqld-user=mysql \ --with-unix-socket-path=/tmp/mysql.sock
\ --with-mysqld-ldflags=-all-static#make && make
install#strip /usr/local/mysql/libexec
/mysqld#scripts/mysql_install_db#chown
-R root /usr/local/mysql#chown -R mysql
/usr/local/mysql/var#chgrp -R mysql /usr/local/mysql
上面各步骤的具体作用在MySQL手册里已有介绍,惟一需要解释、和一般步骤不同的地方在于--with-mysqld-ldflags=-all-static。因为需要用到Chroot环境,而MySQL本身连接成静态后就无需再创建一些库环境了。
3.配置与启动:
MySQL的配置文件需要手工选择、拷贝几个模板文件中的一个到/etc下,这几个模板文件位于源文件的support-files目录,一共有4个:small、medium、large、huge。
#cp support-files/my-medium.cnf
/etc/my.cnf#chown root:sys /etc/my.cnf#chmod
644 /etc/my.cnf
启动MySQL,注意使用用户为MySQL:
#/usr/local/mysq/bin/mysqld_safe --user=mysql &
4.测试:
为了测试安装的程序是否正确及MySQL是否已经正常启动,最好的办法就是用MySQL客户端来连接数据库。
#/usr/local/mysql/bin/mysql[root@ftp bin]
# mysqlWelcome to the MySQL monitor. Commands
end with ; o \g.Your MySQL connection id is
687 to server version: 3.23.58Type help;
o \h for help. Type \c to clear the
buffer.mysql>mysql> show d
atabases;+--------------+
Database +--------------+
mysql test +--------------+2
rows in set (0.00 sec)mysql>quit
连接成功,可以关闭数据库:
#/usr/local/mysql/bin/mysqladmin -uroot shutdown
如果连接失败则需要仔细分析出错原因:
#more /usr/local/mysql/var/`hostname`.err
Chrooting
.Chrooting环境:
Chroot是Unix/类Unix的一种手段,它的建立会将其与主系统几乎完全隔离。也就是说,一旦遭到什么问题,也不会危及到正在运行的主系统。这是一个非常有效的办法,特别是在配置网络服务程序的时候。
2.Chroot的准备工作:
首先,应当建立目录结构:
#mkdir -p /chroot/mysql/dev#mkdir -p
/chroot/mysql/etc#mkdir -p /chroot/mysql/tmp#mkdir -p
/chroot/mysql/var/tmp#mkdir -p /chroot
/mysql/usr/local/mysql/libexec#mkdir -p
/chroot/mysql/usr/local/mysql/share
/mysql/english
然后设定目录权限:
#chown -R root:sys /chroot/mysql#chmod -R 755 /chroot/mysql#chmod 777 /chroot/mysql/tmp
3.拷贝mysql目录下的程序和文件到chroot下:
#cp -p /usr/local/mysql/libexec
/mysqld /chroot/mysql/usr/
local/mysql/libexec/#cp -p /usr/local/mysql/share
/mysql/english/errmsg.sys/chroot/mysql/usr/local
/mysql/share/mysql/english/#cp -p /etc/hosts
/chroot/mysql/etc/#cp -p /etc/host.conf /chroot
/mysql/etc/#cp -p /etc/resolv.conf /chroot
/mysql/etc/#cp -p
/etc/group /chroot/mysql/etc
/#cp -p /etc/passwd
/chroot/mysql/etc/passwd#cp -p
/etc/my.cnf /chroot/mysql/etc/
但不幸的是,一个缺省安装的MySQL,会因为root密码为空及程序漏洞导致被溢出,使得安装MySQL的服务器成为被经常攻击的对象。更严重的是,被攻击之后数据库往往遭破坏,易造成灾难性的后果。下面将进入为了保护数据而进行的保卫战中。
环境要求
.系统环境:
有一台Red Hat Linux 9.0自定义安装的服务器,系统安装了GCC及一些软件包,比如Apache、PHP等。安装完系统后的第一件事就是升级系统的软件包。作为Web服务器,系统接受PHP脚本的请求,PHP则使用下面将要安装的MySQL数据库作为动态发布的接触。
分区情况的要求和一般系统差不多,惟一不同之处在于后面建立的/chroot与/tmp要求在同一个分区上。
2.安全要求:
()MySQL运行在一个独立的(Chroot)环境下;
(2)mysqld进程运行于一个独立的用户/用户组下,此用户和用户组没有根目录,没有Shell,也不能用于其它程序;
(3)修改MySQL的root账号,并使用一个复杂的密码;
(4)只允许本地连接MySQL,启动MySQL时网络连接被禁止掉;
(5)保证连接MySQL的nobody账号登录被禁止;
(6)删除test数据库。
安装MySQL
.安装准备:
安装MySQL之前,按照上述安全要求需要创建一个用于启动MySQL的用户和组。
#groupadd mysql#useradd
mysql -c "start mysqlds account" -d
dev/null -g mysql -s /sbin/nologin
2.编译和安装:
下载MySQL源代码包:
#wget http://mysql.he.net/Downloads/MySQL-4.0/mysql-4.0.6.tar.gz
解压缩:
#tar -zxvf mysql-4.0.6.tar.gz
一般把MySQL安装在/usr/local/mysql下,如果有特殊要求,也可自行调整。不过这样做意义不大,因为后面将Chrooting,到时只是使用这里的客户工具而已,比如mysql,mysqladmin,mysqldump等。下面就开始编译安装吧。
#./configure --prefix=/usr/local/mysql
\ --with-mysqld-user=mysql \ --with-unix-socket-path=/tmp/mysql.sock
\ --with-mysqld-ldflags=-all-static#make && make
install#strip /usr/local/mysql/libexec
/mysqld#scripts/mysql_install_db#chown
-R root /usr/local/mysql#chown -R mysql
/usr/local/mysql/var#chgrp -R mysql /usr/local/mysql
上面各步骤的具体作用在MySQL手册里已有介绍,惟一需要解释、和一般步骤不同的地方在于--with-mysqld-ldflags=-all-static。因为需要用到Chroot环境,而MySQL本身连接成静态后就无需再创建一些库环境了。
3.配置与启动:
MySQL的配置文件需要手工选择、拷贝几个模板文件中的一个到/etc下,这几个模板文件位于源文件的support-files目录,一共有4个:small、medium、large、huge。
#cp support-files/my-medium.cnf
/etc/my.cnf#chown root:sys /etc/my.cnf#chmod
644 /etc/my.cnf
启动MySQL,注意使用用户为MySQL:
#/usr/local/mysq/bin/mysqld_safe --user=mysql &
4.测试:
为了测试安装的程序是否正确及MySQL是否已经正常启动,最好的办法就是用MySQL客户端来连接数据库。
#/usr/local/mysql/bin/mysql[root@ftp bin]
# mysqlWelcome to the MySQL monitor. Commands
end with ; o \g.Your MySQL connection id is
687 to server version: 3.23.58Type help;
o \h for help. Type \c to clear the
buffer.mysql>mysql> show d
atabases;+--------------+
Database +--------------+
mysql test +--------------+2
rows in set (0.00 sec)mysql>quit
连接成功,可以关闭数据库:
#/usr/local/mysql/bin/mysqladmin -uroot shutdown
如果连接失败则需要仔细分析出错原因:
#more /usr/local/mysql/var/`hostname`.err
Chrooting
.Chrooting环境:
Chroot是Unix/类Unix的一种手段,它的建立会将其与主系统几乎完全隔离。也就是说,一旦遭到什么问题,也不会危及到正在运行的主系统。这是一个非常有效的办法,特别是在配置网络服务程序的时候。
2.Chroot的准备工作:
首先,应当建立目录结构:
#mkdir -p /chroot/mysql/dev#mkdir -p
/chroot/mysql/etc#mkdir -p /chroot/mysql/tmp#mkdir -p
/chroot/mysql/var/tmp#mkdir -p /chroot
/mysql/usr/local/mysql/libexec#mkdir -p
/chroot/mysql/usr/local/mysql/share
/mysql/english
然后设定目录权限:
#chown -R root:sys /chroot/mysql#chmod -R 755 /chroot/mysql#chmod 777 /chroot/mysql/tmp
3.拷贝mysql目录下的程序和文件到chroot下:
#cp -p /usr/local/mysql/libexec
/mysqld /chroot/mysql/usr/
local/mysql/libexec/#cp -p /usr/local/mysql/share
/mysql/english/errmsg.sys/chroot/mysql/usr/local
/mysql/share/mysql/english/#cp -p /etc/hosts
/chroot/mysql/etc/#cp -p /etc/host.conf /chroot
/mysql/etc/#cp -p /etc/resolv.conf /chroot
/mysql/etc/#cp -p
/etc/group /chroot/mysql/etc
/#cp -p /etc/passwd
/chroot/mysql/etc/passwd#cp -p
/etc/my.cnf /chroot/mysql/etc/
Jul
30
.NET的数据库天然支持MSSQLServer,但是并非其他数据库不支持,而是微软基于自身利益需要,在支持、营销上推自己的数据库产品;但是作为平台战略,他并非排斥其他数据库,而是参考java体系提出了一套数据库访问规范,让各个第三方进行开发,提供特定的驱动。
MySQL是免费的数据库,在成本上具有无可替代的优势,但是目前来讲,并没有提供。微软把MySQL当作ODBC数据库,可以按照ODBC.Net规范进行访问,具体参考
http://www.microsoft.com/china/community/Columns/Luyan/6.mspx
而实际上,针对ODBC。Net的需要配置DSN的麻烦,而是出现了一个开源的系统MySQLDriverCS,对MySQL的开发进行了封装,实现了.net环境下对于MySQL数据库系统的访问。
http://sourceforge.net/projects/mysqldrivercs/
通过阅读源代码,我们看到MySQLDriverCS的思路是利用C函数的底层库来操纵数据库的,通常提供对MySQL数据库的访问的数据库的C DLL是名为libmySQL.dll的驱动文件,MySQLDriverCS作为一个.net库进行封装C风格的驱动。
具体如何进行呢?
打开工程后,我们看到其中有一个比较特殊的.cs文件CPrototypes.cs:
以下是引用片段:
#region LICENSE
/*
MySQLDriverCS: An C# driver for MySQL.
Copyright (c) 2002 Manuel Lucas Vi馻s Livschitz.
This file is part of MySQLDriverCS.
MySQLDriverCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, o
(at your option) any later version.
MySQLDriverCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY o FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with MySQLDriverCS; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02-307 USA
*/
#endregion
using System;
using System.Data;
using System.Runtime.InteropServices;
namespace MySQLDriverCS
{
//[StructLayout(LayoutKind.Sequential)]
public class MYSQL_FIELD_FACTORY
{
static string version;
public static IMYSQL_FIELD GetInstance()
{
if (version==null)
{
version = CPrototypes.GetClientInfo();
}
if (version.CompareTo("4..2-alpha")>=0)
{
return new MYSQL_FIELD_VERSION_5();
}
else
return new MYSQL_FIELD_VERSION_3();
}
}
public interface IMYSQL_FIELD
{
string Name{get;}
uint Type{get;}
long Max_Length {get;}
}
///<summary>
/// Field descriptor
///</summary>
[StructLayout(LayoutKind.Sequential)]//"3.23.32", 4.0.-alpha
internal class MYSQL_FIELD_VERSION_3: IMYSQL_FIELD
{
///<summary>
/// Name of column
///</summary>
public string name;
///<summary>
/// Table of column if column was a field
///</summary>
public string table;
//public string og_table; /* og table name if table was an alias */
//public string db; /* Database for table */
///<summary>
/// def
///</summary>
public string def;
///<summary>
/// length
///</summary>
public long length;
///<summary>
/// max_length
///</summary>
public long max_length;
///<summary>
/// Div flags
///</summary>
public uint flags;
///<summary>
/// Number of decimals in field
///</summary>
public uint decimals;
///<summary>
/// Type of field. Se mysql_com.h for types
///</summary>
public uint type;
///<summary>
/// Name
///</summary>
public string Name
{
get{return name;}
}
///<summary>
/// Type
///</summary>
public uint Type
{
get{return type;}
}
///<summary>
/// Max_Length
///</summary>
public long Max_Length
{
get {return max_length;}
}
}
///<summary>
/// Field descriptor
///</summary>
[StructLayout(LayoutKind.Sequential)]
internal class MYSQL_FIELD_VERSION_5: IMYSQL_FIELD
{
///<summary>
/// Name of column
///</summary>
public string name;
///<summary>
/// oiginal column name, if an alias
///</summary>
public string og_name;
///<summary>
/// Table of column if column was a field
///</summary>
public string table;
///<summary>
/// og table name if table was an alias
///</summary>
public string og_table;
///<summary>
/// Database for table
///</summary>
public string db;
///<summary>
/// Catalog for table
///</summary>
//public string catalog;
///<summary>
/// def
///</summary>
public string def;
///<summary>
/// length
///</summary>
public long length;
///<summary>
/// max_length
///</summary>
public long max_length;
///<summary>
/// name_length
///</summary>
//public uint name_length;
///<summary>
/// og_name_length
///</summary>
public uint og_name_length;
///<summary>
/// table_length
///</summary>
public uint table_length;
///<summary>
/// og_table_length
///</summary>
public uint og_table_length;
///<summary>
/// db_length
///</summary>
public uint db_length;
///<summary>
/// catalog_length
///</summary>
public uint catalog_length;
///<summary>
/// def_length
///</summary>
public uint def_length;
///<summary>
/// Div flags
///</summary>
public uint flags;
///<summary>
/// Number of decimals in field
///</summary>
public uint decimals;
///<summary>
/// Character set
///</summary>
public uint charsetnr;
///<summary>
/// Type of field. Se mysql_com.h for types
///</summary>
public uint type;
///<summary>
/// Name
///</summary>
public string Name
{
get {return name;}
}
///<summary>
/// Type
///</summary>
public uint Type
{
get {return type;}
}
///<summary>
/// Max_Length
///</summary>
public long Max_Length
{
get {return max_length;}
}
}
//[StructLayout(LayoutKind.Explicit)]
public enum enum_field_types
{
FIELD_TYPE_DECIMAL, FIELD_TYPE_TINY,
FIELD_TYPE_SHORT, FIELD_TYPE_LONG,
FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE,
FIELD_TYPE_NULL, FIELD_TYPE_TIMESTAMP,
FIELD_TYPE_LONGLONG,FIELD_TYPE_INT24,
FIELD_TYPE_DATE, FIELD_TYPE_TIME,
FIELD_TYPE_DATETIME, FIELD_TYPE_YEAR,
FIELD_TYPE_NEWDATE,
FIELD_TYPE_ENUM=247,
FIELD_TYPE_SET=248,
FIELD_TYPE_TINY_BLOB=249,
FIELD_TYPE_MEDIUM_BLOB=250,
FIELD_TYPE_LONG_BLOB=25,
FIELD_TYPE_BLOB=252,
FIELD_TYPE_VAR_STRING=253,
FIELD_TYPE_STRING=254,
FIELD_TYPE_GEOMETRY=255
};
///<summary>
/// C prototypes warpper for mysqllib.
///</summary>
internal class CPrototypes
{
[ DllImport( "libmySQL.dll", EntryPoint="mysql_init" )]
unsafe public static extern void* mysql_init(void* must_be_null);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_close" )]
unsafe public static extern void mysql_close(void* handle);
// BEGIN ADDITION 2004-07-0 BY Alex Seewald
// Enables us to call mysql_option to activate compression and timeout
[ DllImport( "libmySQL.dll", EntryPoint="mysql_options" )]
unsafe public static extern void mysql_options(void* mysql, uint option, uint *value);
// END ADDITION 2004-07-0 By Alex Seewald
[ DllImport( "libmySQL.dll", EntryPoint="mysql_real_connect" )]
unsafe public static extern void* mysql_real_connect(void* mysql, string host, string user, string passwd, string db, uint port, string unix_socket, int client_flag);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_query" )]
unsafe public static extern int mysql_query(void*mysql, string query);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_store_result" )]
unsafe public static extern void *mysql_store_result(void *mysql);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_free_result" )]
unsafe public static extern void mysql_free_result(void*result);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_errno" )]
unsafe public static extern uint mysql_errno(void*mysql);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_error" )]
unsafe public static extern string mysql_error(void*mysql);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_field_count" )]
unsafe public static extern uint mysql_field_count(void*mysql);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_affected_rows" )]
unsafe public static extern ulong mysql_affected_rows(void*mysql);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_num_fields" )]
unsafe public static extern uint mysql_num_fields(void*result);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_num_rows" )]
unsafe public static extern ulong mysql_num_rows(void *result);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_fetch_field_direct" )]
unsafe public static extern IntPtr mysql_fetch_field_direct(void*result, uint fieldnr);
///<returns>Returns a string that represents the client library version</returns>
[DllImport("libmySQL.dll",CharSet=System.Runtime.InteropServices.CharSet.Ansi,
EntryPoint="mysql_get_client_info", ExactSpelling=true)]
public static extern string GetClientInfo();
[ DllImport( "libmySQL.dll", EntryPoint="mysql_fetch_row" )]
unsafe public static extern IntPtr mysql_fetch_row(void*result);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_selct_db" )]
unsafe public static extern int mysql_selct_db(void*mysql,string dbname);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_fetch_lengths" )]
unsafe public static extern UInt32 *mysql_fetch_lengths(void*result);
}
}
基本上是将C风格的基础数据结构进行.net的重新定义,然后通过InteropServices进行访问。
具体如何利用这个库进行操作,可以参考其中的例子。
MySQL是免费的数据库,在成本上具有无可替代的优势,但是目前来讲,并没有提供。微软把MySQL当作ODBC数据库,可以按照ODBC.Net规范进行访问,具体参考
http://www.microsoft.com/china/community/Columns/Luyan/6.mspx
而实际上,针对ODBC。Net的需要配置DSN的麻烦,而是出现了一个开源的系统MySQLDriverCS,对MySQL的开发进行了封装,实现了.net环境下对于MySQL数据库系统的访问。
http://sourceforge.net/projects/mysqldrivercs/
通过阅读源代码,我们看到MySQLDriverCS的思路是利用C函数的底层库来操纵数据库的,通常提供对MySQL数据库的访问的数据库的C DLL是名为libmySQL.dll的驱动文件,MySQLDriverCS作为一个.net库进行封装C风格的驱动。
具体如何进行呢?
打开工程后,我们看到其中有一个比较特殊的.cs文件CPrototypes.cs:
以下是引用片段:
#region LICENSE
/*
MySQLDriverCS: An C# driver for MySQL.
Copyright (c) 2002 Manuel Lucas Vi馻s Livschitz.
This file is part of MySQLDriverCS.
MySQLDriverCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, o
(at your option) any later version.
MySQLDriverCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY o FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with MySQLDriverCS; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02-307 USA
*/
#endregion
using System;
using System.Data;
using System.Runtime.InteropServices;
namespace MySQLDriverCS
{
//[StructLayout(LayoutKind.Sequential)]
public class MYSQL_FIELD_FACTORY
{
static string version;
public static IMYSQL_FIELD GetInstance()
{
if (version==null)
{
version = CPrototypes.GetClientInfo();
}
if (version.CompareTo("4..2-alpha")>=0)
{
return new MYSQL_FIELD_VERSION_5();
}
else
return new MYSQL_FIELD_VERSION_3();
}
}
public interface IMYSQL_FIELD
{
string Name{get;}
uint Type{get;}
long Max_Length {get;}
}
///<summary>
/// Field descriptor
///</summary>
[StructLayout(LayoutKind.Sequential)]//"3.23.32", 4.0.-alpha
internal class MYSQL_FIELD_VERSION_3: IMYSQL_FIELD
{
///<summary>
/// Name of column
///</summary>
public string name;
///<summary>
/// Table of column if column was a field
///</summary>
public string table;
//public string og_table; /* og table name if table was an alias */
//public string db; /* Database for table */
///<summary>
/// def
///</summary>
public string def;
///<summary>
/// length
///</summary>
public long length;
///<summary>
/// max_length
///</summary>
public long max_length;
///<summary>
/// Div flags
///</summary>
public uint flags;
///<summary>
/// Number of decimals in field
///</summary>
public uint decimals;
///<summary>
/// Type of field. Se mysql_com.h for types
///</summary>
public uint type;
///<summary>
/// Name
///</summary>
public string Name
{
get{return name;}
}
///<summary>
/// Type
///</summary>
public uint Type
{
get{return type;}
}
///<summary>
/// Max_Length
///</summary>
public long Max_Length
{
get {return max_length;}
}
}
///<summary>
/// Field descriptor
///</summary>
[StructLayout(LayoutKind.Sequential)]
internal class MYSQL_FIELD_VERSION_5: IMYSQL_FIELD
{
///<summary>
/// Name of column
///</summary>
public string name;
///<summary>
/// oiginal column name, if an alias
///</summary>
public string og_name;
///<summary>
/// Table of column if column was a field
///</summary>
public string table;
///<summary>
/// og table name if table was an alias
///</summary>
public string og_table;
///<summary>
/// Database for table
///</summary>
public string db;
///<summary>
/// Catalog for table
///</summary>
//public string catalog;
///<summary>
/// def
///</summary>
public string def;
///<summary>
/// length
///</summary>
public long length;
///<summary>
/// max_length
///</summary>
public long max_length;
///<summary>
/// name_length
///</summary>
//public uint name_length;
///<summary>
/// og_name_length
///</summary>
public uint og_name_length;
///<summary>
/// table_length
///</summary>
public uint table_length;
///<summary>
/// og_table_length
///</summary>
public uint og_table_length;
///<summary>
/// db_length
///</summary>
public uint db_length;
///<summary>
/// catalog_length
///</summary>
public uint catalog_length;
///<summary>
/// def_length
///</summary>
public uint def_length;
///<summary>
/// Div flags
///</summary>
public uint flags;
///<summary>
/// Number of decimals in field
///</summary>
public uint decimals;
///<summary>
/// Character set
///</summary>
public uint charsetnr;
///<summary>
/// Type of field. Se mysql_com.h for types
///</summary>
public uint type;
///<summary>
/// Name
///</summary>
public string Name
{
get {return name;}
}
///<summary>
/// Type
///</summary>
public uint Type
{
get {return type;}
}
///<summary>
/// Max_Length
///</summary>
public long Max_Length
{
get {return max_length;}
}
}
//[StructLayout(LayoutKind.Explicit)]
public enum enum_field_types
{
FIELD_TYPE_DECIMAL, FIELD_TYPE_TINY,
FIELD_TYPE_SHORT, FIELD_TYPE_LONG,
FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE,
FIELD_TYPE_NULL, FIELD_TYPE_TIMESTAMP,
FIELD_TYPE_LONGLONG,FIELD_TYPE_INT24,
FIELD_TYPE_DATE, FIELD_TYPE_TIME,
FIELD_TYPE_DATETIME, FIELD_TYPE_YEAR,
FIELD_TYPE_NEWDATE,
FIELD_TYPE_ENUM=247,
FIELD_TYPE_SET=248,
FIELD_TYPE_TINY_BLOB=249,
FIELD_TYPE_MEDIUM_BLOB=250,
FIELD_TYPE_LONG_BLOB=25,
FIELD_TYPE_BLOB=252,
FIELD_TYPE_VAR_STRING=253,
FIELD_TYPE_STRING=254,
FIELD_TYPE_GEOMETRY=255
};
///<summary>
/// C prototypes warpper for mysqllib.
///</summary>
internal class CPrototypes
{
[ DllImport( "libmySQL.dll", EntryPoint="mysql_init" )]
unsafe public static extern void* mysql_init(void* must_be_null);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_close" )]
unsafe public static extern void mysql_close(void* handle);
// BEGIN ADDITION 2004-07-0 BY Alex Seewald
// Enables us to call mysql_option to activate compression and timeout
[ DllImport( "libmySQL.dll", EntryPoint="mysql_options" )]
unsafe public static extern void mysql_options(void* mysql, uint option, uint *value);
// END ADDITION 2004-07-0 By Alex Seewald
[ DllImport( "libmySQL.dll", EntryPoint="mysql_real_connect" )]
unsafe public static extern void* mysql_real_connect(void* mysql, string host, string user, string passwd, string db, uint port, string unix_socket, int client_flag);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_query" )]
unsafe public static extern int mysql_query(void*mysql, string query);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_store_result" )]
unsafe public static extern void *mysql_store_result(void *mysql);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_free_result" )]
unsafe public static extern void mysql_free_result(void*result);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_errno" )]
unsafe public static extern uint mysql_errno(void*mysql);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_error" )]
unsafe public static extern string mysql_error(void*mysql);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_field_count" )]
unsafe public static extern uint mysql_field_count(void*mysql);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_affected_rows" )]
unsafe public static extern ulong mysql_affected_rows(void*mysql);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_num_fields" )]
unsafe public static extern uint mysql_num_fields(void*result);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_num_rows" )]
unsafe public static extern ulong mysql_num_rows(void *result);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_fetch_field_direct" )]
unsafe public static extern IntPtr mysql_fetch_field_direct(void*result, uint fieldnr);
///<returns>Returns a string that represents the client library version</returns>
[DllImport("libmySQL.dll",CharSet=System.Runtime.InteropServices.CharSet.Ansi,
EntryPoint="mysql_get_client_info", ExactSpelling=true)]
public static extern string GetClientInfo();
[ DllImport( "libmySQL.dll", EntryPoint="mysql_fetch_row" )]
unsafe public static extern IntPtr mysql_fetch_row(void*result);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_selct_db" )]
unsafe public static extern int mysql_selct_db(void*mysql,string dbname);
[ DllImport( "libmySQL.dll", EntryPoint="mysql_fetch_lengths" )]
unsafe public static extern UInt32 *mysql_fetch_lengths(void*result);
}
}
基本上是将C风格的基础数据结构进行.net的重新定义,然后通过InteropServices进行访问。
具体如何利用这个库进行操作,可以参考其中的例子。
Jul
30
随着网络的普及,基于网络的应用也越来越多。网络数据库就是其中之一。通过一台或几台服务器可以为很多客户提供服务,这种方式给人们带来了很多方便,但也给不法分子造成了可乘之机。由于数据都是通过网络传输的,这就可以在传输的过程中被截获,或者通过非常手段进入数据库。由于以上原因,数据库安全就显得十分重要。因此,本文就以上问题讨论了MySQL数据库在网络安全方面的一些功能。
账户安全
账户是MySQL最简单的安全措施。每一账户都由用户名、密码以及位置(一般由服务器名、IP或通配符)组成。如用户john从server进行登录可能和john从server2登录的权限不同。
MySQL的用户结构是用户名/密码/位置。这其中并不包括数据库名。下面的两条命令为database和database2设置了Selct用户权限。
GRANT Selct ON database.* to 'abc'@'server' IDENTIFIED BY 'password';GRANT Selct ON database2.* to 'abc'@'server' IDENTIFIED BY 'password2';
第一条命令设置了用户abc在连接数据库database时使用password。第二条命令设置了用户abc在连接数据库database2时使用password2。因此,用户abc在连接数据库database和database2的密码是不一样的。
上面的设置是非常有用的。如果你只想让用户对一个数据库进行有限的访问,而对其它数据库不能访问,这样可以对同一个用户设置不同的密码。如果不这样做,当用户发现这个用户名可以访问其它数据库时,那将会造成麻烦。
MySQL使用了很多授权表来跟踪用户和这些用户的不同权限。这些表就是在mysql数据库中的MyISAM表。将这些安全信息保存在MySQL中是非常有意义的。因此,我们可以使用标准的SQL来设置不同的权限。
一般在MySQL数据库中可以使用3种不同类型的安全检查:
·登录验证
也就是最常用的用户名和密码验证。一但你输入了正确的用户名和密码,这个验证就可通过。
·授权
在登录成功后,就要求对这个用户设置它的具体权限。如是否可以删除数据库中的表等。
·访问控制
这个安全类型更具体。它涉及到这个用户可以对数据表进行什么样的操作,如是否可以编辑数据库,是否可以查询数据等等。
访问控制由一些特权组成,这些特权涉及到所何使用和操作MySQL中的数据。它们都是布尔型,即要么允许,要么不允许。下面是这些特权的列表:
·Selct
Selct是设定用户是否可以使用Selct来查询数据。如果用户没有这个特权,那么就只能执行一些简单的Selct命令,如计算表达式(Selct +2),或是日期转换(Selct Unix_TIMESTAMP(NOW( )))等。
·Insrt
·Upate
·INDEX
INDEX决定用户是否可以对表的索引进行设置。如果用户没有这个权限,那么将无法设置表中的索引。
·Altr
·Crate
·GRANT
如果一个用户拥有这个GRANT权限,那么他就可以将自己的权限授给别的用户。也就是说,这个用户可以和其它用户共享自己的权限。
·REFERENCES
有了REFERENCES权限,用户就可以将其它表的一个字段作为某一个表的外键约束。
除了以上的权限外,MySQL还有一些权限可以对整个MySQL进行操作。
·Reload
这个权限可以使用户有权执行各种FLUSH命令,如FLUSH TABLES, FLUSH STATUS等。
·Shutdown
这个权限允许用户关闭MySQL
·Process
通过这个权限,用户可以执行SHOW PROCESSLIST和KILL命令。这些命令可以查看MySQL的处理进程,可以通过这种方式查看SQL执行的细节。
·File
这个权限决定用户是否可以执行LOAD DATA INFILE命令。给用户这个权限要慎重,因为有这个权限的用户可以将任意的文件装载到表中,这样对MySQL是十分危险的。
·Super
这个权限允许用户终止任何查询(这些查询可能并不是这个用户执行的)。
以上几种权限是非常危险的,在给用户授权限时要非常谨慎。
MySQL中的SSL
以上的账户安全只是以普通的Socket进行数据传输的,这样非常不安全。因此,MySQL在4.版以后提供了对SSL(Secure Scokets Layer)的支持。MySQL使用的是免费的OpenSSL库。
由于MySQL的Linux版本一般都是随Linux本身一起发布,因此,它们默认时都不使用SSL进行传输数据。如果要打开SSL功能,需要对hava_openssl变量进行设置:
MySQL的Windows版本已经将OpenSSL加入了。也面的命令是查看你的MySQL是否打开了SSL功能。
SHOW VARIABLES LIKE 'have_openssl'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | have_openssl | NO | +---------------+-------+ row in set (0.00 sec)
如果返回的是NO,那么说明你需要将OpenSSL编译进自己的MySQL。
在有时你可能需要将用户名和密码进行加密传输。在这时可以使用下面GRANT命令:
GRANT ALL PRIVILEGES ON ssl_only_db.* to 'abc'@'%' IDENTIFIED BY "password!" REQUIRE SSL;
还可以通过 REQUIRE x509 选项进行SSL传输:
GRANT ALL PRIVILEGES ON ssl_only_db.* to 'abc'@'%' IDENTIFIED BY "password!" REQUIRE x509;
你还可以使用REQUIRE SUBJECT来指定一个特定的客户端证书来访问数据库。
GRANT ALL PRIVILEGES ON ssl_only_db.* to 'abc'@'%'IDENTIFIED BY "password!"REQUIRE SUBJECT "/C=US/ST=New York/L=Albany/O=Widgets Inc./CN=client-ray.example.com/[email protected]";
也许你并不关心使用的是什么客户许可,而仅仅关心的是你的证书。那么你可以使用REQUIRE ISSUER来实现:
GRANT ALL PRIVILEGES ON ssl_only_db.* to 'abc'@'%' IDENTIFIED BY "password!"REQUIRE ISSUER "/C=US/ST=New+20York/L=Albany/O=Widgets Inc./CN=cacert.example.com/[email protected]";
SSL还可以直接通过密码进行加密。可以使用REQUIRE CIPHER设置密码。
GRANT ALL PRIVILEGES ON ssl_only_db.* 'abc'@'%' IDENTIFIED BY "password!"REQUIRE CIPHER "EDH-RSA-DES-CBC3-SHA";
上面使用了GRANT命令对用户权限进行设置。而这些信息都是保存在授权表中,这些表是安全系统的心脏。在这些表中保存了每一个用户和客户机所具有的权限。如果正确地操作这些表,将会对数据库的安全起到积极的作用,而如果使用不慎,将是非常危险的。
下面让我们来看看MySQL中的最要的5个授权表。
user
用户表保存了用户的权限和被加密的密码。这个表负责确定哪些用户和客户机可以连接到服务器上。
host
这个表为每一个客户机分配权限,它并不考虑用户的权限。MySQL在确定是否接收还是拒绝一个连接时,首先考虑的是user表。而使用GRANT或REVOKE命令并不影响host表,我们可以通过手工方式修改这个表中的内容。
db
db表保存了数据库层的权限信息。
tables_priv
这个表存储了表的权限信息。
columns_priv
这个表保存了单独列的权限信息。通过这个表,可以将操作某一列的权限授予一个用户。
哈希加密
如果数据库保存了敏感的数据,如银行卡密码,客户信息等,你可能想将这些数据以加密的形式保存在数据库中。这样即使有人进入了你的数据库,并看到了这些数据,也很难获得其中的真实信息。
在应用程序的大量信息中,也许你只想交很小的一部分进行加密,如用户的密码等。这些密码不应该以明文的形式保存,它们应该以加密的形式保存在数据库中。一般情况下,大多数系统,这其中包括MySQL本身都是使用哈希算法对敏感数据进行加密的。
哈希加密是单向加密,也就是说,被加密的字符串是无法得到原字符串的。这种方法使用很有限,一般只使用在密码验证或其它需要验证的地方。在比较时并不是将加密字符串进行解密,而是将输入的字符串也使用同样的方法进行加密,再和数据库中的加密字符串进行比较。这样即使知道了算法并得到了加密字符串,也无法还原最初的字符串。银行卡密码就是采用的这种方式进行加密。
MySQL提供了4个函数用于哈希加密:PASSWORD, ENCRYPT, SHA和MD5。下面让我们试一试这4个函数,看看会得到什么结果。我们以加密字符串"pa55word"为例进行说明:
让我们先来看看MD5函数
Selct MD5('pa55word'); +----------------------------------+ | MD5('pa55word') | +----------------------------------+ | a7a433755d6542fd005e8b43afd4 | +----------------------------------+ row in set (0.3 sec) 下面是PASSWORD函数 Selct PASSWORD('pa55word'); +----------------------+ | PASSWORD('pa55word') | +----------------------+ | d35c6556b8cab45 | +----------------------+ row in set (0.00 sec) 下面是ENCRYPT函数 Selct ENCRYPT('pa55word'); +---------------------+ | ENCRYPT('pa55word') | +---------------------+ | up2Ecb0Hdj25A | +---------------------+ row in set (0.7 sec)
上面的每个函数都返回了一个加密后的字符串。为了区分加密字符串的大小写,最好在使用ENCRYPT生成加密字符串时,将这个字段定义成CHAR BINARY类型。
上面列举了3种加密的方法,但我认为使用MD5加密是最好的。这是因为这样做可以将明文密码显示在处理列表中或是查询日志中,这样便于跟踪。如下面的Insrt语句使用插入了一条记录,其中的密码使用了MD5进行加密:
Insrt INTO table (user, pw) VALUE ('user', MD5('password') )
可以通过如下的语句进行密码验证:
Selct * FROM table Whre user = 'user' AND pw = MD5('password')
哈希加密方法可以很好地对密码进行加密,使用了这种方法加密,密码将无法恢复成明文。
账户安全
账户是MySQL最简单的安全措施。每一账户都由用户名、密码以及位置(一般由服务器名、IP或通配符)组成。如用户john从server进行登录可能和john从server2登录的权限不同。
MySQL的用户结构是用户名/密码/位置。这其中并不包括数据库名。下面的两条命令为database和database2设置了Selct用户权限。
GRANT Selct ON database.* to 'abc'@'server' IDENTIFIED BY 'password';GRANT Selct ON database2.* to 'abc'@'server' IDENTIFIED BY 'password2';
第一条命令设置了用户abc在连接数据库database时使用password。第二条命令设置了用户abc在连接数据库database2时使用password2。因此,用户abc在连接数据库database和database2的密码是不一样的。
上面的设置是非常有用的。如果你只想让用户对一个数据库进行有限的访问,而对其它数据库不能访问,这样可以对同一个用户设置不同的密码。如果不这样做,当用户发现这个用户名可以访问其它数据库时,那将会造成麻烦。
MySQL使用了很多授权表来跟踪用户和这些用户的不同权限。这些表就是在mysql数据库中的MyISAM表。将这些安全信息保存在MySQL中是非常有意义的。因此,我们可以使用标准的SQL来设置不同的权限。
一般在MySQL数据库中可以使用3种不同类型的安全检查:
·登录验证
也就是最常用的用户名和密码验证。一但你输入了正确的用户名和密码,这个验证就可通过。
·授权
在登录成功后,就要求对这个用户设置它的具体权限。如是否可以删除数据库中的表等。
·访问控制
这个安全类型更具体。它涉及到这个用户可以对数据表进行什么样的操作,如是否可以编辑数据库,是否可以查询数据等等。
访问控制由一些特权组成,这些特权涉及到所何使用和操作MySQL中的数据。它们都是布尔型,即要么允许,要么不允许。下面是这些特权的列表:
·Selct
Selct是设定用户是否可以使用Selct来查询数据。如果用户没有这个特权,那么就只能执行一些简单的Selct命令,如计算表达式(Selct +2),或是日期转换(Selct Unix_TIMESTAMP(NOW( )))等。
·Insrt
·Upate
·INDEX
INDEX决定用户是否可以对表的索引进行设置。如果用户没有这个权限,那么将无法设置表中的索引。
·Altr
·Crate
·GRANT
如果一个用户拥有这个GRANT权限,那么他就可以将自己的权限授给别的用户。也就是说,这个用户可以和其它用户共享自己的权限。
·REFERENCES
有了REFERENCES权限,用户就可以将其它表的一个字段作为某一个表的外键约束。
除了以上的权限外,MySQL还有一些权限可以对整个MySQL进行操作。
·Reload
这个权限可以使用户有权执行各种FLUSH命令,如FLUSH TABLES, FLUSH STATUS等。
·Shutdown
这个权限允许用户关闭MySQL
·Process
通过这个权限,用户可以执行SHOW PROCESSLIST和KILL命令。这些命令可以查看MySQL的处理进程,可以通过这种方式查看SQL执行的细节。
·File
这个权限决定用户是否可以执行LOAD DATA INFILE命令。给用户这个权限要慎重,因为有这个权限的用户可以将任意的文件装载到表中,这样对MySQL是十分危险的。
·Super
这个权限允许用户终止任何查询(这些查询可能并不是这个用户执行的)。
以上几种权限是非常危险的,在给用户授权限时要非常谨慎。
MySQL中的SSL
以上的账户安全只是以普通的Socket进行数据传输的,这样非常不安全。因此,MySQL在4.版以后提供了对SSL(Secure Scokets Layer)的支持。MySQL使用的是免费的OpenSSL库。
由于MySQL的Linux版本一般都是随Linux本身一起发布,因此,它们默认时都不使用SSL进行传输数据。如果要打开SSL功能,需要对hava_openssl变量进行设置:
MySQL的Windows版本已经将OpenSSL加入了。也面的命令是查看你的MySQL是否打开了SSL功能。
SHOW VARIABLES LIKE 'have_openssl'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | have_openssl | NO | +---------------+-------+ row in set (0.00 sec)
如果返回的是NO,那么说明你需要将OpenSSL编译进自己的MySQL。
在有时你可能需要将用户名和密码进行加密传输。在这时可以使用下面GRANT命令:
GRANT ALL PRIVILEGES ON ssl_only_db.* to 'abc'@'%' IDENTIFIED BY "password!" REQUIRE SSL;
还可以通过 REQUIRE x509 选项进行SSL传输:
GRANT ALL PRIVILEGES ON ssl_only_db.* to 'abc'@'%' IDENTIFIED BY "password!" REQUIRE x509;
你还可以使用REQUIRE SUBJECT来指定一个特定的客户端证书来访问数据库。
GRANT ALL PRIVILEGES ON ssl_only_db.* to 'abc'@'%'IDENTIFIED BY "password!"REQUIRE SUBJECT "/C=US/ST=New York/L=Albany/O=Widgets Inc./CN=client-ray.example.com/[email protected]";
也许你并不关心使用的是什么客户许可,而仅仅关心的是你的证书。那么你可以使用REQUIRE ISSUER来实现:
GRANT ALL PRIVILEGES ON ssl_only_db.* to 'abc'@'%' IDENTIFIED BY "password!"REQUIRE ISSUER "/C=US/ST=New+20York/L=Albany/O=Widgets Inc./CN=cacert.example.com/[email protected]";
SSL还可以直接通过密码进行加密。可以使用REQUIRE CIPHER设置密码。
GRANT ALL PRIVILEGES ON ssl_only_db.* 'abc'@'%' IDENTIFIED BY "password!"REQUIRE CIPHER "EDH-RSA-DES-CBC3-SHA";
上面使用了GRANT命令对用户权限进行设置。而这些信息都是保存在授权表中,这些表是安全系统的心脏。在这些表中保存了每一个用户和客户机所具有的权限。如果正确地操作这些表,将会对数据库的安全起到积极的作用,而如果使用不慎,将是非常危险的。
下面让我们来看看MySQL中的最要的5个授权表。
user
用户表保存了用户的权限和被加密的密码。这个表负责确定哪些用户和客户机可以连接到服务器上。
host
这个表为每一个客户机分配权限,它并不考虑用户的权限。MySQL在确定是否接收还是拒绝一个连接时,首先考虑的是user表。而使用GRANT或REVOKE命令并不影响host表,我们可以通过手工方式修改这个表中的内容。
db
db表保存了数据库层的权限信息。
tables_priv
这个表存储了表的权限信息。
columns_priv
这个表保存了单独列的权限信息。通过这个表,可以将操作某一列的权限授予一个用户。
哈希加密
如果数据库保存了敏感的数据,如银行卡密码,客户信息等,你可能想将这些数据以加密的形式保存在数据库中。这样即使有人进入了你的数据库,并看到了这些数据,也很难获得其中的真实信息。
在应用程序的大量信息中,也许你只想交很小的一部分进行加密,如用户的密码等。这些密码不应该以明文的形式保存,它们应该以加密的形式保存在数据库中。一般情况下,大多数系统,这其中包括MySQL本身都是使用哈希算法对敏感数据进行加密的。
哈希加密是单向加密,也就是说,被加密的字符串是无法得到原字符串的。这种方法使用很有限,一般只使用在密码验证或其它需要验证的地方。在比较时并不是将加密字符串进行解密,而是将输入的字符串也使用同样的方法进行加密,再和数据库中的加密字符串进行比较。这样即使知道了算法并得到了加密字符串,也无法还原最初的字符串。银行卡密码就是采用的这种方式进行加密。
MySQL提供了4个函数用于哈希加密:PASSWORD, ENCRYPT, SHA和MD5。下面让我们试一试这4个函数,看看会得到什么结果。我们以加密字符串"pa55word"为例进行说明:
让我们先来看看MD5函数
Selct MD5('pa55word'); +----------------------------------+ | MD5('pa55word') | +----------------------------------+ | a7a433755d6542fd005e8b43afd4 | +----------------------------------+ row in set (0.3 sec) 下面是PASSWORD函数 Selct PASSWORD('pa55word'); +----------------------+ | PASSWORD('pa55word') | +----------------------+ | d35c6556b8cab45 | +----------------------+ row in set (0.00 sec) 下面是ENCRYPT函数 Selct ENCRYPT('pa55word'); +---------------------+ | ENCRYPT('pa55word') | +---------------------+ | up2Ecb0Hdj25A | +---------------------+ row in set (0.7 sec)
上面的每个函数都返回了一个加密后的字符串。为了区分加密字符串的大小写,最好在使用ENCRYPT生成加密字符串时,将这个字段定义成CHAR BINARY类型。
上面列举了3种加密的方法,但我认为使用MD5加密是最好的。这是因为这样做可以将明文密码显示在处理列表中或是查询日志中,这样便于跟踪。如下面的Insrt语句使用插入了一条记录,其中的密码使用了MD5进行加密:
Insrt INTO table (user, pw) VALUE ('user', MD5('password') )
可以通过如下的语句进行密码验证:
Selct * FROM table Whre user = 'user' AND pw = MD5('password')
哈希加密方法可以很好地对密码进行加密,使用了这种方法加密,密码将无法恢复成明文。
Jul
30
MySQL易学易用,且附带丰富的技术文档,这二个因素使之被广泛应用。然而,随着MySQL发展之迅速,即使一个MySQL老手有时也会为该软件出其不意的功能感叹。本文将为你介绍这些不为人知的特性。
以XML格式查看查询结果
通过使用传统—xml 选项调用MySQL命令行客户程序,你可以以XML格式(而不是传统的列表形式)来查看MySQL查询结果。如果你打算将查询输出与其它程序集成在一起,这一技巧非常有用,这里是一个例子:
表A
shell> mysql --xml
mysql> Selct * FROM test.stories;
This is a test
2005-07-28 00:4:57
2
This is the second test
2005-07-28 00:5:
2 rows in set (0. sec)
快速重建索引
通常情况下,如果你想改变服务器的全文搜索变量,你需要在表格中重新建立全文索引,以确保你的更新得到映射。这一操作将会花费大量的时间,特别是如果你需要处理很多数据的时候。一种快速的解决方法是使用REPAIR TABLE命令,以下为演示过程:
表B
mysql> REPAIR TABLE content QUICK;
+-----------+--------+----------+----------+
| Table| Op| Msg_type | Msg_text |
+-----------+--------+----------+----------+
| content| repair | status| OK|
+-----------+--------+----------+----------+
row in set (0.05 sec)
压缩一定的表格类型
如果你处理的是只读MyISAM表格,MySQL允许你将其压缩以节省磁盘空间。对此可以使用包括myisampack,如下所示:
表C
shell> myisampackmovies.MYI
Compressing movies.MYD: (46 records)
- Calculating statistics
- Compressing file
4.05%
使用传统SQL
MySQL支持SQL查询中的传统用法,支持IF与CASE结构。以下是一个简单的例子:
表D
mysql> Selct IF (priv=, 'admin', 'guest') As usertype FROM privs Whre username = 'joe';
+----------+
| usertype |
+----------+
| admin|
+----------+
row in set (0.00 sec)
以CSV格式输出表格数据
MySQL输出文件包含一个全部SQL命令列表。如果你想将输出文件导入到MySQL,这一功能非常实用,但如果目标程序(比如Excel)不能与SQL相互通讯,这一方法将行不通。在这种情况下,可以通过告诉MySQL以CSV格式建立输出文件,这种CSV格式很方便地导入到绝大部分的程序。这里演示了mysqldump的操作过程:
shell> mysqldump -T . --fields-terminated-by=", " mydbmytable
这将在当前目录中生成一个文本文件,包含来自mydb.mytable列表中以逗号为间隔符的记录。
以激活strict模式减少“bad”数据的出现
MySQL服务器能够以多种不同的模式运行,而每一种都针对于特定的目的而优化。在默认情况下,没有设置模式。然而,通过在服务器命令行中添加以下选项可以很容易地改变模式的设置并将MySQL以“strict”模式运行:
shell> mysqld --sql_mode="STRICT_ALL_TABLES" &
在“strict”模式下,通过MySQL的中止查询执行并返回一个错误,服务器的很多自动修正功能都被无效化。同样,该模式下也将会执行更为严格的时间检查。
监视服务器
你可以通过运行SHOW STATUS命令获得一份服务器运行与统计的报告,包括打开连接的次数,激活查询次数,服务器正常运行时间等等。例如:
表 E
mysql> SHOW STATUS;
+------------------+-------+
| Variable_name| Value |
+------------------+-------+
| Aborted_clients| 0|
| Aborted_connects | 0|
...
| Uptime| 85|
+------------------+-------+
56 rows in set (0.6 sec)
自动返回Crate TABLE代码
MySQL允许你自动获得SQL命令重新建立一个特定的表格。只简单地运行SHOW Crate TABLE命令,并查看表格建立代码,如下所示:
表 F
mysql> SHOW Crate TABLE products;
-----------------------------------------------------
| Table| Crate Table
+----------+-----------------------------------------
| products | Crate TABLE `products` (
`id` int(8) NOT NULL auto_increment,
`name` varchar(255) NOT NULL default '',
`price` int(0) default NULL,
PRIMARY KEY(`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin |
+----------+-----------------------------------------
row in set (0.27 sec)
建立一个更为有用的命令提示:
在缺省情况下,MySQL命令行客户程序显示一个简单的mysql>提示符。然而,你可以使用特定的修改内容来改变这一提示符使之变得更为有效,这些内容包括:当前用户名称,主机名称,以及当前选择的数据库。如下所示:
表 G
mysql> prompt \U:/\d>
PROMPT set to '\U:/\d>'
root@localhost:/db>
从这里的文档文件你可以获得支持MySQL客户程序更改的一个完整列表。
以XML格式查看查询结果
通过使用传统—xml 选项调用MySQL命令行客户程序,你可以以XML格式(而不是传统的列表形式)来查看MySQL查询结果。如果你打算将查询输出与其它程序集成在一起,这一技巧非常有用,这里是一个例子:
表A
shell> mysql --xml
mysql> Selct * FROM test.stories;
This is a test
2005-07-28 00:4:57
2
This is the second test
2005-07-28 00:5:
2 rows in set (0. sec)
快速重建索引
通常情况下,如果你想改变服务器的全文搜索变量,你需要在表格中重新建立全文索引,以确保你的更新得到映射。这一操作将会花费大量的时间,特别是如果你需要处理很多数据的时候。一种快速的解决方法是使用REPAIR TABLE命令,以下为演示过程:
表B
mysql> REPAIR TABLE content QUICK;
+-----------+--------+----------+----------+
| Table| Op| Msg_type | Msg_text |
+-----------+--------+----------+----------+
| content| repair | status| OK|
+-----------+--------+----------+----------+
row in set (0.05 sec)
压缩一定的表格类型
如果你处理的是只读MyISAM表格,MySQL允许你将其压缩以节省磁盘空间。对此可以使用包括myisampack,如下所示:
表C
shell> myisampackmovies.MYI
Compressing movies.MYD: (46 records)
- Calculating statistics
- Compressing file
4.05%
使用传统SQL
MySQL支持SQL查询中的传统用法,支持IF与CASE结构。以下是一个简单的例子:
表D
mysql> Selct IF (priv=, 'admin', 'guest') As usertype FROM privs Whre username = 'joe';
+----------+
| usertype |
+----------+
| admin|
+----------+
row in set (0.00 sec)
以CSV格式输出表格数据
MySQL输出文件包含一个全部SQL命令列表。如果你想将输出文件导入到MySQL,这一功能非常实用,但如果目标程序(比如Excel)不能与SQL相互通讯,这一方法将行不通。在这种情况下,可以通过告诉MySQL以CSV格式建立输出文件,这种CSV格式很方便地导入到绝大部分的程序。这里演示了mysqldump的操作过程:
shell> mysqldump -T . --fields-terminated-by=", " mydbmytable
这将在当前目录中生成一个文本文件,包含来自mydb.mytable列表中以逗号为间隔符的记录。
以激活strict模式减少“bad”数据的出现
MySQL服务器能够以多种不同的模式运行,而每一种都针对于特定的目的而优化。在默认情况下,没有设置模式。然而,通过在服务器命令行中添加以下选项可以很容易地改变模式的设置并将MySQL以“strict”模式运行:
shell> mysqld --sql_mode="STRICT_ALL_TABLES" &
在“strict”模式下,通过MySQL的中止查询执行并返回一个错误,服务器的很多自动修正功能都被无效化。同样,该模式下也将会执行更为严格的时间检查。
监视服务器
你可以通过运行SHOW STATUS命令获得一份服务器运行与统计的报告,包括打开连接的次数,激活查询次数,服务器正常运行时间等等。例如:
表 E
mysql> SHOW STATUS;
+------------------+-------+
| Variable_name| Value |
+------------------+-------+
| Aborted_clients| 0|
| Aborted_connects | 0|
...
| Uptime| 85|
+------------------+-------+
56 rows in set (0.6 sec)
自动返回Crate TABLE代码
MySQL允许你自动获得SQL命令重新建立一个特定的表格。只简单地运行SHOW Crate TABLE命令,并查看表格建立代码,如下所示:
表 F
mysql> SHOW Crate TABLE products;
-----------------------------------------------------
| Table| Crate Table
+----------+-----------------------------------------
| products | Crate TABLE `products` (
`id` int(8) NOT NULL auto_increment,
`name` varchar(255) NOT NULL default '',
`price` int(0) default NULL,
PRIMARY KEY(`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin |
+----------+-----------------------------------------
row in set (0.27 sec)
建立一个更为有用的命令提示:
在缺省情况下,MySQL命令行客户程序显示一个简单的mysql>提示符。然而,你可以使用特定的修改内容来改变这一提示符使之变得更为有效,这些内容包括:当前用户名称,主机名称,以及当前选择的数据库。如下所示:
表 G
mysql> prompt \U:/\d>
PROMPT set to '\U:/\d>'
root@localhost:/db>
从这里的文档文件你可以获得支持MySQL客户程序更改的一个完整列表。
Jul
30
1、mysql 数据库没有增量备份的机制,当数据量太大的时候备份是一个很大的问题。还好 mysql 数据库提供了一种主从备份的机制,其实就是把主数据库的所有的数据同时写到备份数据库中。实现 mysql 数据库的热备份。
2、要想实现双机的热备首先要了解主从数据库服务器的版本的需求。要实现热备 mysql 的版本都要高于3.2,还有一个基本的原则就是作为从数据库的数据库版本可以高于主服务器数据库的版本,但是不可以低于主服务器的数据库版本。
3、设置主数据库服务器:
a. 首先查看主服务器的版本是否是支持热备的版本。然后查看 my.cnf(类 unix)或者 my.ini(windows)中 mysqld 配置块的配置有没有 log-bin (记录数据库更改日志),因为 mysql 的复制机制是基于日志的复制机制,所以主服务器一定要支持更改日志才行。然后设置要写入日志的数据库或者不要写入日志的数据库。这样只有您感兴趣的数据库的更改才写入到数据库的日志中。
server-id= //数据库的 id 这个应该默认是就不用改动
log-bin=log_name //日志文件的名称,这里可以制定日志到别的目录 如果没有设置则默认主机名的一个日志名称
binlog-do-db=db_name //记录日志的数据库
binlog-ignore-db=db_name //不记录日志的数据库
以上的如果有多个数据库用","分割开,然后设置同步数据库的用户帐号
mysql> GRANT REPLICATION SLAVE ON *.*
-> TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
4.0.2 以前的版本, 因为不支持 REPLICATION 要使用下面的语句来实现这个功能
mysql> GRANT FILE ON *.*
-> TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
设置好主服务器的配置文件后重新启动数据库
b.锁定现有的数据库并备份现在的数据
锁定数据库
mysql> FLUSH TABLES WITH READ LOCK;
备份数据库有两种办法一种是直接进入到 mysql 的 data 目录然后打包你需要备份数据库的文件夹,第二种是使用 mysqldump 的方式来备份数据库但是要加上"--master-data " 这个参数,建议使用第一种方法来备份数据库
c.查看主服务器的状态
mysql> show master status\G;
+---------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73 | test | manual,mysql |
+---------------+----------+--------------+------------------+
记录 File 和 Position 项目的值,以后要用的。
d.然后把数据库的锁定打开
mysql> UNLOCK TABLES;
4、设置从服务器
a.首先设置数据库的配置文件
server-id=n //设置数据库 id 默认主服务器是可以随便设置但是如果有多台从服务器则不能重复。
master-host=db-master.mycompany.com //主服务器的IP地址或者域名
master-port=3306 //主数据库的端口号
master-user=pertinax //同步数据库的用户
master-password=freitag //同步数据库的密码
master-connect-retry=60 //如果从服务器发现主服务器断掉,重新连接的时间差
report-host=db-slave.mycompany.com //报告错误的服务器
b.把从主数据库服务器备份出来的数据库导入到从服务器中
c.然后启动从数据库服务器,如果启动的时候没有加上 "--skip-slave-start" 这个参数则进入到 mysql 中
mysql> slave stop; //停止 slave 的服务
d.设置主服务器的各种参数
mysql> CHANGE MASTER TO
-> MASTER_HOST='master_host_name', //主服务器的IP地址
-> MASTER_USER='replication_user_name', //同步数据库的用户
-> MASTER_PASSWORD='replication_password', //同步数据库的密码
-> MASTER_LOG_FILE='recorded_log_file_name', //主服务器二进制日志的文件名,前面要求记住的参
-> MASTER_LOG_POS=recorded_log_position; //日志文件的开始位置(前面要求记住的参数)
e.启动同步数据库的线程
mysql> slave start;
查看数据库的同步情况吧。如果能够成功同步那就恭喜了!
查看主从服务器的状态
mysql> SHOW PROCESSLIST\G //可以查看 mysql 的进程看看是否有监听的进程
如果日志太大清除日志的步骤如下
.锁定主数据库
mysql> FLUSH TABLES WITH READ LOCK;
2.停掉从数据库的 slave
mysql> slave stop;
3.查看主数据库的日志文件名和日志文件的 position
show master status;
+---------------+----------+--------------+------------------+
| File | Position | Binlog_do_db | Binlog_ignore_db |
+---------------+----------+--------------+------------------+
| louis-bin.00 | 79 | | mysql |
+---------------+----------+--------------+------------------+
4.解开主数据库的锁
mysql> unlock tables;
5.更新从数据库中主数据库的信息
mysql> CHANGE MASTER TO
-> MASTER_HOST='master_host_name', //主服务器的IP地址
-> MASTER_USER='replication_user_name', //同步数据库的用户
-> MASTER_PASSWORD='replication_password', //同步数据库的密码
-> MASTER_LOG_FILE='recorded_log_file_name', //主服务器二进制日志的文件名,前面要求记住的参数
-> MASTER_LOG_POS=recorded_log_position; //日志文件的开始位置(前面要求记住的参数)
6.启动从数据库的 slave
mysql> slave start;
2、要想实现双机的热备首先要了解主从数据库服务器的版本的需求。要实现热备 mysql 的版本都要高于3.2,还有一个基本的原则就是作为从数据库的数据库版本可以高于主服务器数据库的版本,但是不可以低于主服务器的数据库版本。
3、设置主数据库服务器:
a. 首先查看主服务器的版本是否是支持热备的版本。然后查看 my.cnf(类 unix)或者 my.ini(windows)中 mysqld 配置块的配置有没有 log-bin (记录数据库更改日志),因为 mysql 的复制机制是基于日志的复制机制,所以主服务器一定要支持更改日志才行。然后设置要写入日志的数据库或者不要写入日志的数据库。这样只有您感兴趣的数据库的更改才写入到数据库的日志中。
server-id= //数据库的 id 这个应该默认是就不用改动
log-bin=log_name //日志文件的名称,这里可以制定日志到别的目录 如果没有设置则默认主机名的一个日志名称
binlog-do-db=db_name //记录日志的数据库
binlog-ignore-db=db_name //不记录日志的数据库
以上的如果有多个数据库用","分割开,然后设置同步数据库的用户帐号
mysql> GRANT REPLICATION SLAVE ON *.*
-> TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
4.0.2 以前的版本, 因为不支持 REPLICATION 要使用下面的语句来实现这个功能
mysql> GRANT FILE ON *.*
-> TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
设置好主服务器的配置文件后重新启动数据库
b.锁定现有的数据库并备份现在的数据
锁定数据库
mysql> FLUSH TABLES WITH READ LOCK;
备份数据库有两种办法一种是直接进入到 mysql 的 data 目录然后打包你需要备份数据库的文件夹,第二种是使用 mysqldump 的方式来备份数据库但是要加上"--master-data " 这个参数,建议使用第一种方法来备份数据库
c.查看主服务器的状态
mysql> show master status\G;
+---------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73 | test | manual,mysql |
+---------------+----------+--------------+------------------+
记录 File 和 Position 项目的值,以后要用的。
d.然后把数据库的锁定打开
mysql> UNLOCK TABLES;
4、设置从服务器
a.首先设置数据库的配置文件
server-id=n //设置数据库 id 默认主服务器是可以随便设置但是如果有多台从服务器则不能重复。
master-host=db-master.mycompany.com //主服务器的IP地址或者域名
master-port=3306 //主数据库的端口号
master-user=pertinax //同步数据库的用户
master-password=freitag //同步数据库的密码
master-connect-retry=60 //如果从服务器发现主服务器断掉,重新连接的时间差
report-host=db-slave.mycompany.com //报告错误的服务器
b.把从主数据库服务器备份出来的数据库导入到从服务器中
c.然后启动从数据库服务器,如果启动的时候没有加上 "--skip-slave-start" 这个参数则进入到 mysql 中
mysql> slave stop; //停止 slave 的服务
d.设置主服务器的各种参数
mysql> CHANGE MASTER TO
-> MASTER_HOST='master_host_name', //主服务器的IP地址
-> MASTER_USER='replication_user_name', //同步数据库的用户
-> MASTER_PASSWORD='replication_password', //同步数据库的密码
-> MASTER_LOG_FILE='recorded_log_file_name', //主服务器二进制日志的文件名,前面要求记住的参
-> MASTER_LOG_POS=recorded_log_position; //日志文件的开始位置(前面要求记住的参数)
e.启动同步数据库的线程
mysql> slave start;
查看数据库的同步情况吧。如果能够成功同步那就恭喜了!
查看主从服务器的状态
mysql> SHOW PROCESSLIST\G //可以查看 mysql 的进程看看是否有监听的进程
如果日志太大清除日志的步骤如下
.锁定主数据库
mysql> FLUSH TABLES WITH READ LOCK;
2.停掉从数据库的 slave
mysql> slave stop;
3.查看主数据库的日志文件名和日志文件的 position
show master status;
+---------------+----------+--------------+------------------+
| File | Position | Binlog_do_db | Binlog_ignore_db |
+---------------+----------+--------------+------------------+
| louis-bin.00 | 79 | | mysql |
+---------------+----------+--------------+------------------+
4.解开主数据库的锁
mysql> unlock tables;
5.更新从数据库中主数据库的信息
mysql> CHANGE MASTER TO
-> MASTER_HOST='master_host_name', //主服务器的IP地址
-> MASTER_USER='replication_user_name', //同步数据库的用户
-> MASTER_PASSWORD='replication_password', //同步数据库的密码
-> MASTER_LOG_FILE='recorded_log_file_name', //主服务器二进制日志的文件名,前面要求记住的参数
-> MASTER_LOG_POS=recorded_log_position; //日志文件的开始位置(前面要求记住的参数)
6.启动从数据库的 slave
mysql> slave start;










