首页 行业资讯 宠物日常 宠物养护 宠物健康 宠物故事
您的当前位置:首页正文

Mysql异常Packet for query is too large (14040 > 1024)

2023-11-10 来源:画鸵萌宠网

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 上面是改变之后的值,但是网上多数是说修改my.cnf的时候,这个值直接加到mysqld下面,设置为20M以上的值即可,但是之前使用的配置中已经很高了,通过观察发现query_cache_limit值为1M试着改动该值之后发现max_allowed_packet这个值也有所改动.

    max_allowed_packet参数 这个参数为接收的数据包的大小,该值取较小的值可以捕获数据包的异常,以及防止由于数据包过大而导致内存溢出。

    query_cache_limit参数 该参数指定了单次查询缓存大小,不宜过大,如果数据比较多的情况下应该适当的加大该参数值,但是一般小数据量的查询不需要设置太大否则造成内存碎片。

    Mysql异常Packet for query is too large (14040 > 1024)

    标签:ber   通过   参数   比较   print   replace   markdown   导致   show   

    小编还为您整理了以下内容,可能对您也有帮助:

    如何解决 MySQL max

    MySQL是目前使用很广泛的数据库,在使用过程中,有时我们会遇到一个与 "max_allowed_packet" 相关的报错,那如何解决这个问题呢? 看如下经验。

    方法/步骤

    先看看与这个错误相关的后台异常 :

    Packet for query is too large (1706 > 1024). You can change this value on the server by setting the max_allowed_packet' variable.

    一旦数据库出现这个问题,基本执行任何查询语句,后台都会报这个错!(除非查询所得数据量特别少)!

    先登录数据库,查看 max_allowed_packet 这个参数值

    连接数据库服务器,登录 mysql, 执行命令 :

    show variables like '%max_allowed_packate%'

    即可查看这个系统参数目前的值 ! 我的系统,目前显示只有 1024 字节,确实太小了!

    通过 mysql 命令更改这个值到 100M !

    连接数据库服务器,登录 mysql, 执行命令 :

    set global max_allowed_packet = 100*1024*1024

    退出后,重新登录 mysql ,再次查看这个系统项的值, 注意,必须重新登录mysql,否则这个值还是显示为原始值(缓存)!

    修改后,这个配置项显示为 100 M !

    修改配置文件--Windows

    我们刚才的修改是针对运行环境,但如果我们的配置文件不变,则重启数据库后,这个值又恢复为原始值了,对于 Windows 下的 MySQL,我们需要修改其配置文件 my.ini , 这个文件在 MySQL 的安装根目录下。

    注意: MySQL 配置文件分为几个段 (Section), 包括 [mysql], [mysqld], [mysqlmp] 等, 我们需要在 [mysqld] 段下添加配置项 :

    max_allowed_packet= 100M

    修改配置文件--Linux

    在 Linux 中,MySQL 对应的配置文件是 my.cnf , 我们在Linux终端输入如下命令 :

    mysql --help | grep my.cnf

    可以查看 MySQL 所使用的 my.cnf 列表(优先级列表,先找到的配置文件生效),MySQL 会逐个目录寻找这个文件,直到找到为止!

    我们逐个目录找到我们系统 MySQL 所使用的 my.cnf 配置文件,找到对应的配置项,修改为 100M 即可。

    linux系统下怎么解决packet for query is too large you c

    其实,这一种说法是不完全正确的。首先第一点,mysql的query_cache的键值并不是简单的query,而是query加databasename加flag。这个从源码中就可以看出。在这里不做重点描述,后续可以针对于这一点再具体分析。重要的是第二点,是不是加了空格,mysql就认为是不同的查询呢?实际上这个是要分情况而言的,要看这个空格加在哪。 如果空格是加在query之前,比如是在query的起始处加了空格,这样是丝毫不影响query cache的结果的,mysql认为这是一条query, 而如果空格是在query中,那会影响query cache的结果,mysql会认为是不同的query。 下面我们通过实验及源码具体分析。首先,我们先试验一下: 首先,我们看一下mysql query_cache的状态: 首先,我们可以确认,mysql的query_cache功能是打开的。 其次,我们看一下状态: 因为这个db是新的db,所以hits,inset都为0,现在我们执行一条select语句: 状态变为: 可以看到,执行一条select后,现在的qcache状态为,insert+1,这样我们就可以推断出,现在刚才那条select语句已经加入了qcache中。那我们现在再将刚才那条sql前面加上空格,看看会怎样呢? 请注意,这条sql,比刚才那条sql前面多了一个空格。 按照网上的理论,这条sql应该会作为另一个键而插入另一个cache,不会复用先前的cache,但结果呢? 我们可以看到,hits变为了1,而inserts根本没变,这就说明了,这条在前面加了空格的query命中了没有空格的query的结果集。从这,我们就可以得出结论,网上先前流传的说法,是不严谨的。 那究竟是怎么回事呢?到底应该如何呢?为什么前面有空格的会命中了没有空格的query的结果集。其实,这些我们可以通过源码获得答案。 翻看下mysql的源码,我这翻看的是5_buffer_length); thd->convert_buffer_buffer_length); return FALSE; } 这个方法在一开始就会对query进行处理(代码第4行),将开头和末尾的garbage remove掉。 看到这里,我们基本已经明了了,mysql会对输入的query进行预处理,将空格等东西给处理掉,所以不会开头的空格不会影响到query_cache,因为对mysql来说,就是一条query。

    com.mysql.jdbc.PacketTooBigException: Packet for query is too larg...

    jdbc和连接池对于你这个场景来说,都足够,既然用spring管理了,建议还是使用连接池,另外,spring自身没有实现连接池,一般都是对第三方连接池的包装,常见的有C3P0,dbcp以及最近比较流行的boneCP等,这几个配置都差不多太多,以boneCP为例:
    <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource"
    destroy-method="close">
    <property name="driverClass" value="${jdbc.driverClass}" />
    <property name="jdbcUrl" value="${jdbc.url}" />
    <property name="username" value="${jdbc.user}" />
    <property name="password" value="${jdbc.password}" />
    <property name="idleConnectionTestPeriod" value="60" />
    <property name="idleMaxAge" value="240" />
    <property name="maxConnectionsPerPartition" value="30" />
    <property name="minConnectionsPerPartition" value="10" />
    <property name="partitionCount" value="2" />
    <property name="acquireIncrement" value="5" />
    <property name="statementsCacheSize" value="100" />
    <property name="releaseHelperThreads" value="3" />
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource" />
    </bean>

    com.mysql.jdbc.PacketTooBigException: Packet for query is too larg...

    jdbc和连接池对于你这个场景来说,都足够,既然用spring管理了,建议还是使用连接池,另外,spring自身没有实现连接池,一般都是对第三方连接池的包装,常见的有C3P0,dbcp以及最近比较流行的boneCP等,这几个配置都差不多太多,以boneCP为例:
    <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource"
    destroy-method="close">
    <property name="driverClass" value="${jdbc.driverClass}" />
    <property name="jdbcUrl" value="${jdbc.url}" />
    <property name="username" value="${jdbc.user}" />
    <property name="password" value="${jdbc.password}" />
    <property name="idleConnectionTestPeriod" value="60" />
    <property name="idleMaxAge" value="240" />
    <property name="maxConnectionsPerPartition" value="30" />
    <property name="minConnectionsPerPartition" value="10" />
    <property name="partitionCount" value="2" />
    <property name="acquireIncrement" value="5" />
    <property name="statementsCacheSize" value="100" />
    <property name="releaseHelperThreads" value="3" />
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource" />
    </bean>

    mysql一直提示query ok 0 row affected

    1、项目刚开始运行时是正常的,可以正常访问,可是运行了一段时间就报错。

    2、查询下设置最大值SHOW VARIABLES LIKE '%max_allowed_packet%';。

    3、找到mysql的安装目录。

    4、打开my.ini,文件。

    5、查找max_allowed_packet,有的文件没有,没有的话增加[mysqld]。max_allowed_packet = 20M。

    6、然后重启,mysql,运行程序,可以正常添加数据,问题就解决了。

    数据库mysql创建表格老是出错,看不懂英文提示?

    来自:51CTO(作者:superZS)
    我在刚开始学习数据库的时候,没少走弯路。经常会遇到各种稀奇古怪的 error 信息,遇到报错会很慌张,急需一个解决问题的办法。跟无头苍蝇一样,会不加思索地把错误粘到百度上,希望赶紧查找一下有没有好的处理问题的方法。我想这个应该是刚从事数据库的小白,都会遇到窘境。
    今天就给大家列举 MySQL 数据库中,最经典的十大错误案例,并附有处理问题的解决思路和方法,希望能给刚入行,或数据库爱好者一些帮助,今后再遇到任何报错,我们都可以很淡定地去处理。
    学习任何一门技术的同时,其实就是自我*的过程。沉下心,尝试去拥抱数据的世界!
    Top 1:
    Too many connections(连接数过多,导致连接不上数据库,业务无法正常进行)
    问题还原
    解决问题的思路:
    1、首先先要考虑在我们 MySQL 数据库参数文件里面,对应的 max_connections 这个参数值是不是设置的太小了,导致客户端连接数超过了数据库所承受的最大值。
    ● 该值默认大小是151,我们可以根据实际情况进行调整。
    ● 对应解决办法:set global max_connections=500
    但这样调整会有隐患,因为我们无法确认数据库是否可以承担这么大的连接压力,就好比原来一个人只能吃一个馒头,但现在却非要让他吃 10 个,他肯定接受不了。反应到服务器上面,就有可能会出现宕机的可能。
    所以这又反应出了,我们在新上线一个业务系统的时候,要做好压力测试。保证后期对数据库进行优化调整。
    2、其次可以* Innodb 的并发处理数量,如果 innodb_thread_concurrency = 0(这种代表不受*) 可以先改成 16或是64 看服务器压力。如果非常大,可以先改的小一点让服务器的压力下来之后,然后再慢慢增大,根据自己的业务而定。个人建议可以先调整为 16 即可。
    MySQL 随着连接数的增加性能是会下降的,可以让开发配合设置 thread pool,连接复用。在MySQL商业版中加入了thread pool这项功能
    另外对于有的监控程序会读取 information_schema 下面的表,可以考虑关闭下面的参数
    innodb_stats_on_metadata=0
    set global innodb_stats_on_metadata=0
    Top 2:(主从复制报错类型)
    Last_SQL_Errno: 1062 (从库与主库数据冲突)
    Last_Errno: 1062
    Last_Error: Could not execute Write_rows event on table test.t;
    Duplicate entry '4' for key 'PRIMARY',
    Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY;
    the event's master log mysql-bin.000014, end_log_pos 1505

    针对这个报错,我们首先要考虑是不是在从库中误操作导致的。结果发现,我们在从库中进行了一条针对有主键表的 sql 语句的插入,导致主库再插入相同 sql 的时候,主从状态出现异常。发生主键冲突的报错。
    解决方法:
    在确保主从数据一致性的前提下,可以在从库进行错误跳过。一般使用 percona-toolkit 中的 pt-slave-restart 进行。
    在从库完成如下操作
    [root@zs bin]# ./pt-slave-restart -uroot -proot123
    2017-07-20T14:05:30 p=...,u=root node4-relay-bin.000002 1506 1062

    之后最好在从库中开启 read_only 参数,禁止在从库进行写入操作
    Last_IO_Errno: 1593(server-id冲突)
    Last_IO_Error:
    Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids;
    these ids must be different for replication to work
    (or the --replicate-same-server-id option must be used on slave but this
    does not always make sense; please check the manual before using it)

    这个报错出现之后,就看一目了然看到两台机器的 server-id 是一样的。
    在搭建主从复制的过程中,我们要确保两台机器的 server-id 是唯一的。这里再强调一下 server-id 的命名规则(服务器 ip 地址的最后一位+本 MySQL 服务的端口号)
    解决方法:
    在主从两台机器上设置不同的 server-id。
    Last_SQL_Errno: 1032(从库少数据,主库更新的时候,从库报错)
    Last_SQL_Error:
    Could not execute Update_rows event on table test.t; Can't find record
    in 't', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the
    event's master log mysql-bin.000014, end_log_pos 1708

    解决问题的办法:
    根据报错信息,我们可以获取到报错日志和position号,然后就能找到主库执行的哪条sql,导致的主从报错。
    在主库执行:
    /usr/local/mysql/bin/mysqlbinlog --no-defaults -v -v --base64-output=decode-rows /data/mysql/mysql-bin.000014 |grep -A 10 1708 > 1.log
    cat 1.log
    #170720 14:20:15 server id 3 end_log_pos 1708 CRC32 0x97b6bdec Update_rows: table id 113 flags: STMT_END_F
    ### UPDATE `test`.`t`
    ### WHERE
    ### @1=4 /* INT meta=0 nullable=0 is_null=0 */
    ### @2='dd' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
    ### SET
    ### @1=4 /* INT meta=0 nullable=0 is_null=0 */
    ### @2='ddd' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
    # at 1708
    #170720 14:20:15 server id 3 end_log_pos 1739 CRC32 0xecaf1922 Xid = 654
    COMMIT/*!*/;
    DELIMITER ;
    # End of log file
    ROLLBACK /* added by mysqlbinlog */;
    /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
    /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

    获取到 sql 语句之后,就可以在从库反向执行 sql 语句。把从库缺少的 sql 语句补全,解决报错信息。
    在从库依次执行:
    mysql> insert into t (b) values ('ddd');
    Query OK, 1 row affected (0.01 sec)
    mysql> stop slave;
    Query OK, 0 rows affected (0.00 sec)
    mysql> exit
    Bye
    [root@node4 bin]# ./pt-slave-restart -uroot -proot123
    2017-07-20T14:31:37 p=...,u=root node4-relay-bin.000005 283 1032

    Top 3:MySQL安装过程中的报错
    [root@zs data]# /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf &[1] 3758
    [root@zs data]# 170720 14:41:24 mysqld_safe Logging to '/data/mysql/error.log'.
    170720 14:41:24 mysqld_safe Starting mysqld daemon with databases from /data/mysql170720
    14:41:25 mysqld_safe mysqld from pid file /data/mysql/node4.pid ended
    170720 14:41:24 mysqld_safe Starting mysqld daemon with databases from /data/mysql2017-07-20
    14:41:25 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated.
    Please use --explicit_defaults_for_timestamp server option
    (see documentation for more details)./usr/local/mysql/bin/mysqld:
    File '/data/mysql/mysql-bin.index' not found (Errcode: 13 - Permission denied)
    2017-07-20 14:41:25 4388 [ERROR] Aborting

    解决思路:
    遇到这样的报错信息,我们要学会时时去关注错误日志 error log 里面的内容。看见了关键的报错点 Permission denied。证明当前 MySQL 数据库的数据目录没有权限。
    解决方法:
    [root@zs data]# chown mysql:mysql -R mysql
    [root@zs data]# /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf &
    [1] 4402
    [root@zs data]# 170720 14:45:56 mysqld_safe Logging to '/data/mysql/error.log'.
    170720 14:45:56 mysqld_safe Starting mysqld daemon with databases from /data/mysql

    启动成功。
    如何避免这类问题,个人建议在安装 MySQL 初始化的时候,一定加上--user=mysql,这样就可以避免权限问题。
    ./mysql_install_db --basedir=/usr/local/mysql/ --datadir=/data/mysql/ --defaults-file=/etc/my.cnf --user=mysql
    Top 4:数据库密码忘记的问题
    [root@zs ~]# mysql -uroot -p
    Enter password:
    ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
    [root@zs ~]# mysql -uroot -p
    Enter password:
    ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

    我们有可能刚刚接手别人的 MySQL 数据库,而且没有完善的交接文档。root 密码可以丢失或者忘记了。
    解决思路:
    目前是进入不了数据库的情况,所以我们要考虑是不是可以跳过权限。因为在数据库中,mysql数据库中user表记录着我们用户的信息。
    解决方法:
    启动 MySQL 数据库的过程中,可以这样执行:
    /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf --skip-grant-tables &

    这样启动,就可以不用输入密码,直接进入 mysql 数据库了。然后在修改你自己想要改的root密码即可。
    update mysql.user set password=password('root123') where user='root';

    Top 5:truncate 删除数据,导致自动清空自增ID,前端返回报错 not found。
    这个问题的出现,就要考虑下 truncate 和 delete 的区别了。
    看下实验演练:
    首先先创建一张表;
    CREATE TABLE `t` (
    `a` int(11) NOT NULL AUTO_INCREMENT,
    `b` varchar(20) DEFAULT NULL,
    PRIMARY KEY (`a`),
    KEY `b` (`b`)
    ) ENGINE=InnoDB AUTO_INCREMENT=300 DEFAULT CHARSET=utf8

    插入三条数据:
    mysql> insert into t (b) values ('aa');
    Query OK, 1 row affected (0.00 sec)
    mysql> insert into t (b) values ('bb');
    Query OK, 1 row affected (0.00 sec)
    mysql> insert into t (b) values ('cc');
    Query OK, 1 row affected (0.00 sec)
    mysql> select * from t;
    +-----+------+
    | a | b |
    +-----+------+
    | 300 | aa |
    | 301 | bb |
    | 302 | cc |
    +-----+------+
    3 rows in set (0.00 sec)

    先用 delete 进行删除全表信息,再插入新值。
    结果发现 truncate 把自增初始值重置了,自增属性从1开始记录了。当前端用主键id进行查询时,就会报没有这条数据的错误。
    个人建议不要使用 truncate 对表进行删除操作,虽然可以回收表空间,但是会涉及自增属性问题。这些坑,我们不要轻易钻进去。
    Top 6:
    阿里云 MySQL 的配置文件中,需要注意一个参数设置就是:
    lower_case_table_names = 0;默认情况
    lower_case_table_names = 1;是不区分大小写 . 如果报你小写的表名找不到, 那你就把远端数据库的表名改成小写 , 反之亦然 . 注意 Mybatis 的 Mapper 文件的所有表名也要相应修改
    Top 7:
    有同学经常会问张老师,为什么我的数据库总会出现中文乱码的情况。一堆????不知道怎么回事。当向数据库中写入创建表,并插入中文时,会出现这种问题。此报错会涉及数据库字符集的问题。
    解决思路:
    对于中文乱码的情况,记住老师告诉你的三个统一就可以。还要知道在目前的mysql数据库中字符集编码都是默认的UTF8
    处理办法:
    1、数据终端,也就是我们连接数据库的工具设置为 utf8
    2、操作系统层面;可以通过 cat /etc/sysconfig/i18n 查看;也要设置为 utf8
    3、数据库层面;在参数文件中的 mysqld 下,加入 character-set-server=utf8。
    Emoji 表情符号录入 mysql 数据库中报错。
    Caused by: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x97\xF0\x9F...' for column 'CONTENT' at row 1
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2734)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
    at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1379)

    解决思路:针对表情插入的问题,一定还是字符集的问题。
    处理方法:我们可以直接在参数文件中,加入
    vim /etc/my.cnf
    [mysqld]
    init-connect='SET NAMES utf8mb4'
    character-set-server=utf8mb4
    注:utf8mb4 是 utf8 的超集。

    Top 8:使用 binlog_format=statement 这种格式,跨库操作,导致从库丢失数据,用户访问导致出现错误数据信息。
    当前数据库二进制日志的格式为:binlog_format=statement
    在主库设置binlog-do-db=mydb1(只同步mydb1这一个库)
    在主库执行use mydb2;
    insert into mydb1.t1 values ('bb');这条语句不会同步到从库。
    但是这样操作就可以;
    use mydb1;
    insert into mydb1.t1 values ('bb');因为这是在同一个库中完成的操作。
    在生产环境中建议使用binlog的格式为row,而且慎用binlog-do-db参数。
    Top 9:MySQL 数据库连接超时的报错 ;
    org.hibernate.util.JDBCExceptionReporter - SQL Error:0, SQLState: 08S01
    org.hibernate.util.JDBCExceptionReporter - The last packet successfully received from the server was43200 milliseconds ago.The last packet sent successfully to the server was 43200 milliseconds ago, which is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection 'autoReconnect=true' to avoid this problem.
    org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
    org.hibernate.exception.JDBCConnectionException: Could not execute JDBC batch update
    com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
    org.hibernate.util.JDBCExceptionReporter - SQL Error:0, SQLState: 08003
    org.hibernate.util.JDBCExceptionReporter - No operations allowed after connection closed. Connection was implicitly closed e to underlying exception/error:
    ** BEGIN NESTED EXCEPTION **

    大多数做 DBA 的同学,可能都会被开发人员告知,你们的数据库报了这个错误了。赶紧看看是哪里的问题。
    这个问题是由两个参数影响的,wait_timeout 和 interactive_timeout。数据默认的配置时间是28800(8小时)意味着,超过这个时间之后,MySQL 数据库为了节省资源,就会在数据库端断开这个连接,Mysql服务器端将其断开了,但是我们的程序再次使用这个连接时没有做任何判断,所以就挂了。
    解决思路:
    先要了解这两个参数的特性;这两个参数必须同时设置,而且必须要保证值一致才可以。
    我们可以适当加大这个值,8小时太长了,不适用于生产环境。因为一个连接长时间不工作,还占用我们的连接数,会消耗我们的系统资源。
    解决方法:
    可以适当在程序中做判断;强烈建议在操作结束时更改应用程序逻辑以正确关闭连接;然后设置一个比较合理的timeout的值(根据业务情况来判断)
    Top 10 :can't open file (errno:24)
    有的时候,数据库跑得好好的,突然报不能打开数据库文件的错误了。
    解决思路:
    首先我们要先查看数据库的 error log。然后判断是表损坏,还是权限问题。还有可能磁盘空间不足导致的不能正常访问表;操作系统的*也要关注下;用 perror 工具查看具体错误!
    linux:/usr/local/mysql/bin # ./perror 24
    OS error code 24: Too many open files

    超出最大打开文件数*!ulimit -n查看系统的最大打开文件数是65535,不可能超出!那必然是数据库的最大打开文件数超出*!
    在 MySQL 里查看最大打开文件数*命令:show variables like 'open_files_limit';
    发现该数值过小,改为2048,重启 MySQL,应用正常
    处理方法:
    repair table ;
    chown mysql权限
    清理磁盘中的垃圾数据

    数据库mysql创建表格老是出错,看不懂英文提示?

    来自:51CTO(作者:superZS)
    我在刚开始学习数据库的时候,没少走弯路。经常会遇到各种稀奇古怪的 error 信息,遇到报错会很慌张,急需一个解决问题的办法。跟无头苍蝇一样,会不加思索地把错误粘到百度上,希望赶紧查找一下有没有好的处理问题的方法。我想这个应该是刚从事数据库的小白,都会遇到窘境。
    今天就给大家列举 MySQL 数据库中,最经典的十大错误案例,并附有处理问题的解决思路和方法,希望能给刚入行,或数据库爱好者一些帮助,今后再遇到任何报错,我们都可以很淡定地去处理。
    学习任何一门技术的同时,其实就是自我*的过程。沉下心,尝试去拥抱数据的世界!
    Top 1:
    Too many connections(连接数过多,导致连接不上数据库,业务无法正常进行)
    问题还原
    解决问题的思路:
    1、首先先要考虑在我们 MySQL 数据库参数文件里面,对应的 max_connections 这个参数值是不是设置的太小了,导致客户端连接数超过了数据库所承受的最大值。
    ● 该值默认大小是151,我们可以根据实际情况进行调整。
    ● 对应解决办法:set global max_connections=500
    但这样调整会有隐患,因为我们无法确认数据库是否可以承担这么大的连接压力,就好比原来一个人只能吃一个馒头,但现在却非要让他吃 10 个,他肯定接受不了。反应到服务器上面,就有可能会出现宕机的可能。
    所以这又反应出了,我们在新上线一个业务系统的时候,要做好压力测试。保证后期对数据库进行优化调整。
    2、其次可以* Innodb 的并发处理数量,如果 innodb_thread_concurrency = 0(这种代表不受*) 可以先改成 16或是64 看服务器压力。如果非常大,可以先改的小一点让服务器的压力下来之后,然后再慢慢增大,根据自己的业务而定。个人建议可以先调整为 16 即可。
    MySQL 随着连接数的增加性能是会下降的,可以让开发配合设置 thread pool,连接复用。在MySQL商业版中加入了thread pool这项功能
    另外对于有的监控程序会读取 information_schema 下面的表,可以考虑关闭下面的参数
    innodb_stats_on_metadata=0
    set global innodb_stats_on_metadata=0
    Top 2:(主从复制报错类型)
    Last_SQL_Errno: 1062 (从库与主库数据冲突)
    Last_Errno: 1062
    Last_Error: Could not execute Write_rows event on table test.t;
    Duplicate entry '4' for key 'PRIMARY',
    Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY;
    the event's master log mysql-bin.000014, end_log_pos 1505

    针对这个报错,我们首先要考虑是不是在从库中误操作导致的。结果发现,我们在从库中进行了一条针对有主键表的 sql 语句的插入,导致主库再插入相同 sql 的时候,主从状态出现异常。发生主键冲突的报错。
    解决方法:
    在确保主从数据一致性的前提下,可以在从库进行错误跳过。一般使用 percona-toolkit 中的 pt-slave-restart 进行。
    在从库完成如下操作
    [root@zs bin]# ./pt-slave-restart -uroot -proot123
    2017-07-20T14:05:30 p=...,u=root node4-relay-bin.000002 1506 1062

    之后最好在从库中开启 read_only 参数,禁止在从库进行写入操作
    Last_IO_Errno: 1593(server-id冲突)
    Last_IO_Error:
    Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids;
    these ids must be different for replication to work
    (or the --replicate-same-server-id option must be used on slave but this
    does not always make sense; please check the manual before using it)

    这个报错出现之后,就看一目了然看到两台机器的 server-id 是一样的。
    在搭建主从复制的过程中,我们要确保两台机器的 server-id 是唯一的。这里再强调一下 server-id 的命名规则(服务器 ip 地址的最后一位+本 MySQL 服务的端口号)
    解决方法:
    在主从两台机器上设置不同的 server-id。
    Last_SQL_Errno: 1032(从库少数据,主库更新的时候,从库报错)
    Last_SQL_Error:
    Could not execute Update_rows event on table test.t; Can't find record
    in 't', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the
    event's master log mysql-bin.000014, end_log_pos 1708

    解决问题的办法:
    根据报错信息,我们可以获取到报错日志和position号,然后就能找到主库执行的哪条sql,导致的主从报错。
    在主库执行:
    /usr/local/mysql/bin/mysqlbinlog --no-defaults -v -v --base64-output=decode-rows /data/mysql/mysql-bin.000014 |grep -A 10 1708 > 1.log
    cat 1.log
    #170720 14:20:15 server id 3 end_log_pos 1708 CRC32 0x97b6bdec Update_rows: table id 113 flags: STMT_END_F
    ### UPDATE `test`.`t`
    ### WHERE
    ### @1=4 /* INT meta=0 nullable=0 is_null=0 */
    ### @2='dd' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
    ### SET
    ### @1=4 /* INT meta=0 nullable=0 is_null=0 */
    ### @2='ddd' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
    # at 1708
    #170720 14:20:15 server id 3 end_log_pos 1739 CRC32 0xecaf1922 Xid = 654
    COMMIT/*!*/;
    DELIMITER ;
    # End of log file
    ROLLBACK /* added by mysqlbinlog */;
    /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
    /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

    获取到 sql 语句之后,就可以在从库反向执行 sql 语句。把从库缺少的 sql 语句补全,解决报错信息。
    在从库依次执行:
    mysql> insert into t (b) values ('ddd');
    Query OK, 1 row affected (0.01 sec)
    mysql> stop slave;
    Query OK, 0 rows affected (0.00 sec)
    mysql> exit
    Bye
    [root@node4 bin]# ./pt-slave-restart -uroot -proot123
    2017-07-20T14:31:37 p=...,u=root node4-relay-bin.000005 283 1032

    Top 3:MySQL安装过程中的报错
    [root@zs data]# /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf &[1] 3758
    [root@zs data]# 170720 14:41:24 mysqld_safe Logging to '/data/mysql/error.log'.
    170720 14:41:24 mysqld_safe Starting mysqld daemon with databases from /data/mysql170720
    14:41:25 mysqld_safe mysqld from pid file /data/mysql/node4.pid ended
    170720 14:41:24 mysqld_safe Starting mysqld daemon with databases from /data/mysql2017-07-20
    14:41:25 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated.
    Please use --explicit_defaults_for_timestamp server option
    (see documentation for more details)./usr/local/mysql/bin/mysqld:
    File '/data/mysql/mysql-bin.index' not found (Errcode: 13 - Permission denied)
    2017-07-20 14:41:25 4388 [ERROR] Aborting

    解决思路:
    遇到这样的报错信息,我们要学会时时去关注错误日志 error log 里面的内容。看见了关键的报错点 Permission denied。证明当前 MySQL 数据库的数据目录没有权限。
    解决方法:
    [root@zs data]# chown mysql:mysql -R mysql
    [root@zs data]# /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf &
    [1] 4402
    [root@zs data]# 170720 14:45:56 mysqld_safe Logging to '/data/mysql/error.log'.
    170720 14:45:56 mysqld_safe Starting mysqld daemon with databases from /data/mysql

    启动成功。
    如何避免这类问题,个人建议在安装 MySQL 初始化的时候,一定加上--user=mysql,这样就可以避免权限问题。
    ./mysql_install_db --basedir=/usr/local/mysql/ --datadir=/data/mysql/ --defaults-file=/etc/my.cnf --user=mysql
    Top 4:数据库密码忘记的问题
    [root@zs ~]# mysql -uroot -p
    Enter password:
    ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
    [root@zs ~]# mysql -uroot -p
    Enter password:
    ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

    我们有可能刚刚接手别人的 MySQL 数据库,而且没有完善的交接文档。root 密码可以丢失或者忘记了。
    解决思路:
    目前是进入不了数据库的情况,所以我们要考虑是不是可以跳过权限。因为在数据库中,mysql数据库中user表记录着我们用户的信息。
    解决方法:
    启动 MySQL 数据库的过程中,可以这样执行:
    /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf --skip-grant-tables &

    这样启动,就可以不用输入密码,直接进入 mysql 数据库了。然后在修改你自己想要改的root密码即可。
    update mysql.user set password=password('root123') where user='root';

    Top 5:truncate 删除数据,导致自动清空自增ID,前端返回报错 not found。
    这个问题的出现,就要考虑下 truncate 和 delete 的区别了。
    看下实验演练:
    首先先创建一张表;
    CREATE TABLE `t` (
    `a` int(11) NOT NULL AUTO_INCREMENT,
    `b` varchar(20) DEFAULT NULL,
    PRIMARY KEY (`a`),
    KEY `b` (`b`)
    ) ENGINE=InnoDB AUTO_INCREMENT=300 DEFAULT CHARSET=utf8

    插入三条数据:
    mysql> insert into t (b) values ('aa');
    Query OK, 1 row affected (0.00 sec)
    mysql> insert into t (b) values ('bb');
    Query OK, 1 row affected (0.00 sec)
    mysql> insert into t (b) values ('cc');
    Query OK, 1 row affected (0.00 sec)
    mysql> select * from t;
    +-----+------+
    | a | b |
    +-----+------+
    | 300 | aa |
    | 301 | bb |
    | 302 | cc |
    +-----+------+
    3 rows in set (0.00 sec)

    先用 delete 进行删除全表信息,再插入新值。
    结果发现 truncate 把自增初始值重置了,自增属性从1开始记录了。当前端用主键id进行查询时,就会报没有这条数据的错误。
    个人建议不要使用 truncate 对表进行删除操作,虽然可以回收表空间,但是会涉及自增属性问题。这些坑,我们不要轻易钻进去。
    Top 6:
    阿里云 MySQL 的配置文件中,需要注意一个参数设置就是:
    lower_case_table_names = 0;默认情况
    lower_case_table_names = 1;是不区分大小写 . 如果报你小写的表名找不到, 那你就把远端数据库的表名改成小写 , 反之亦然 . 注意 Mybatis 的 Mapper 文件的所有表名也要相应修改
    Top 7:
    有同学经常会问张老师,为什么我的数据库总会出现中文乱码的情况。一堆????不知道怎么回事。当向数据库中写入创建表,并插入中文时,会出现这种问题。此报错会涉及数据库字符集的问题。
    解决思路:
    对于中文乱码的情况,记住老师告诉你的三个统一就可以。还要知道在目前的mysql数据库中字符集编码都是默认的UTF8
    处理办法:
    1、数据终端,也就是我们连接数据库的工具设置为 utf8
    2、操作系统层面;可以通过 cat /etc/sysconfig/i18n 查看;也要设置为 utf8
    3、数据库层面;在参数文件中的 mysqld 下,加入 character-set-server=utf8。
    Emoji 表情符号录入 mysql 数据库中报错。
    Caused by: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x97\xF0\x9F...' for column 'CONTENT' at row 1
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2734)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
    at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1379)

    解决思路:针对表情插入的问题,一定还是字符集的问题。
    处理方法:我们可以直接在参数文件中,加入
    vim /etc/my.cnf
    [mysqld]
    init-connect='SET NAMES utf8mb4'
    character-set-server=utf8mb4
    注:utf8mb4 是 utf8 的超集。

    Top 8:使用 binlog_format=statement 这种格式,跨库操作,导致从库丢失数据,用户访问导致出现错误数据信息。
    当前数据库二进制日志的格式为:binlog_format=statement
    在主库设置binlog-do-db=mydb1(只同步mydb1这一个库)
    在主库执行use mydb2;
    insert into mydb1.t1 values ('bb');这条语句不会同步到从库。
    但是这样操作就可以;
    use mydb1;
    insert into mydb1.t1 values ('bb');因为这是在同一个库中完成的操作。
    在生产环境中建议使用binlog的格式为row,而且慎用binlog-do-db参数。
    Top 9:MySQL 数据库连接超时的报错 ;
    org.hibernate.util.JDBCExceptionReporter - SQL Error:0, SQLState: 08S01
    org.hibernate.util.JDBCExceptionReporter - The last packet successfully received from the server was43200 milliseconds ago.The last packet sent successfully to the server was 43200 milliseconds ago, which is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection 'autoReconnect=true' to avoid this problem.
    org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
    org.hibernate.exception.JDBCConnectionException: Could not execute JDBC batch update
    com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
    org.hibernate.util.JDBCExceptionReporter - SQL Error:0, SQLState: 08003
    org.hibernate.util.JDBCExceptionReporter - No operations allowed after connection closed. Connection was implicitly closed e to underlying exception/error:
    ** BEGIN NESTED EXCEPTION **

    大多数做 DBA 的同学,可能都会被开发人员告知,你们的数据库报了这个错误了。赶紧看看是哪里的问题。
    这个问题是由两个参数影响的,wait_timeout 和 interactive_timeout。数据默认的配置时间是28800(8小时)意味着,超过这个时间之后,MySQL 数据库为了节省资源,就会在数据库端断开这个连接,Mysql服务器端将其断开了,但是我们的程序再次使用这个连接时没有做任何判断,所以就挂了。
    解决思路:
    先要了解这两个参数的特性;这两个参数必须同时设置,而且必须要保证值一致才可以。
    我们可以适当加大这个值,8小时太长了,不适用于生产环境。因为一个连接长时间不工作,还占用我们的连接数,会消耗我们的系统资源。
    解决方法:
    可以适当在程序中做判断;强烈建议在操作结束时更改应用程序逻辑以正确关闭连接;然后设置一个比较合理的timeout的值(根据业务情况来判断)
    Top 10 :can't open file (errno:24)
    有的时候,数据库跑得好好的,突然报不能打开数据库文件的错误了。
    解决思路:
    首先我们要先查看数据库的 error log。然后判断是表损坏,还是权限问题。还有可能磁盘空间不足导致的不能正常访问表;操作系统的*也要关注下;用 perror 工具查看具体错误!
    linux:/usr/local/mysql/bin # ./perror 24
    OS error code 24: Too many open files

    超出最大打开文件数*!ulimit -n查看系统的最大打开文件数是65535,不可能超出!那必然是数据库的最大打开文件数超出*!
    在 MySQL 里查看最大打开文件数*命令:show variables like 'open_files_limit';
    发现该数值过小,改为2048,重启 MySQL,应用正常
    处理方法:
    repair table ;
    chown mysql权限
    清理磁盘中的垃圾数据

    高分 java连接SQL server 2000 详细步骤

    试试吧,

    在JSP中访问Oracle ,SqlServer ,DB2, Informix ,Access 数据库

    2007-1-13

    在JSP中访问Oracle ,SqlServer ,DB2, Informix ,Access 数据库

    现在有好多初学jsp的网友经常会问数据库怎么连接啊,怎么老出错啊?所以我集中的在这写篇文章供大家参考,其实这种把数据库逻辑全部放在jsp里未必是好的做法,但是有利于初学者学习,所以我就这样做了,当大家学到一定程度的时候,可以考虑用MVC的模式开发。在练习这些代码的时候,你一定将jdbc的驱动程序放到服务器的类路径里,然后要在数据库里建一个表test,有两个字段比如为test1,test2,可以用下面SQL建 create table test(test1 varchar(20),test2 varchar(20),然后向这个表写入一条测试纪录,那么现在开始我们的jsp和数据库之旅吧。

    一、jsp连接Oracle8/8i/9i数据库(用thin模式)

    testoracle.jsp如下:

    <%@ page contentType="text/html;charset=gb2312"%>

    <%@ page import="java.sql.*"%>

    <html>

    <body>

    <%Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();

    String url="jdbc:oracle:thin:@localhost:1521:orcl";

    //orcl为你的数据库的SID

    String user="scott";

    String password="tiger";

    Connection conn= DriverManager.getConnection(url,user,password);

    Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);

    String sql="select * from test";

    ResultSet rs=stmt.executeQuery(sql);

    while(rs.next()) {%>

    您的第一个字段内容为:<%=rs.getString(1)%>

    您的第二个字段内容为:<%=rs.getString(2)%>

    <%}%>

    <%out.print("数据库操作成功,恭喜你");%>

    <%rs.close();

    stmt.close();

    conn.close();

    %>

    </body>

    </html>

    二、jsp连接Sql Server7.0/2000数据库

    testsqlserver.jsp如下:

    <%@ page contentType="text/html;charset=gb2312"%>

    <%@ page import="java.sql.*"%>

    <html>

    <body>

    <%Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();

    String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=pubs";

    //pubs为你的数据库的

    String user="sa";

    String password="";

    Connection conn= DriverManager.getConnection(url,user,password);

    Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);

    String sql="select * from test";

    ResultSet rs=stmt.executeQuery(sql);

    while(rs.next()) {%>

    您的第一个字段内容为:<%=rs.getString(1)%>

    您的第二个字段内容为:<%=rs.getString(2)%>

    <%}%>

    <%out.print("数据库操作成功,恭喜你");%>

    <%rs.close();

    stmt.close();

    conn.close();

    %>

    </body>

    </html>

    三、jsp连接DB2数据库

    testdb2.jsp如下:

    <%@ page contentType="text/html;charset=gb2312"%>

    <%@ page import="java.sql.*"%>

    <html>

    <body>

    <%Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance();

    String url="jdbc:db2://localhost:5000/sample";

    //sample为你的数据库名

    String user="admin";

    String password="";

    Connection conn= DriverManager.getConnection(url,user,password);

    Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,

    ResultSet.CONCUR_UPDATABLE);

    String sql="select * from test";

    ResultSet rs=stmt.executeQuery(sql);

    while(rs.next()) {%>

    您的第一个字段内容为:<%=rs.getString(1)%>

    您的第二个字段内容为:<%=rs.getString(2)%>

    <%}%>

    <%out.print("数据库操作成功,恭喜你");%>

    <%rs.close();

    stmt.close();

    conn.close();

    %>

    </body>

    </html>

    四、jsp连接Informix数据库

    testinformix.jsp如下:

    <%@ page contentType="text/html;charset=gb2312"%>

    <%@ page import="java.sql.*"%>

    <html>

    <body>

    <%Class.forName("com.informix.jdbc.IfxDriver").newInstance();

    String url =

    "jdbc:informix-sqli://123.45.67.89:1533/testDB:INFORMIXSERVER=myserver;

    user=testuser;password=testpassword";

    //testDB为你的数据库名

    Connection conn= DriverManager.getConnection(url);

    Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);

    String sql="select * from test";

    ResultSet rs=stmt.executeQuery(sql);

    while(rs.next()) {%>

    您的第一个字段内容为:<%=rs.getString(1)%>

    您的第二个字段内容为:<%=rs.getString(2)%>

    <%}%>

    <%out.print("数据库操作成功,恭喜你");%>

    <%rs.close();

    stmt.close();

    conn.close();

    %>

    </body>

    </html>

    五、jsp连接Access数据库

    <%@page import="java.sql.*"

    import ="java.util.*"

    import ="java.io.*"

    import="java.text.*"

    contentType="text/html; charset=gb2312"

    buffer="20kb"

    %><%! int all,i,m_count;

    String odbcQuery;

    Connection odbcconn;

    Statement odbcstmt;

    ResultSet odbcrs;

    String username,title,content,work,email,url,time,date;

    String datetime;

    %>

    <%

    try{

    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

    }catch (ClassNotFoundException e)

    { out.print ("驱动程序不存在");

    }

    try{

    odbcconn = DriverManager.getConnection("jdbc:odbc:db1");

    odbcstmt = odbcconn.createStatement();

    odbcQuery="Select * From book where datetime>2001-4-26 Order By datetime DESC";

    odbcrs=odbcstmt.executeQuery(odbcQuery);

    int i=0;

    while (i<130) odbcrs.next();

    while (odbcrs.next())

    {

    //*/////////////////////////显示数据库的内容用于调试程序是用//

    int ii;

    try{

    try{

    for (ii=1;;ii++)

    out.print ("<br>Cloumn "+ii+" is: "+odbcrs.getString(ii));

    }catch (NullPointerException e) {

    out.print ("有空的指针");

    }

    }catch (SQLException e){

    }

    }

    odbcrs.close();

    odbcstmt.close();

    odbcconn.close();

    }catch (SQLException e)

    { out.print (e);

    }

    %>

    查看(24) 评论(0)

    Hibernate快速入门

    2006-11-10

    其实Hibernate本身是个的框架,它不需要任何web server或application server的支持。然而,大多数的Hibernate入门介绍都加入了很多非Hibernate的东西,比如: Tomcat, Eclipse, Log4J,Struts, XDoclet, 甚至JBoss。这容易让人产生Hibernate复杂难懂的误解,特别是打击了初学者的积极性。

    在这篇文章将不涉及Eclipse, log4j, Struts, Tomcat, XDoclet,和JBoss。本文的目的是演示一下Hibernate的安装过程以及最基本的功能,从而给初学者一个低得不能再低的入门门槛。

    下载文件

    你需要Java SDK、 Hibernate包、Ant包、和JDBC Driver。

    1、Hibernate包下载地址:

    http://prdownloads.sourceforge.n ... t_by=date&sort=desc

    2、Ant包下载地址:

    http://archive.apache.org/dist/ant/

    3、JDBC Driver要根据你用的database来定,一般database官方网站上都会有。Hibernate支持常用的database,比如 MySQL, Oracle, PostgreSQL, 和MS-SQL Server。这些数据库都有JDBC Driver:

    Oracle JDBC Driver下载地址(下载前必须同意Oracle协议书)

    http://otn.oracle.com/software/h ... tdocs/jdbc9201.html

    MySQL JDBC Driver下载地址

    http://dev.mysql.com/downloads/connector/j/3.0.html

    PostgreSQL JDBC Driver下载地址

    http://jdbc.postgresql.org/download.html

    MS-SQL Server JDBC Driver下载地址

    http://www.microsoft.com/downloa ... bf71&displaylang=en

    4、将Hibernate包和Ant包分别解压至c:dev下(此目录不重要,你可以换其它任何目录)。

    配置环境

    1、你需要添加一个新的环境变量: ANT_HOME,让它指向c:dev<的ANT包所在目录>并在PATH环境变量里添加%ANT_HOME%in。

    2、你需要添加一个新的环境变量: JAVA_HOME,让它指向你的j2sdk根目录。并在PATH环境变量里添加%JAVA_HOME%in。

    3、创建一个项目ā?目录,比如c:workspaceMy1stHibernate。

    在项目目录下,另外创建三个目录: src, classes, lib。

    在lib目录下,创建两个目录: hibernate和db。

    这样你有了如下的文件结构:

    c:workspaceMy1stHibernate

    c:workspaceMy1stHibernatesrc

    c:workspaceMy1stHibernateclasses

    c:workspaceMy1stHibernatelib

    c:workspaceMy1stHibernatelibhibernate

    c:workspaceMy1stHibernatelibdb

    4、将c:dev<的Hibernate包所在目录>hibernate2.jar文件copy到c:workspaceMy1stHibernatelibhibernate下。

    将c:dev<的Hibernate包所在目录>lib下的所有文件同样copy到c:workspaceMy1stHibernatelibhibernate下。

    将你的JDBC Driver文件(一般是一个jar文件)copy到c:workspaceMy1stHibernatelibdb下。

    创建数据库

    1、用你最喜爱的database软件,创建一个hibernate_test的数据库。

    2、在此数据库下,新建一个table名为CUSTOMER

    CREATE TABLE CUSTOMER

    (

    CID INTEGER NOT NULL PRIMARY KEY, USERNAME VARCHAR(12) NOT NULL, PASSWORD VARCHAR(12)

    );

    编写Java文件

    public class Customer {

    private int id;

    private String username;

    private String password;

    public int getId() {

    return id;

    }

    public String getPassword() {

    return password;

    }

    public String getUsername() {

    return username;

    }

    public void setId(int id) {

    this.id = id;

    }

    public void setPassword(String password) {

    this.password = password;

    }

    public void setUsername(String username) {

    this.username = username;

    }

    }

    将此类存为c:workspaceMy1stHibernatesrcCustomer.java文件。

    编写Test类

    import net.sf.hibernate.*;

    import net.sf.hibernate.cfg.*;

    public class Test {

    public static void main(String[] args) {

    try {

    SessionFactory sf = new Configuration().configure().buildSessionFactory();

    Session session = sf.openSession();

    Transaction tx = session.beginTransaction();

    for (int i = 0; i <200; i++) {

    Customer customer = new Customer();

    custoā?mer.setUsername("customer" + i);

    customer.setPassword("customer");

    session.save(customer);

    }

    tx.commit();

    session.close();

    } catch (HibernateException e) {

    e.printStackTrace();

    }

    }

    }

    将此类存为c:workspaceMy1stHibernatesrcTest.java文件。

    创建Hibernate映射文件

    因为这里只有一个Class --- Customer 和一个Table --- CUSTOMER,你只需要建立一个映射文件--- Customer.hbm.xml,来对应Customer类和CUSTOMER表之间的关系。

    <xml version="1.0"?>

    <DOCTYPE hibernate-mapping PUBLIC

    "-//Hibernate/Hibernate Mapping DTD//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

    <ibernate-mapping>

    <lass name="Customer" table="CUSTOMER">

    <d name="id" column="CID">

    <enerator class="increment" />

    <id>

    <roperty name="username" column="USERNAME" />

    <roperty name="password" column="PASSWORD" />

    <class>

    <hibernate-mapping>

    把此文件存为c:workspaceMy1stHibernatesrcCustomer.hbm.xml,和Customer.java放在同一目录下。

    编写Ant build.xml文件

    你不一定要知道这个build.xml的细节,其实Ant也不是Hibernate所必须的。这里用Ant是为了简化一些任务,比如: 编译、copy、运行,等。

    <xml version="1.0" ?>

    <roject name="My1stHibernate" default="build" basedir=".">

    <roperty name="base.dir" value="." />

    <roperty name="src.dir" value="src" />

    <roperty name="lib.dir" value="lib" />

    <roperty name="build.dir" value="classes" />

    <ath id="myclasspath">

    <ileset dir="${lib.dir}">

    <nclude name="**/*.jar" />

    <fileset>

    <athelement location="${build.dir}" />

    <path>

    <arget name="init">

    <kdir dir="${build.dir}" />

    <target>

    <arget name="build" depends="init" description="compile the source files">

    <avac classpathref="myclasspath" srcdir="${src.dir}" destdir="${build.dir}" />

    <opy todir="${build.dir}" >

    <ileset dir="${src.dir}" >

    ā?<xclude name="**/*.java"/>

    <fileset>

    <copy>

    <target>

    <arget name="run" depends="build">

    <ava classpathref="myclasspath" classname="Test" fork="true" />

    <target>

    <arget name="clean">

    <elete includeEmptyDirs="true">

    <ileset dir="${build.dir}" />

    <delete>

    <target>

    <project>

    配置Hibernate描述文件

    Hibernate描述文件可以是一个properties或xml 文件,其中最重要的是定义数据库的连接。我这里列出的是一个XML格式的hibernate.cfg.xml描述文件。

    <xml version="1.0" encoding="utf-8" ?>

    <DOCTYPE hibernate-configuration

    PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"

    "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">

    <ibernate-configuration>

    <ession-factory name="java:/hibernate/HibernateFactory">

    <roperty name="show_sql">rue<property>

    <roperty name="connection.driver_class">

    oracle.jdbc.driver.OracleDriver <-- 这里是Oracle 9i的JDBC driver class名 -->

    <property>

    <roperty name="connection.url">

    jdbc:oracle:oci8:@hibernate_test <-- 这里是Oracle的hibernate_test数据库URL -->

    <property>

    <roperty name="connection.username">

    你的数据库用户名

    <property>

    <roperty name="connection.password">

    你的数据库密码

    <property>

    <roperty name="dialect">

    net.sf.hibernate.dialect.Oracle9Dialect <-- 这里是Oracle 9i的Dialect -->

    <property>

    <apping resource="Customer.hbm.xml" /><-- 指定Customer的映射文件 -->

    <session-factory>

    <hibernate-configuration>

    如果你用的不是Oracle 9i,可到C:dev<的Hibernate包所在目录>srchibernate.properties文件里找到你的数据库,然后替换以上相对应的值。

    开始运行

    到c:workspaceMy1stHibernate下,运行ant run。如果你严格依照以上步骤,应该看到

    run:

    [java] log4j:WARN No appenders could be found for logger (net.sf.hibernate.cfg.Environment).

    [java] log4j:WARN Please initialize the log4j system properly.

    [java] Hibernate: insert into CUSTOMER (USERNAME, PASSWORD, CID) values (?, ?, ?)

    BUILD SUCCESSFUL

    到你的hibernate_test数据库看一下,在CUSTMOR表里新添了200条记录,但你没有写任何JDBC code。

    以后如果你要更换数据库,只需要改变hibernate.cfg.xml描述文件里相应的值即可。

    查看(89) 评论(4)

    掌握 Ajax, Ajax 简介

    2006-11-10

    Ajax 由 HTML、JavaScript™ 技术、DHTML 和 DOM 组成,这一杰出的方法可以将笨拙的 Web 界面转化成交互性的 Ajax 应用程序。本文的作者是一位 Ajax 专家,他演示了这些技术如何协同工作 —— 从总体概述到细节的讨论 —— 使高效的 Web 开发成为现实。他还揭开了 Ajax 核心概念的神秘面纱,包括 XMLHttpRequest 对象。

    五年前,如果不知道 XML,您就是一只无人重视的丑小鸭。十八个月前,Ruby 成了关注的中心,不知道 Ruby 的程序员只能坐冷板凳了。今天,如果想跟上最新的技术时尚,那您的目标就是 Ajax。

    但是,Ajax 不仅仅 是一种时尚,它是一种构建网站的强大方法,而且不像学习一种全新的语言那样困难。

    但在详细探讨 Ajax 是什么之前,先让我们花几分钟了解 Ajax 做 什么。目前,编写应用程序时有两种基本的选择:

    桌面应用程序

    Web 应用程序

    两者是类似的,桌面应用程序通常以 CD 为介质(有时候可从网站下载)并完全安装到您的计算机上。桌面应用程序可能使用互联网下载更新,但运行这些应用程序的代码在桌面计算机上。Web 应用程序运行在某处的 Web 服务器上 —— 毫不奇怪,要通过 Web 浏览器访问这种应用程序。

    不过,比这些应用程序的运行代码放在何处更重要的是,应用程序如何运转以及如何与其进行交互。桌面应用程序一般很快(就在您的计算机上运行,不用等待互联网连接),具有漂亮的用户界面(通常和操作系统有关)和非凡的动态性。可以单击、选择、输入、打开菜单和子菜单、到处巡游,基本上不需要等待。

    另一方面,Web 应用程序是最新的潮流,它们提供了在桌面上不能实现的服务(比如 Amazon.com 和 eBay)。但是,伴随着 Web 的强大而出现的是等待,等待服务器响应,等待屏幕刷新,等待请求返回和生成新的页面。

    显然这样说过于简略了,但基本的概念就是如此。您可能已经猜到,Ajax 尝试建立桌面应用程序的功能和交互性,与不断更新的 Web 应用程序之间的桥梁。可以使用像桌面应用程序中常见的动态用户界面和漂亮的控件,不过是在 Web 应用程序中。

    还等什么呢?我们来看看 Ajax 如何将笨拙的 Web 界面转化成能迅速响应的 Ajax 应用程序吧。

    老技术,新技巧

    在谈到 Ajax 时,实际上涉及到多种技术,要灵活地运用它必须深入了解这些不同的技术(本系列的头几篇文章将分别讨论这些技术)。好消息是您可能已经非常熟悉其中的大部分技术,更好的是这些技术都很容易学习,并不像完整的编程语言(如 Java 或 Ruby)那样困难。

    Ajax 的定义

    顺便说一下,Ajax 是 Asynchronous JavaScript and XML(以及 DHTML 等)的缩写。这个短语是 Adaptive Path 的 Jesse James Garrett 发明的(请参阅 参考资料),按照 Jesse 的解释,这不是 个首字母缩写词。

    下面是 Ajax 应用程序所用到的基本技术:

    HTML 用于建立 Web 表单并确定应用程序其他部分使用的字段。

    JavaScript 代码是运行 Ajax 应用程序的核心代码,帮助改进与服务器应用程序的通信。

    DHTML 或 Dynamic HTML,用于动态更新表单。我们将使用 div、span 和其他动态 HTML 元素来标记 HTML。

    文档对象模型 DOM 用于(通过 JavaScript 代码)处理 HTML 结构和(某些情况下)服务器返回的 XML。

    我们来进一步分析这些技术的职责。以后的文章中我将深入讨论这些技术,目前只要熟悉这些组件和技术就可以了。对这些代码越熟悉,就越容易从对这些技术的零散了解转变到真正把握这些技术(同时也真正打开了 Web 应用程序开发的大门)。

    XMLHttpRequest 对象

    要了解的一个对象可能对您来说也是最陌生的,即 XMLHttpRequest。这是一个 JavaScript 对象,创建该对象很简单,如清单 1 所示。

    清单 1. 创建新的 XMLHttpRequest 对象

    <script language="javascript" type="text/javascript">

    var xmlHttp = new XMLHttpRequest();

    </script>

    下一期文章中将进一步讨论这个对象,现在要知道这是处理所有服务器通信的对象。继续阅读之前,先停下来想一想:通过 XMLHttpRequest 对象与服务器进行对话的是 JavaScript 技术。这不是一般的应用程序流,这恰恰是 Ajax 的强大功能的来源。

    在一般的 Web 应用程序中,用户填写表单字段并单击 Submit 按钮。然后整个表单发送到服务器,服务器将它转发给处理表单的脚本(通常是 PHP 或 Java,也可能是 CGI 进程或者类似的东西),脚本执行完成后再发送回全新的页面。该页面可能是带有已经填充某些数据的新表单的 HTML,也可能是确认页面,或者是具有根据原来表单中输入数据选择的某些选项的页面。当然,在服务器上的脚本或程序处理和返回新表单时用户必须等待。屏幕变成一片空白,等到服务器返回数据后再重新绘制。这就是交互性差的原因,用户得不到立即反馈,因此感觉不同于桌面应用程序。

    Ajax 基本上就是把 JavaScript 技术和 XMLHttpRequest 对象放在 Web 表单和服务器之间。当用户填写表单时,数据发送给一些 JavaScript 代码而不是 直接发送给服务器。相反,JavaScript 代码捕获表单数据并向服务器发送请求。同时用户屏幕上的表单也不会闪烁、消失或延迟。换句话说,JavaScript 代码在幕后发送请求,用户甚至不知道请求的发出。更好的是,请求是异步发送的,就是说 JavaScript 代码(和用户)不用等待服务器的响应。因此用户可以继续输入数据、滚动屏幕和使用应用程序。

    然后,服务器将数据返回 JavaScript 代码(仍然在 Web 表单中),后者决定如何处理这些数据。它可以迅速更新表单数据,让人感觉应用程序是立即完成的,表单没有提交或刷新而用户得到了新数据。JavaScript 代码甚至可以对收到的数据执行某种计算,再发送另一个请求,完全不需要用户干预!这就是 XMLHttpRequest 的强大之处。它可以根据需要自行与服务器进行交互,用户甚至可以完全不知道幕后发生的一切。结果就是类似于桌面应用程序的动态、快速响应、高交互性的体验,但是背后又拥有互联网的全部强大力量。

    加入一些 JavaScript

    得到 XMLHttpRequest 的句柄后,其他的 JavaScript 代码就非常简单了。事实上,我们将使用 JavaScript 代码完成非常基本的任务:

    获取表单数据:JavaScript 代码很容易从 HTML 表单中抽取数据并发送到服务器。

    修改表单上的数据:更新表单也很简单,从设置字段值到迅速替换图像。

    解析 HTML 和 XML:使用 JavaScript 代码操纵 DOM(请参阅 下一节),处理 HTML 表单服务器返回的 XML 数据的结构。

    对于前两点,需要非常熟悉 getElementById() 方法,如 清单 2 所示。

    清单 2. 用 JavaScript 代码捕获和设置字段值

    // Get the value of the "phone" field and stuff it in a variable called phone

    var phone = document.getElementById("phone").value;

    // Set some values on a form using an array called response

    document.getElementById("order").value = response[0];

    document.getElementById("address").value = response[1];

    这里没有特别需要注意的地方,真是好极了!您应该认识到这里并没有非常复杂的东西。只要掌握了 XMLHttpRequest,Ajax 应用程序的其他部分就是如 清单 2 所示的简单 JavaScript 代码了,混合有少量的 HTML。同时,还要用一点儿 DOM,我们就来看看吧。

    以 DOM 结束

    最后还有 DOM,即文档对象模型。可能对有些读者来说 DOM 有点儿令人生畏,HTML 设计者很少使用它,即使 JavaScript 程序员也不大用到它,除非要完成某项高端编程任务。大量使用 DOM 的是 复杂的 Java 和 C/C++ 程序,这可能就是 DOM 被认为难以学习的原因。

    幸运的是,在 JavaScript 技术中使用 DOM 很容易,也非常直观。现在,按照常规也许应该说明如何使用 DOM,或者至少要给出一些示例代码,但这样做也可能误导您。即使不理会 DOM,仍然能深入地探讨 Ajax,这也是我准备采用的方法。以后的文章将再次讨论 DOM,现在只要知道可能需要 DOM 就可以了。当需要在 JavaScript 代码和服务器之间传递 XML 和改变 HTML 表单的时候,我们再深入研究 DOM。没有它也能做一些有趣的工作,因此现在就把 DOM 放到一边吧。

    回页首

    获取 Request 对象

    有了上面的基础知识后,我们来看看一些具体的例子。XMLHttpRequest 是 Ajax 应用程序的核心,而且对很多读者来说可能还比较陌生,我们就从这里开始吧。从 清单 1 可以看出,创建和使用这个对象非常简单,不是吗?等一等。

    还记得几年前的那些讨厌的浏览器战争吗?没有一样东西在不同的浏览器上得到同样的结果。不管您是否相信,这些战争仍然在继续,虽然规模较小。但令人奇怪的是,XMLHttpRequest 成了这场战争的牺牲品之一。因此获得 XMLHttpRequest 对象可能需要采用不同的方法。下面我将详细地进行解释。

    使用 Micr

    C#连接mysql数据库,怎么设置超时时间

    MySQL查询超时的设置方法

    为了优化OceanBase的query timeout设置方式,特调研MySQL关于timeout的处理,记录如下。

    [plain]
    mysql> show variables like '%time%';
    +----------------------------+-------------------+
    | Variable_name | Value |
    +----------------------------+-------------------+
    | connect_timeout | 10 |
    | datetime_format | %Y-%m-%d %H:%i:%s |
    | delayed_insert_timeout | 300 |
    | flush_time | 1800 |
    | innodb_lock_wait_timeout | 50 |
    | innodb_old_blocks_time | 0 |
    | innodb_rollback_on_timeout | OFF |
    | interactive_timeout | 28800 |
    | lc_time_names | en_US |
    | lock_wait_timeout | 31536000 |
    | long_query_time | 10.000000 |
    | net_read_timeout | 30 |
    | net_write_timeout | 60 |
    | slave_net_timeout | 3600 |
    | slow_launch_time | 2 |
    | system_time_zone | |
    | time_format | %H:%i:%s |
    | time_zone | SYSTEM |
    | timed_mutexes | OFF |
    | timestamp | 1366027807 |
    | wait_timeout | 28800 |
    +----------------------------+-------------------+
    21 rows in set, 1 warning (0.00 sec)

    重点解释其中几个参数:

    connect_timeout:

    The number of seconds that the mysqld server waits for a connect packet before respondingwith Bad handshake. The default value is 10 seconds as of MySQL 5.1.23 and 5 seconds before that. Increasing the connect_timeout value might help if clients frequently encounter errors of the form Lost connection to MySQL server at ‘XXX’, system error: errno.
    解释:在获取链接时,等待握手的超时时间,只在登录时有效,登录成功这个参数就不管事了。主要是为了防止网络不佳时应用重连导致连接数涨太快,一般默认即可。

    interactive_timeout:

    The number of seconds the server waits for activity on an interactive connection before closing it. An interactive client is defined as a client that uses the CLIENT_INTERACTIVE option to mysql_real_connect(). See alsowait_timeout.

    解释:一个持续SLEEP状态的线程多久被关闭。线程每次被使用都会被唤醒为acrivity状态,执行完Query后成为interactive状态,重新开始计时。wait_timeout不同在于只作用于TCP/IP和Socket链接的线程,意义是一样的。

    MySQL可以配置连接的超时时间,这个时间如果做得太长,甚至到了10min,那么很可能发生这种情况,3000个链接都被占满而且sleep在哪,新链接进不来,导致无法正常服务。因此这个配置尽量配置一个符合逻辑的值,60s或者120s等等。
    说人话:

    命令行下面敲一个命令后,直至下一个命令到来之前的时间间隔为interactive_time,如果这个时间间隔超过了interactive_timeout,则连接会被自动断开,下一个命令失败。不过一般的mysql客户端都有自动重连机制,下一个命令会在重连后执行。

    [sql]
    mysql> set interactive_timeout = 1;
    Query OK, 0 rows affected (0.00 sec)

    mysql> show session variables like '%timeout%';
    +----------------------------+----------+
    | Variable_name | Value |
    +----------------------------+----------+
    | connect_timeout | 10 |
    | interactive_timeout | 1 |
    | wait_timeout | 28800 |
    +----------------------------+----------+
    10 rows in set (0.00 sec)

    =====

    [sql]
    mysql> set wait_timeout = 1;
    Query OK, 0 rows affected (0.00 sec)
    【去泡杯茶,等会儿】

    mysql> show session variables like '%timeout%';
    ERROR 2006 (HY000): MySQL server has gone away
    No connection. Trying to reconnect...
    Connection id: 7
    Current database: *** NONE ***

    +----------------------------+----------+
    | Variable_name | Value |
    +----------------------------+----------+
    | connect_timeout | 10 |
    | interactive_timeout | 28800 |
    | wait_timeout | 28800 |
    +----------------------------+----------+
    10 rows in set (0.01 sec)

    wait_timeout:
    The number of seconds the server waits for activity on a noninteractive connection (连接上没有活动命令,可能是客户端喝咖啡去了。)before closing it. Before MySQL 5.1.41, this timeout applies only to TCP/IP connections, not to connections made through Unix socket files, named pipes, or shared memory.
    On thread startup, the session wait_timeout value is initialized from the global wait_timeout value or from the global interactive_timeout value, depending on the type of client
    这里顺带解释一下什么是non-interactive connection

    > Non-Interactive Commands
    Just do a quick look up on a table without logging into the client, running the query then logging back out again.
    You can instead just type one line using the ' -e ' flag.
    [sql]
    c:\mysql\bin\mysql -u admin -p myDatabase -e 'SELECT * FROM employee'

    net_read_timeout / net_write_timeout
    The number of seconds to wait for more data from a connection before aborting the read. Before MySQL 5.1.41, this timeout applies only to TCP/IP connections, not to connections made through Unix socket files, named pipes, or shared memory. When the server is reading from the client, net_read_timeout is the timeout value controlling when to abort. When the server is writing to the client, net_write_timeout is the timeout value controlling when to abort. See also slave_net_timeout.
    On Linux, the NO_ALARM build flag affects timeout behavior as indicated in the description of the net_retry_count system variable.
    解释:这个参数只对TCP/IP链接有效,分别是数据库等待接收客户端发送网络包和发送网络包给客户端的超时时间,这是在Activity状态下的线程才有效的参数

    JDBC setQueryTimeout函数:

    为了避免查询出现死循环,或时间过长等现象,而导致线程阻塞,在获得Statement的实例后,stmt.setQueryTimeout(10); 避免因为查询导致程序出现线程阻塞。

    但昨天发现程序出现了,“ORA-01013: 用户请求取消当前的操作”的异常。手工执行出错SQL语句发现,这个语句耗时20多秒。因为setQueryTimeout(10),所以还没有执行完查询语句就抛出异常了。使用setQueryTimeout(10)时一定要把时间设置的长一些,如60秒以上。只要不导致线程长期阻塞,就可以。太短了容易抛出,“ORA-01013: 用户请求取消当前的操作”的异常

    JDBC实现setQueryTimeout的原理:

    [java]
    class IfxCancelQueryImpl extends TimerTask
    implements IfmxCancelQuery
    {
    IfxStatement stmt;
    Timer t = null;

    public void startCancel(IfxStatement paramIfxStatement, int paramInt)
    throws Exception
    {
    this.stmt = paramIfxStatement;
    this.t = new Timer(true);
    this.t.schele(this, paramInt * 1000);
    }

    public void run()
    {
    try
    {
    this.stmt.cancel();
    this.t.cancel();
    }
    catch (SQLException localSQLException)
    {
    this.t.cancel();
    throw new Error(localSQLException.getErrorCode() + ":" + localSQLException.getMessage());
    }
    }
    }

    C#连接mysql数据库,怎么设置超时时间

    MySQL查询超时的设置方法

    为了优化OceanBase的query timeout设置方式,特调研MySQL关于timeout的处理,记录如下。

    [plain]
    mysql> show variables like '%time%';
    +----------------------------+-------------------+
    | Variable_name | Value |
    +----------------------------+-------------------+
    | connect_timeout | 10 |
    | datetime_format | %Y-%m-%d %H:%i:%s |
    | delayed_insert_timeout | 300 |
    | flush_time | 1800 |
    | innodb_lock_wait_timeout | 50 |
    | innodb_old_blocks_time | 0 |
    | innodb_rollback_on_timeout | OFF |
    | interactive_timeout | 28800 |
    | lc_time_names | en_US |
    | lock_wait_timeout | 31536000 |
    | long_query_time | 10.000000 |
    | net_read_timeout | 30 |
    | net_write_timeout | 60 |
    | slave_net_timeout | 3600 |
    | slow_launch_time | 2 |
    | system_time_zone | |
    | time_format | %H:%i:%s |
    | time_zone | SYSTEM |
    | timed_mutexes | OFF |
    | timestamp | 1366027807 |
    | wait_timeout | 28800 |
    +----------------------------+-------------------+
    21 rows in set, 1 warning (0.00 sec)

    重点解释其中几个参数:

    connect_timeout:

    The number of seconds that the mysqld server waits for a connect packet before respondingwith Bad handshake. The default value is 10 seconds as of MySQL 5.1.23 and 5 seconds before that. Increasing the connect_timeout value might help if clients frequently encounter errors of the form Lost connection to MySQL server at ‘XXX’, system error: errno.
    解释:在获取链接时,等待握手的超时时间,只在登录时有效,登录成功这个参数就不管事了。主要是为了防止网络不佳时应用重连导致连接数涨太快,一般默认即可。

    interactive_timeout:

    The number of seconds the server waits for activity on an interactive connection before closing it. An interactive client is defined as a client that uses the CLIENT_INTERACTIVE option to mysql_real_connect(). See alsowait_timeout.

    解释:一个持续SLEEP状态的线程多久被关闭。线程每次被使用都会被唤醒为acrivity状态,执行完Query后成为interactive状态,重新开始计时。wait_timeout不同在于只作用于TCP/IP和Socket链接的线程,意义是一样的。

    MySQL可以配置连接的超时时间,这个时间如果做得太长,甚至到了10min,那么很可能发生这种情况,3000个链接都被占满而且sleep在哪,新链接进不来,导致无法正常服务。因此这个配置尽量配置一个符合逻辑的值,60s或者120s等等。
    说人话:

    命令行下面敲一个命令后,直至下一个命令到来之前的时间间隔为interactive_time,如果这个时间间隔超过了interactive_timeout,则连接会被自动断开,下一个命令失败。不过一般的mysql客户端都有自动重连机制,下一个命令会在重连后执行。

    [sql]
    mysql> set interactive_timeout = 1;
    Query OK, 0 rows affected (0.00 sec)

    mysql> show session variables like '%timeout%';
    +----------------------------+----------+
    | Variable_name | Value |
    +----------------------------+----------+
    | connect_timeout | 10 |
    | interactive_timeout | 1 |
    | wait_timeout | 28800 |
    +----------------------------+----------+
    10 rows in set (0.00 sec)

    =====

    [sql]
    mysql> set wait_timeout = 1;
    Query OK, 0 rows affected (0.00 sec)
    【去泡杯茶,等会儿】

    mysql> show session variables like '%timeout%';
    ERROR 2006 (HY000): MySQL server has gone away
    No connection. Trying to reconnect...
    Connection id: 7
    Current database: *** NONE ***

    +----------------------------+----------+
    | Variable_name | Value |
    +----------------------------+----------+
    | connect_timeout | 10 |
    | interactive_timeout | 28800 |
    | wait_timeout | 28800 |
    +----------------------------+----------+
    10 rows in set (0.01 sec)

    wait_timeout:
    The number of seconds the server waits for activity on a noninteractive connection (连接上没有活动命令,可能是客户端喝咖啡去了。)before closing it. Before MySQL 5.1.41, this timeout applies only to TCP/IP connections, not to connections made through Unix socket files, named pipes, or shared memory.
    On thread startup, the session wait_timeout value is initialized from the global wait_timeout value or from the global interactive_timeout value, depending on the type of client
    这里顺带解释一下什么是non-interactive connection

    > Non-Interactive Commands
    Just do a quick look up on a table without logging into the client, running the query then logging back out again.
    You can instead just type one line using the ' -e ' flag.
    [sql]
    c:\mysql\bin\mysql -u admin -p myDatabase -e 'SELECT * FROM employee'

    net_read_timeout / net_write_timeout
    The number of seconds to wait for more data from a connection before aborting the read. Before MySQL 5.1.41, this timeout applies only to TCP/IP connections, not to connections made through Unix socket files, named pipes, or shared memory. When the server is reading from the client, net_read_timeout is the timeout value controlling when to abort. When the server is writing to the client, net_write_timeout is the timeout value controlling when to abort. See also slave_net_timeout.
    On Linux, the NO_ALARM build flag affects timeout behavior as indicated in the description of the net_retry_count system variable.
    解释:这个参数只对TCP/IP链接有效,分别是数据库等待接收客户端发送网络包和发送网络包给客户端的超时时间,这是在Activity状态下的线程才有效的参数

    JDBC setQueryTimeout函数:

    为了避免查询出现死循环,或时间过长等现象,而导致线程阻塞,在获得Statement的实例后,stmt.setQueryTimeout(10); 避免因为查询导致程序出现线程阻塞。

    但昨天发现程序出现了,“ORA-01013: 用户请求取消当前的操作”的异常。手工执行出错SQL语句发现,这个语句耗时20多秒。因为setQueryTimeout(10),所以还没有执行完查询语句就抛出异常了。使用setQueryTimeout(10)时一定要把时间设置的长一些,如60秒以上。只要不导致线程长期阻塞,就可以。太短了容易抛出,“ORA-01013: 用户请求取消当前的操作”的异常

    JDBC实现setQueryTimeout的原理:

    [java]
    class IfxCancelQueryImpl extends TimerTask
    implements IfmxCancelQuery
    {
    IfxStatement stmt;
    Timer t = null;

    public void startCancel(IfxStatement paramIfxStatement, int paramInt)
    throws Exception
    {
    this.stmt = paramIfxStatement;
    this.t = new Timer(true);
    this.t.schele(this, paramInt * 1000);
    }

    public void run()
    {
    try
    {
    this.stmt.cancel();
    this.t.cancel();
    }
    catch (SQLException localSQLException)
    {
    this.t.cancel();
    throw new Error(localSQLException.getErrorCode() + ":" + localSQLException.getMessage());
    }
    }
    }

    我将数据库的用户名root的主机改为%还是不可以访问mysql数据库,为什么?

    还要设定权限的啊

    [root@localhost ~]# mysql

    Welcome to the MySQL monitor. Commands end with ; or \g.

    Your MySQL connection id is 1

    Server version: 5.1.41-community MySQL Community Server (GPL)

    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

    mysql> grant all on *.* to root@'%' identified by 'your_password';

    Query OK, 0 rows affected (0.01 sec)

    mysql> exit

    Bye

    [root@localhost ~]# /etc/init.d/mysql restart追问我使用的wamp,集成的开发环境

    追答修改权限是在数据库里面改 不是在IDE的环境

    分页显示怎么使用

    目前最好的JSP分页技术

    在使用数据库的过程中,不可避免的需要使用到分页的功能,可是JDBC的规范对此却没有很好的解决。对于这个需求很多朋友都有自己的解决方案,比如使用Vector等集合类先保存取出的数据再分页。但这种方法的可用性很差,与JDBC本身的接口完全不同,对不同类型的字段的支持也不好。这里提供了一种与JDBC兼容性非常好的方案。
    JDBC和分页
    Sun的JDBC规范的制定,有时很让人哭笑不得,在JDBC1.0中,对于一个结果集(ResultSet)你甚至只能执行next()操作,而无法让其向后滚动,这就直接导致在只执行一次SQL查询的情况下无法获得结果集的大小。所以,如果你使用的是JDBC1.0的驱动,那么是几乎无法实现分页的。
    好在Sun的JDBC2规范中很好的弥补了这一个不足,增加了结果集的前后滚动操作,虽然仍然不能直接支持分页,但我们已经可以在这个基础上写出自己的可支持分页的ResultSet了。

    和具体数据库相关的实现方法
    有一些数据库,如Mysql, Oracle等有自己的分页方法,比如Mysql可以使用limit子句,Oracle可以使用ROWNUM来*结果集的大小和起始位置。这里以Mysql为例,其典型代码如下:
    // 计算总的记录条数
    String SQL = "SELECT Count(*) AS total " + this.QueryPart;
    rs = db.executeQuery(SQL);
    if (rs.next())
    Total = rs.getInt(1);
    // 设置当前页数和总页数
    TPages = (int)Math.ceil((double)this.Total/this.MaxLine);
    CPages = (int)Math.floor((double)Offset/this.MaxLine+1);
    // 根据条件判断,取出所需记录
    if (Total > 0) {
    SQL = Query + " LIMIT " + Offset + " , " + MaxLine;
    rs = db.executeQuery(SQL);
    }
    return rs;
    }
    毫无疑问,这段代码在数据库是Mysql时将会是漂亮的,但是作为一个通用的类(事实上我后面要提供的就是一个通用类库中的一部分),需要适应不同的数据库,而基于这个类(库)的应用,也可能使用不同的数据库,所以,我们将不使用这种方法。

    另一种繁琐的实现方法
    我看过一些人的做法(事实上包括我在内,一开始也是使用这种方法的),即不使用任何封装,在需要分页的地方,直接操作ResultSet滚到相应的位置,再读取相应数量的记录。其典型代码如下:
    <%
    sqlStmt = sqlCon.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,
    java.sql.ResultSet.CONCUR_READ_ONLY);
    strSQL = "select name,age from test";
    //执行SQL语句并获取结果集
    sqlRst = sqlStmt.executeQuery(strSQL);
    //获取记录总数
    sqlRst.last();
    intRowCount = sqlRst.getRow();
    //记算总页数
    intPageCount = (intRowCount+intPageSize-1) / intPageSize;
    //调整待显示的页码
    if(intPage>intPageCount) intPage = intPageCount;
    %>
    <table border="1" cellspacing="0" cellpadding="0">
    <tr>
    <th>姓名</th>
    <th>年龄</th>
    </tr>
    <%
    if(intPageCount>0){
    //将记录指针定位到待显示页的第一条记录上
    sqlRst.absolute((intPage-1) * intPageSize + 1);
    //显示数据
    i = 0;
    while(i<intPageSize && !sqlRst.isAfterLast()){
    %>
    <tr>
    <td><%=sqlRst.getString(1)%></td>
    <td><%=sqlRst.getString(2)%></td>
    </tr>
    <%
    sqlRst.next();
    i++;
    }
    }
    %>
    </table>
    很显然,这种方法没有考虑到代码重用的问题,不仅代码数量巨大,而且在代码需要修改的情况下,将会无所适从。

    使用Vector进行分页
    还见过另一些实现分页的类,是先将所有记录都select出来,然后将ResultSet中的数据都get出来,存入Vector等集合类中,再根据所需分页的大小,页数,定位到相应的位置,读取数据。或者先使用前面提到的两种分页方法,取得所需的页面之后,再存入Vector中。
    扔开代码的效率不说,单是从程序结构和使用的方便性上讲,就是很糟糕的。比如,这种做法支持的字段类型有限,int, double, String类型还比较好处理,如果碰到Blob, Text等类型,实现起来就很麻烦了。这是一种更不可取的方案。

    一个新的Pageable接口及其实现
    很显然,看过上面三种实现方法后,我们对新的分页机制有了一个目标,即:不与具体数据库相关;尽可能做到代码重用;尽可能与原JDBC接口的使用方法保持一致;尽可能高的效率。
    首先,我们需要提供一个与java.sql.ResultSet向下兼容的接口,把它命名为Pageable,接口定义如下:
    public interface Pageable extends java.sql.ResultSet{
    /**返回总页数
    */
    int getPageCount();
    /**返回当前页的记录条数
    */
    int getPageRowsCount();
    /**返回分页大小
    */
    int getPageSize();
    /**转到指定页
    */
    void gotoPage(int page) ;
    /**设置分页大小
    */
    void setPageSize(int pageSize);
    /**返回总记录行数
    */
    int getRowsCount();
    /**
    * 转到当前页的第一条记录
    * @exception java.sql.SQLException 异常说明。
    */
    void pageFirst() throws java.sql.SQLException;
    /**
    * 转到当前页的最后一条记录
    * @exception java.sql.SQLException 异常说明。
    */
    void pageLast() throws java.sql.SQLException;
    /**返回当前页号
    */
    int getCurPage();
    }
    这是一个对java.sql.ResultSet进行了扩展的接口,主要是增加了对分页的支持,如设置分页大小,跳转到某一页,返回总页数等等。
    接着,我们需要实现这个接口,由于这个接口继承自ResultSet,并且它的大部分功能也都和ResultSet原有功能相同,所以这里使用了一个简单的Decorator模式。
    PageableResultSet2的类声明和成员声明如下:
    public class PageableResultSet2 implements Pageable {
    protected java.sql.ResultSet rs=null;
    protected int rowsCount;
    protected int pageSize;
    protected int curPage;
    protected String command = "";
    }
    可以看到,在PageableResultSet2中,包含了一个ResultSet的实例(这个实例只是实现了ResultSet接口,事实上它是由各个数据库厂商分别实现的),并且把所有由ResultSet继承来的方法都直接转发给该实例来处理。
    PageableResultSet2中继承自ResultSet的主要方法:
    //……
    public boolean next() throws SQLException {
    return rs.next();
    }
    //……
    public String getString(String columnName) throws SQLException {
    try {
    return rs.getString(columnName);
    }
    catch (SQLException e) {//这里是为了增加一些出错信息的内容便于调试
    throw new SQLException (e.toString()+" columnName="
    +columnName+" SQL="+this.getCommand());
    }
    }
    //……
    只有在Pageable接口中新增的方法才需要自己的写方法处理。
    /**方法注释可参考Pageable.java
    */
    public int getCurPage() {
    return curPage;
    }
    public int getPageCount() {
    if(rowsCount==0) return 0;
    if(pageSize==0) return 1;
    //calculate PageCount
    double tmpD=(double)rowsCount/pageSize;
    int tmpI=(int)tmpD;
    if(tmpD>tmpI) tmpI++;
    return tmpI;
    }
    public int getPageRowsCount() {
    if(pageSize==0) return rowsCount;
    if(getRowsCount()==0) return 0;
    if(curPage!=getPageCount()) return pageSize;
    return rowsCount-(getPageCount()-1)*pageSize;
    }
    public int getPageSize() {
    return pageSize;
    }
    public int getRowsCount() {
    return rowsCount;
    }
    public void gotoPage(int page) {
    if (rs == null)
    return;
    if (page < 1)
    page = 1;
    if (page > getPageCount())
    page = getPageCount();
    int row = (page - 1) * pageSize + 1;
    try {
    rs.absolute(row);
    curPage = page;
    }
    catch (java.sql.SQLException e) {
    }
    }
    public void pageFirst() throws java.sql.SQLException {
    int row=(curPage-1)*pageSize+1;
    rs.absolute(row);
    }
    public void pageLast() throws java.sql.SQLException {
    int row=(curPage-1)*pageSize+getPageRowsCount();
    rs.absolute(row);
    }
    public void setPageSize(int pageSize) {
    if(pageSize>=0){
    this.pageSize=pageSize;
    curPage=1;
    }
    }
    PageableResultSet2的构造方法:
    public PageableResultSet2(java.sql.ResultSet rs) throws java.sql.SQLException {
    if(rs==null) throw new SQLException("given ResultSet is NULL","user");

    rs.last();
    rowsCount=rs.getRow();
    rs.beforeFirst();

    this.rs=rs;
    }
    这里只是简单的取得一个总记录数,并将记录游标移回初始位置(before first),同时将参数中的ResultSet赋给成员变量。

    Pageable的使用方法
    因为Pageable接口继承自ResultSet,所以在使用方法上与ResultSet一致,尤其是在不需要分页功能的时候,可以直接当成ResultSet使用。而在需要分页时,只需要简单的setPageSize, gotoPage,即可。
    PreparedStatement pstmt=null;
    Pageable rs=null;
    ……//构造SQL,并准备一个pstmt.
    rs=new PageableResultSet2(pstmt.executeQuery());//构造一个Pageable
    rs.setPageSize(20);//每页20个记录
    rs.gotoPage(2);//跳转到第2页
    for(int i=0; i<rs.getPageRowsCount(); i++){//循环处理
    int id=rs.getInt(“ID”);
    ……//继续处理
    }

    总结
    一个好的基础类应该是便于使用,并且具备足够的可移植性,同时要保证其功能的完善。在上面的实现中,我们从java.sql.ResultSet接口继承出Pageable,并实现了它。这就保证了在使用中与JDBC原有操作的一致性,同时对原有功能没有缩减。
    同时它也是易于使用的,因为封装了一切必要的操作,所以在你的代码中唯一显得"难看"和"不舒服"的地方就是需要自己去构造一个PageableResultSet2。不过只要你愿意,这也是可以解决的。
    当然它也有具有充分的可移植性,当你将数据库由Oracle变为Mysql或者SQLServer的时候,你仍然可以使用这些分页的代码。它在使用中(或者说在移植的过程中)唯一的*就是你必须要使用一个支持JDBC2的驱动(现在明白为什么我把类命名为PageableResultSet2了吧。:P),不过,好在JDBC2已经成为标准了,绝大多数的数据库(如Oracle, Mysql, SQLServer)都有自己的或者第三方提供的JDBC2的驱动。
    OK,这个分页的实现是否对你的编程有帮助呢?仔细看看,其实真正自己写的代码并不多的,大部分都只是简单的转发操作。一个合适的模式应用可以帮你很大忙。

    分页显示怎么使用

    目前最好的JSP分页技术

    在使用数据库的过程中,不可避免的需要使用到分页的功能,可是JDBC的规范对此却没有很好的解决。对于这个需求很多朋友都有自己的解决方案,比如使用Vector等集合类先保存取出的数据再分页。但这种方法的可用性很差,与JDBC本身的接口完全不同,对不同类型的字段的支持也不好。这里提供了一种与JDBC兼容性非常好的方案。
    JDBC和分页
    Sun的JDBC规范的制定,有时很让人哭笑不得,在JDBC1.0中,对于一个结果集(ResultSet)你甚至只能执行next()操作,而无法让其向后滚动,这就直接导致在只执行一次SQL查询的情况下无法获得结果集的大小。所以,如果你使用的是JDBC1.0的驱动,那么是几乎无法实现分页的。
    好在Sun的JDBC2规范中很好的弥补了这一个不足,增加了结果集的前后滚动操作,虽然仍然不能直接支持分页,但我们已经可以在这个基础上写出自己的可支持分页的ResultSet了。

    和具体数据库相关的实现方法
    有一些数据库,如Mysql, Oracle等有自己的分页方法,比如Mysql可以使用limit子句,Oracle可以使用ROWNUM来*结果集的大小和起始位置。这里以Mysql为例,其典型代码如下:
    // 计算总的记录条数
    String SQL = "SELECT Count(*) AS total " + this.QueryPart;
    rs = db.executeQuery(SQL);
    if (rs.next())
    Total = rs.getInt(1);
    // 设置当前页数和总页数
    TPages = (int)Math.ceil((double)this.Total/this.MaxLine);
    CPages = (int)Math.floor((double)Offset/this.MaxLine+1);
    // 根据条件判断,取出所需记录
    if (Total > 0) {
    SQL = Query + " LIMIT " + Offset + " , " + MaxLine;
    rs = db.executeQuery(SQL);
    }
    return rs;
    }
    毫无疑问,这段代码在数据库是Mysql时将会是漂亮的,但是作为一个通用的类(事实上我后面要提供的就是一个通用类库中的一部分),需要适应不同的数据库,而基于这个类(库)的应用,也可能使用不同的数据库,所以,我们将不使用这种方法。

    另一种繁琐的实现方法
    我看过一些人的做法(事实上包括我在内,一开始也是使用这种方法的),即不使用任何封装,在需要分页的地方,直接操作ResultSet滚到相应的位置,再读取相应数量的记录。其典型代码如下:
    <%
    sqlStmt = sqlCon.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,
    java.sql.ResultSet.CONCUR_READ_ONLY);
    strSQL = "select name,age from test";
    //执行SQL语句并获取结果集
    sqlRst = sqlStmt.executeQuery(strSQL);
    //获取记录总数
    sqlRst.last();
    intRowCount = sqlRst.getRow();
    //记算总页数
    intPageCount = (intRowCount+intPageSize-1) / intPageSize;
    //调整待显示的页码
    if(intPage>intPageCount) intPage = intPageCount;
    %>
    <table border="1" cellspacing="0" cellpadding="0">
    <tr>
    <th>姓名</th>
    <th>年龄</th>
    </tr>
    <%
    if(intPageCount>0){
    //将记录指针定位到待显示页的第一条记录上
    sqlRst.absolute((intPage-1) * intPageSize + 1);
    //显示数据
    i = 0;
    while(i<intPageSize && !sqlRst.isAfterLast()){
    %>
    <tr>
    <td><%=sqlRst.getString(1)%></td>
    <td><%=sqlRst.getString(2)%></td>
    </tr>
    <%
    sqlRst.next();
    i++;
    }
    }
    %>
    </table>
    很显然,这种方法没有考虑到代码重用的问题,不仅代码数量巨大,而且在代码需要修改的情况下,将会无所适从。

    使用Vector进行分页
    还见过另一些实现分页的类,是先将所有记录都select出来,然后将ResultSet中的数据都get出来,存入Vector等集合类中,再根据所需分页的大小,页数,定位到相应的位置,读取数据。或者先使用前面提到的两种分页方法,取得所需的页面之后,再存入Vector中。
    扔开代码的效率不说,单是从程序结构和使用的方便性上讲,就是很糟糕的。比如,这种做法支持的字段类型有限,int, double, String类型还比较好处理,如果碰到Blob, Text等类型,实现起来就很麻烦了。这是一种更不可取的方案。

    一个新的Pageable接口及其实现
    很显然,看过上面三种实现方法后,我们对新的分页机制有了一个目标,即:不与具体数据库相关;尽可能做到代码重用;尽可能与原JDBC接口的使用方法保持一致;尽可能高的效率。
    首先,我们需要提供一个与java.sql.ResultSet向下兼容的接口,把它命名为Pageable,接口定义如下:
    public interface Pageable extends java.sql.ResultSet{
    /**返回总页数
    */
    int getPageCount();
    /**返回当前页的记录条数
    */
    int getPageRowsCount();
    /**返回分页大小
    */
    int getPageSize();
    /**转到指定页
    */
    void gotoPage(int page) ;
    /**设置分页大小
    */
    void setPageSize(int pageSize);
    /**返回总记录行数
    */
    int getRowsCount();
    /**
    * 转到当前页的第一条记录
    * @exception java.sql.SQLException 异常说明。
    */
    void pageFirst() throws java.sql.SQLException;
    /**
    * 转到当前页的最后一条记录
    * @exception java.sql.SQLException 异常说明。
    */
    void pageLast() throws java.sql.SQLException;
    /**返回当前页号
    */
    int getCurPage();
    }
    这是一个对java.sql.ResultSet进行了扩展的接口,主要是增加了对分页的支持,如设置分页大小,跳转到某一页,返回总页数等等。
    接着,我们需要实现这个接口,由于这个接口继承自ResultSet,并且它的大部分功能也都和ResultSet原有功能相同,所以这里使用了一个简单的Decorator模式。
    PageableResultSet2的类声明和成员声明如下:
    public class PageableResultSet2 implements Pageable {
    protected java.sql.ResultSet rs=null;
    protected int rowsCount;
    protected int pageSize;
    protected int curPage;
    protected String command = "";
    }
    可以看到,在PageableResultSet2中,包含了一个ResultSet的实例(这个实例只是实现了ResultSet接口,事实上它是由各个数据库厂商分别实现的),并且把所有由ResultSet继承来的方法都直接转发给该实例来处理。
    PageableResultSet2中继承自ResultSet的主要方法:
    //……
    public boolean next() throws SQLException {
    return rs.next();
    }
    //……
    public String getString(String columnName) throws SQLException {
    try {
    return rs.getString(columnName);
    }
    catch (SQLException e) {//这里是为了增加一些出错信息的内容便于调试
    throw new SQLException (e.toString()+" columnName="
    +columnName+" SQL="+this.getCommand());
    }
    }
    //……
    只有在Pageable接口中新增的方法才需要自己的写方法处理。
    /**方法注释可参考Pageable.java
    */
    public int getCurPage() {
    return curPage;
    }
    public int getPageCount() {
    if(rowsCount==0) return 0;
    if(pageSize==0) return 1;
    //calculate PageCount
    double tmpD=(double)rowsCount/pageSize;
    int tmpI=(int)tmpD;
    if(tmpD>tmpI) tmpI++;
    return tmpI;
    }
    public int getPageRowsCount() {
    if(pageSize==0) return rowsCount;
    if(getRowsCount()==0) return 0;
    if(curPage!=getPageCount()) return pageSize;
    return rowsCount-(getPageCount()-1)*pageSize;
    }
    public int getPageSize() {
    return pageSize;
    }
    public int getRowsCount() {
    return rowsCount;
    }
    public void gotoPage(int page) {
    if (rs == null)
    return;
    if (page < 1)
    page = 1;
    if (page > getPageCount())
    page = getPageCount();
    int row = (page - 1) * pageSize + 1;
    try {
    rs.absolute(row);
    curPage = page;
    }
    catch (java.sql.SQLException e) {
    }
    }
    public void pageFirst() throws java.sql.SQLException {
    int row=(curPage-1)*pageSize+1;
    rs.absolute(row);
    }
    public void pageLast() throws java.sql.SQLException {
    int row=(curPage-1)*pageSize+getPageRowsCount();
    rs.absolute(row);
    }
    public void setPageSize(int pageSize) {
    if(pageSize>=0){
    this.pageSize=pageSize;
    curPage=1;
    }
    }
    PageableResultSet2的构造方法:
    public PageableResultSet2(java.sql.ResultSet rs) throws java.sql.SQLException {
    if(rs==null) throw new SQLException("given ResultSet is NULL","user");

    rs.last();
    rowsCount=rs.getRow();
    rs.beforeFirst();

    this.rs=rs;
    }
    这里只是简单的取得一个总记录数,并将记录游标移回初始位置(before first),同时将参数中的ResultSet赋给成员变量。

    Pageable的使用方法
    因为Pageable接口继承自ResultSet,所以在使用方法上与ResultSet一致,尤其是在不需要分页功能的时候,可以直接当成ResultSet使用。而在需要分页时,只需要简单的setPageSize, gotoPage,即可。
    PreparedStatement pstmt=null;
    Pageable rs=null;
    ……//构造SQL,并准备一个pstmt.
    rs=new PageableResultSet2(pstmt.executeQuery());//构造一个Pageable
    rs.setPageSize(20);//每页20个记录
    rs.gotoPage(2);//跳转到第2页
    for(int i=0; i<rs.getPageRowsCount(); i++){//循环处理
    int id=rs.getInt(“ID”);
    ……//继续处理
    }

    总结
    一个好的基础类应该是便于使用,并且具备足够的可移植性,同时要保证其功能的完善。在上面的实现中,我们从java.sql.ResultSet接口继承出Pageable,并实现了它。这就保证了在使用中与JDBC原有操作的一致性,同时对原有功能没有缩减。
    同时它也是易于使用的,因为封装了一切必要的操作,所以在你的代码中唯一显得"难看"和"不舒服"的地方就是需要自己去构造一个PageableResultSet2。不过只要你愿意,这也是可以解决的。
    当然它也有具有充分的可移植性,当你将数据库由Oracle变为Mysql或者SQLServer的时候,你仍然可以使用这些分页的代码。它在使用中(或者说在移植的过程中)唯一的*就是你必须要使用一个支持JDBC2的驱动(现在明白为什么我把类命名为PageableResultSet2了吧。:P),不过,好在JDBC2已经成为标准了,绝大多数的数据库(如Oracle, Mysql, SQLServer)都有自己的或者第三方提供的JDBC2的驱动。
    OK,这个分页的实现是否对你的编程有帮助呢?仔细看看,其实真正自己写的代码并不多的,大部分都只是简单的转发操作。一个合适的模式应用可以帮你很大忙。

    mysqldump导出的表使用mysqlimport恢复提示data too long

    可能是编码问题。
    1. 建数据库
    Microsoft Windows XP [版本 5.1.2600]
    (C) 版权所有 1985-2001 Microsoft Corp.
    C:\Documents and Settings\awish>mysql -u root -p
    Enter password: *******
    Welcome to the MySQL monitor. Commands end with ; or \g.
    Your MySQL connection id is 24 to server version: 5.0.27-community-nt
    Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
    mysql> create database test;
    2. 设置数据编码为utf8
    mysql> use test;
    Database changed
    mysql> set names utf8; //设置数据库字符集为utf8
    Query OK, 0 rows affected (0.00 sec)
    3. 创建数据表
    mysql> CREATE TABLE person
    -> (
    -> id INT(8) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> name varchar(16) default 'nobody',
    -> birthday char(19),
    -> )ENGINE=InnoDB DEFAULT CHARSET=utf8//创建数据表,字符集设定为utf8
    -> ;
    Query OK, 0 rows affected (0.03 sec)
    4. 创建导入SQL脚本文件 c:\test.sql
    use test;
    insert into person values(null, '张三', '1984-08-20');
    insert into person values(null, '李四', '1984-08-20');
    insert into person values(null, '王五', '1984-08-20');
    5. 导入SQL脚本文件
    Microsoft Windows XP [版本 5.1.2600]
    (C) 版权所有 1985-2001 Microsoft Corp.
    C:\Documents and Settings\awish>mysql -u root -p test<C:\test.sql
    Enter password: *******
    ERROR 1406 (22001) at line 3: Data too long for column 'name' at row 1
    C:\Documents and Settings\awish>
    分析: 很明显, 张三, 李四, 王五 只有4个字节, 而建表时定义最多可以有15个, 理论下完全可以, 为什么 too long 呢? 唯一的解释就是编码问题!!!!
    若把上面SQL脚本改为: insert into person values(null, 'aaaaaaaaaaaaaa', '1984-08-20'); 却可以正常插入!!
    后来找资料发现, MySQL的默认编码为 gb2312

    在 test.sql 脚本中加入: set names gb2312 问题解决
    use test;
    set names gb2312;
    insert into parent values(null, '张三', '1984-08-20');
    insert into parent values(null, '李四', '1984-08-20');
    insert into parent values(null, '王五', '1984-08-20');
    导入命令:
    C:\Documents and Settings\awish>mysql -u root -p test<C:\test.sql
    Enter password: *******
    C:\Documents and Settings\awish>
    导入成功!!!
    6. 查询数据
    C:\Documents and Settings\awish>mysql -u root -p test
    Enter password: *******
    Welcome to the MySQL monitor. Commands end with ; or \g.
    Your MySQL connection id is 27 to server version: 5.0.27-community-nt
    Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
    mysql> use test;
    Database changed
    mysql> select * from person;
    +----+--------+------------+
    | id | name | birthday |
    +----+--------+------------+
    | 1 | 寮犱笁 | 1984-08-20 |
    | 2 | 鏉庡洓 | 1984-08-20 |
    | 3 | 鐜嬩簲 | 1984-08-20 |
    +----+--------+------------+
    3 rows in set (0.00 sec)
    mysql>
    由于中文字符编码为 utf8 后, 人是不认得了, 我们可以导出看其效果!
    7. 导出数据库
    Microsoft Windows XP [版本 5.1.2600]
    (C) 版权所有 1985-2001 Microsoft Corp.
    C:\Documents and Settings\awish>mysqlmp -u root -p test>c:\test2.sql
    Enter password: *******
    C:\Documents and Settings\awish>
    我们把它存为 C:\test2.sql
    打开test2.sql 脚本文件, 我们将会看到:
    --
    -- Table structure for table `person`
    --
    DROP TABLE IF EXISTS `person`;
    CREATE TABLE `person` (
    `id` int(10) unsigned NOT NULL auto_increment,
    `name` varchar(16) default 'nobody',
    `birthday` char(19) default NULL,
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    --
    -- Dumping data for table `person`
    --
    LOCK TABLES `person` WRITE;
    /*!40000 ALTER TABLE `person` DISABLE KEYS */;
    INSERT INTO `person` VALUES (1,'张三','1984-08-20'),(2,'李四','1984-08-20'),(3,'王五','1984-08-20');
    /*!40000 ALTER TABLE `person` ENABLE KEYS */;
    UNLOCK TABLES;
    数据完全正确!!
    这时如果要想把 test2.sql文件导入到数据库中, 按照上面的, 加上: set names gb2312

    mysqldump导出的表使用mysqlimport恢复提示data too long

    可能是编码问题。
    1. 建数据库
    Microsoft Windows XP [版本 5.1.2600]
    (C) 版权所有 1985-2001 Microsoft Corp.
    C:\Documents and Settings\awish>mysql -u root -p
    Enter password: *******
    Welcome to the MySQL monitor. Commands end with ; or \g.
    Your MySQL connection id is 24 to server version: 5.0.27-community-nt
    Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
    mysql> create database test;
    2. 设置数据编码为utf8
    mysql> use test;
    Database changed
    mysql> set names utf8; //设置数据库字符集为utf8
    Query OK, 0 rows affected (0.00 sec)
    3. 创建数据表
    mysql> CREATE TABLE person
    -> (
    -> id INT(8) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> name varchar(16) default 'nobody',
    -> birthday char(19),
    -> )ENGINE=InnoDB DEFAULT CHARSET=utf8//创建数据表,字符集设定为utf8
    -> ;
    Query OK, 0 rows affected (0.03 sec)
    4. 创建导入SQL脚本文件 c:\test.sql
    use test;
    insert into person values(null, '张三', '1984-08-20');
    insert into person values(null, '李四', '1984-08-20');
    insert into person values(null, '王五', '1984-08-20');
    5. 导入SQL脚本文件
    Microsoft Windows XP [版本 5.1.2600]
    (C) 版权所有 1985-2001 Microsoft Corp.
    C:\Documents and Settings\awish>mysql -u root -p test<C:\test.sql
    Enter password: *******
    ERROR 1406 (22001) at line 3: Data too long for column 'name' at row 1
    C:\Documents and Settings\awish>
    分析: 很明显, 张三, 李四, 王五 只有4个字节, 而建表时定义最多可以有15个, 理论下完全可以, 为什么 too long 呢? 唯一的解释就是编码问题!!!!
    若把上面SQL脚本改为: insert into person values(null, 'aaaaaaaaaaaaaa', '1984-08-20'); 却可以正常插入!!
    后来找资料发现, MySQL的默认编码为 gb2312

    在 test.sql 脚本中加入: set names gb2312 问题解决
    use test;
    set names gb2312;
    insert into parent values(null, '张三', '1984-08-20');
    insert into parent values(null, '李四', '1984-08-20');
    insert into parent values(null, '王五', '1984-08-20');
    导入命令:
    C:\Documents and Settings\awish>mysql -u root -p test<C:\test.sql
    Enter password: *******
    C:\Documents and Settings\awish>
    导入成功!!!
    6. 查询数据
    C:\Documents and Settings\awish>mysql -u root -p test
    Enter password: *******
    Welcome to the MySQL monitor. Commands end with ; or \g.
    Your MySQL connection id is 27 to server version: 5.0.27-community-nt
    Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
    mysql> use test;
    Database changed
    mysql> select * from person;
    +----+--------+------------+
    | id | name | birthday |
    +----+--------+------------+
    | 1 | 寮犱笁 | 1984-08-20 |
    | 2 | 鏉庡洓 | 1984-08-20 |
    | 3 | 鐜嬩簲 | 1984-08-20 |
    +----+--------+------------+
    3 rows in set (0.00 sec)
    mysql>
    由于中文字符编码为 utf8 后, 人是不认得了, 我们可以导出看其效果!
    7. 导出数据库
    Microsoft Windows XP [版本 5.1.2600]
    (C) 版权所有 1985-2001 Microsoft Corp.
    C:\Documents and Settings\awish>mysqlmp -u root -p test>c:\test2.sql
    Enter password: *******
    C:\Documents and Settings\awish>
    我们把它存为 C:\test2.sql
    打开test2.sql 脚本文件, 我们将会看到:
    --
    -- Table structure for table `person`
    --
    DROP TABLE IF EXISTS `person`;
    CREATE TABLE `person` (
    `id` int(10) unsigned NOT NULL auto_increment,
    `name` varchar(16) default 'nobody',
    `birthday` char(19) default NULL,
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    --
    -- Dumping data for table `person`
    --
    LOCK TABLES `person` WRITE;
    /*!40000 ALTER TABLE `person` DISABLE KEYS */;
    INSERT INTO `person` VALUES (1,'张三','1984-08-20'),(2,'李四','1984-08-20'),(3,'王五','1984-08-20');
    /*!40000 ALTER TABLE `person` ENABLE KEYS */;
    UNLOCK TABLES;
    数据完全正确!!
    这时如果要想把 test2.sql文件导入到数据库中, 按照上面的, 加上: set names gb2312

    显示全文