月度归档:2013年06月

Java 理论与实践: 哈希

来源:http://www.ibm.com/developerworks/cn/java/j-jtp08223/

虽然Java语言不直接支持关联数组 -- 可以使用任何对象作为一个索引的数组 -- 但在根 Object 类中使用 hashCode() 方法明确表示期望广泛使用 HashMap (及其前辈 Hashtable )。理想情况下基于散列的容器提供有效插入和有效检索;直接在对象模式中支持散列可以促进基于散列的容器的开发和使用。

定义对象的相等性

Object 类有两种方法来推断对象的标识: equals()hashCode() 。一般来说,如果您 Override 了其中一种,您必须同时 Override 这两种,因为两者之间有必须维持的至关重要的关系。特殊情况是根据 equals() 方法,如果两个对象是相等的,它们必须有相同的 hashCode() 值(尽管这通常不是真的)。

特定类的 equals() 的语义在Implementer的左侧定义;定义对特定类来说 equals() 意味着什么是其设计工作的一部分。 Object 提供的缺省实施简单引用下面等式:

  public boolean equals(Object obj) { return (this == obj); }

 

在这种缺省实施情况下,只有它们引用真正同一个对象时这两个引用才是相等的。同样, Object 提供的 hashCode() 的缺省实施通过将对象的内存地址对映于一个整数值来生成。由于在某些架构上,地址空间大于 int 值的范围,两个不同的对象有相同的 hashCode() 是可能的。如果您 Override 了 hashCode() ,您仍旧可以使用 System.identityHashCode() 方法来接入这类缺省值。

Override equals() -- 简单实例

缺省情况下, equals()hashCode() 基于标识的实施是合理的,但对于某些类来说,它们希望放宽等式的定义。例如, Integer 类定义 equals() 与下面类似:

  public boolean equals(Object obj) {
    return (obj instanceof Integer 
            && intValue() == ((Integer) obj).intValue());
  }

 

在这个定义中,只有在包含相同的整数值的情况下这两个 Integer 对象是相等的。结合将不可修改的 Integer ,这使得使用 Integer 作为 HashMap 中的关键字是切实可行的。这种基于值的Equal方法可以由Java类库中的所有原始封装类使用,如 IntegerFloatCharacterBoolean 以及 String (如果两个 String 对象包含相同顺序的字符,那它们是相等的)。由于这些类都是不可修改的并且可以实施 hashCode()equals() ,它们都可以做为很好的散列关键字。

为什么 Override equals()和hashCode()?

如果 Integer 不 Override equals()hashCode() 情况又将如何?如果我们从未在 HashMap 或其它基于散列的集合中使用 Integer 作为关键字的话,什么也不会发生。但是,如果我们在 HashMap中 使用这类 Integer 对象作为关键字,我们将不能够可靠地检索相关的值,除非我们在 get() 调用中使用与 put() 调用中极其类似的 Integer 实例。这要求确保在我们的整个程序中,只能使用对应于特定整数值的 Integer 对象的一个实例。不用说,这种方法极不方便而且错误频频。

Object 的interface contract要求如果根据 equals() 两个对象是相等的,那么它们必须有相同的 hashCode() 值。当其识别能力整个包含在 equals() 中时,为什么我们的根对象类需要 hashCode()hashCode() 方法纯粹用于提高效率。Java平台设计人员预计到了典型Java应用程序中基于散列的集合类(Collection Class)的重要性--如 HashtableHashMapHashSet ,并且使用 equals() 与许多对象进行比较在计算方面非常昂贵。使所有Java对象都能够支持 hashCode() 并结合使用基于散列的集合,可以实现有效的存储和检索。

 

实施equals()和hashCode()的需求

实施 equals()hashCode() 有一些限制, Object 文件中列举出了这些限制。特别是 equals() 方法必须显示以下属性:

  • Symmetry:两个引用, ab , a.equals(b) if and only if b.equals(a)
  • Reflexivity:所有非空引用, a.equals(a)
  • Transitivity:If a.equals(b) and b.equals(c) , then a.equals(c)
  • Consistency with hashCode() :两个相等的对象必须有相同的 hashCode()

Object 的规范中并没有明确要求 equals()hashCode() 必须 一致-- 它们的结果在随后的调用中将是相同的,假设“不改变对象相等性比较中使用的任何信息。”这听起来象“计算的结果将不改变,除非实际情况如此。”这一模糊声明通常解释为相等性和散列值计算应是对象的可确定性功能,而不是其它。

 

对象相等性意味着什么?

人们很容易满足Object类规范对 equals()hashCode() 的要求。决定是否和如何 Override equals() 除了判断以外,还要求其它。在简单的不可修值类中,如 Integer (事实上是几乎所有不可修改的类),选择相当明显 -- 相等性应基于基本对象状态的相等性。在 Integer 情况下,对象的唯一状态是基本的整数值。

对于可修改对象来说,答案并不总是如此清楚。 equals()hashCode() 是否应基于对象的标识(象缺省实施)或对象的状态(象Integer和String)?没有简单的答案 -- 它取决于类的计划使用。对于象 ListMap 这样的容器来说,人们对此争论不已。Java类库中的大多数类,包括容器类,错误出现在根据对象状态来提供 equals()hashCode() 实施。

如果对象的 hashCode() 值可以基于其状态进行更改,那么当使用这类对象作为基于散列的集合中的关键字时我们必须注意,确保当它们用于作为散列关键字时,我们并不允许更改它们的状 态。所有基于散列的集合假设,当对象的散列值用于作为集合中的关键字时它不会改变。如果当关键字在集合中时它的散列代码被更改,那么将产生一些不可预测和 容易混淆的结果。实践过程中这通常不是问题 -- 我们并不经常使用象 List 这样的可修改对象做为 HashMap 中的关键字。

一个简单的可修改类的例子是Point,它根据状态来定义 equals()hashCode() 。如果两个 Point 对象引用相同的 (x, y) 座标, Point 的散列值来源于 xy 座标值的IEEE 754-bit表示,那么它们是相等的。

对于比较复杂的类来说, equals()hashCode() 的行为可能甚至受到superclass或interface的影响。例如, List 接口要求如果并且只有另一个对象是 List, 而且它们有相同顺序的相同的Elements(由Element上的 Object.equals() 定义), List 对象等于另一个对象。 hashCode() 的需求更特殊--list的 hashCode() 值必须符合以下计算:

  hashCode = 1;
  Iterator i = list.iterator();
  while (i.hasNext()) {
      Object obj = i.next();
      hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
  }

 

不仅仅散列值取决于list的内容,而且还规定了结合各个Element的散列值的特殊算法。( String 类规定类似的算法用于计算 String 的散列值。)

 

编写自己的equals()和hashCode()方法

Override 缺省的 equals() 方法比较简单,但如果不违反对称(Symmetry)或传递性(Transitivity)需求,Override 已经 Override 的 equals() 方法极其棘手。当 Override equals() 时,您应该总是在 equals() 中包括一些Javadoc注释,以帮助那些希望能够正确扩展您的类的用户。

作为一个简单的例子,考虑以下类:

  class A {
    final B someNonNullField;
    C someOtherField;
    int someNonStateField;
  }

 

我们应如何编写该类的 equals() 的方法?这种方法适用于许多情况:

  public boolean equals(Object other) {
    // Not strictly necessary, but often a good optimization
    if (this == other)
      return true;
    if (!(other instanceof A))
      return false;
    A otherA = (A) other;
    return 
      (someNonNullField.equals(otherA.someNonNullField))
        && ((someOtherField == null) 
            ? otherA.someOtherField == null 
            : someOtherField.equals(otherA.someOtherField)));
  }

 

现在我们定义了 equals() ,我们必须以统一的方法来定义 hashCode() 。一种统一但并不总是有效的定义 hashCode() 的方法如下:

  public int hashCode() { return 0; }

 

这种方法将生成大量的条目并显著降低 HashMap s的性能,但它符合规范。一个更合理的 hashCode() 实施应该是这样:

  public int hashCode() { 
    int hash = 1;
    hash = hash * 31 + someNonNullField.hashCode();
    hash = hash * 31 
                + (someOtherField == null ? 0 : someOtherField.hashCode());
    return hash;
  }

 

注意:这两种实施都降低了类状态字段的 equals()hashCode() 方法一定比例的计算能力。根据您使用的类,您可能希望降低superclass的 equals()hashCode() 功能一部分计算能力。对于原始字段来说,在相关的封装类中有helper功能,可以帮助创建散列值,如 Float.floatToIntBits

编写一个完美的 equals() 方法是不现实的。通常,当扩展一个自身 Override 了 equals() 的instantiable类时,Override equals() 是不切实际的,而且编写将被 Override 的 equals() 方法(如在抽象类中)不同于为具体类编写 equals() 方法。关于实例以及说明的更详细信息请参阅 Effective Java Programming Language Guide, Item 7 ( 参考资料) 。

 

有待改进?

将散列法构建到Java类库的根对象类中是一种非常明智的设计折衷方法 -- 它使使用基于散列的容器变得如此简单和高效。但是,人们对Java类库中的散列算法和对象相等性的方法和实施提出了许多批评。 java.util 中基于散列的容器非常方便和简便易用,但可能不适用于需要非常高性能的应用程序。虽然其中大部分将不会改变,但当您设计严重依赖于基于散列的容器效率的应用程序时必须考虑这些因素,它们包括:

  • 太小的散列范围。使用 int 而不是 long 作为 hashCode() 的返回类型增加了散列冲突的几率。
  • 糟糕的散列值分配。短strings和小型integers的散列值是它们自己的小整数,接近于其它“邻近”对象的散列值。一个循规导矩(Well-behaved)的散列函数将在该散列范围内更均匀地分配散列值。
  • 无定义的散列操作。虽然某些类,如 StringList ,定义了将其Element的散列值结合到一个散列值中使用的散列算法,但语言规范不定义将多个对象的散列值结合到新散列值中的任何批准的方法。我们在前面 编写自己的equals()和hashCode()方法中讨论的 ListString 或实例类 A 使用的诀窍都很简单,但算术上还远远不够完美。类库不提供任何散列算法的方便实施,它可以简化更先进的 hashCode() 实施的创建。
  • 当扩展已经 Override 了 equals() 的 instantiable类时很难编写 equals() 。当扩展已经 Override 了 equals() 的 instantiable类时,定义 equals() 的“显而易见的”方式都不能满足 equals() 方法的对称或传递性需求。这意味着当 Override equals() 时,您必须了解您正在扩展的类的结构和实施详细信息,甚至需要暴露基本类中的机密字段,它违反了面向对象的设计的原则。

 

结束语

通过统一定义 equals()hashCode(), 您可以提升类作为基于散列的集合中的关键字的使用性。有两种方法来定义对象的相等性和散列值:基于标识,它是 Object 提供的缺省方法;基于状态,它要求 Override equals()hashCode() 。当对象的状态更改时如果对象的散列值发生变化,确信当状态作为散列关键字使用时您不允许更更改其状态。

参考文章
java大型HashMap评估:JDK、FastUtil、Goldman Sachs、HPPC、Koloboke与Trove
Java 理论与实践: 构建一个更好的 HashMap
集合框架 Map篇(4)—-ConcurrentHashMap
集合框架 Map篇(1)—-HashMap、LinkedHashMap、IdentityHashMap
Java集合框架之fastutil
Java 理论与实践: 哈希
通过分析 JDK 源代码研究 Hash 存储机制

 

用户体验测试

来源:互联网

1首页可用性设计

[确保用户打开首页的可用性良好,能够明白该如何操作。]

1. 首页元素要清晰的关注用户的关键任务(避免“增加功能倾向”)

2. 如果网站比较大,那么首页应包含搜索输入框

3. 首页要十分清楚的提供产品(内容)分类

4. 信息展示时应当是简单的、自然的、符合逻辑顺序的

5. 在首页展示真实网站内容的优秀示例

6. 首页上的链接简洁明确

7. 在首页提供一个最近的特色项列表,并提供存档内容的链接

8. 首页导航不要过度修饰,确保用户不会把它误认为广告

9. 在首页有清晰的声明价值取向(例如一个标志性的口号或欢迎语)

10. 在首页包含有意义的图案设计,而非无关的剪贴画或绘画作品

11. 导航选项按逻辑性或用户导向方式排序(把次要的公司信息放在底部)

12. 首页标题可以为诸如google等搜索引擎提供良好可见度

13. 所有公司相关信息安排在一个显著区域(例如:“关于我们(About Us)”)

14. 一看到首页,第一次访问的人就知道从何处开始

15. 在首页展示出所有主要的操作选项

16. 首页拥有一个易记的URL

17. 首页需经过专业设计,以给用户良好的第一印象

18. 首页的设计要能激发用户探索站点的兴趣

19. 首页就要像一个首页,不能让用户把它与二级页面混淆

2任务导向测试

1. 网站应避免出现不相干的、多余的或让用户分心的信息

2. 避免过多的使用脚本、小应用程序、视频音频文件、图案和图片

3. 网站应避免不必要的登记

4. 关键人物路径必须是清晰的,无干扰的(例如:购买、捐献)

5. 信息以简单的、自然的、符合逻辑的形式展示

6. 应尽量缩减每个任务需要的屏幕数量

7. 应减量减少页面滚动和点击

8. 网站应正确的预期和提示用户下一步可能的动作

9. 展示图表时,确保用户可以看到真实数据(例如在柱状图上标明数字注解)

10. 当分配给用户任务时,应充分利用计算机的优势(例如搜索输入的自动完成功能)

11. 用户可以快速完成普通任务

12. 当必要时,应为当前任务提供数据对比功能(例如:商品比较)

13. 任务顺序应当与用户日常工作顺序一致

14. 网站可以保证用户的工作比不使用它时更轻松快捷

15. 最重要的或经常使用的主题、特征或功能应放在页面中央附近的位置,而不是特别靠左边或右边

16. 确保用户不会重复输入相同的信息

17. 重要的、频繁使用的主题或任务应接近网站的“表面”

18. 保持最少的录入(例如购买过程中),并为用户提供加速器

19. 任何给定任务路径应当有一个合理的步骤长度(2-5次点击)

20. 当一个任务有多步时,网站要告诉用户完成任务需要的所有步骤,并为用户当前步骤所在的位置提供反馈

21. 在每个产品后面紧跟它的价格

22. 可以非常容易的找到网站的隐私策略,尤其是在那些要求填写个人信息的页面。隐私策略应当是简单的、清晰的

23. 网站用户不需要记住从一个地方到另一个地方的信息

24. 隐喻的使用可以被典型用户轻松理解

25. 数据格式应当遵循文化常规

26. 软件的内部工作细节不要暴露给用户

27. 应当迎合用户那些之前已经养成的那些小的互联网习惯

28. 网站应当易于用户浏览,在执行前可以自己尝试其它的功能操作

29. 第一次到访的典型用户应当可以在不需帮助的情况下完成最常用的功能

30. 当用户回到网站时,用户可以记得如何执行主要任务

31. 那些新颖设备的功能应当是显而易见的

32. 在购物车页面,在页面的顶部或底部应当清晰的展示”处理结账”按钮

33. 重要的操作入口(例如“添加到购物车”)应当非常清晰可见

34. 操作按钮(例如“提交”)应当由用户触发,而非在完成所有选项时系统自动触发

35. 命令或操作项应以按钮的形式的展示(而非例如链接)

36. 如果用户在事务处理中中途退出,用户在稍后返回站点时可以继续他退出之前的工作

37. 当页面展示大量信息时,用户可以排序和过滤信息

38. 按钮或图标上的图像应当与内容相关

39. 当用户被系统自动注销时应当提示用户,并且自动注销的时间间隔要恰当

40. 不必要的功能(例如flash动画)可以被关闭或跳过

41. 网站应当是健壮的,并且所有关键功能可正常工作(例如不应有java页面异常、CGI报错或死链接)

42. 网站通过不同程度的说明来支持新手用户和专家用户(例如帮助信息、错误信息)

43. 网站允许用户重新填写一些信息项(例如更改发货地址、更改账户信息)

44. 网站允许用户自定义操作时间参数(例如自动退出的时间)

3导航和信息架构测试

1. 关联页面或区域间的跳转移动应当是方便的、显而易见的,并且可以容易的回到首页

2. 在绝大部分页面都可以轻松的导航至用户最可能需要的信息

3. 导航选项按照最常用逻辑或任务导向方式排序

4. 导航系统应当是内容宽泛并层级较浅的,而非有比较深的层级

5. 站点结构是简单的,有一个清晰的概念模型,没有不必要的层次

6. 在所有页面都可以到达网站主要部分,导航过程不会中断

7. 导航标签放在页面顶端,而且要设计成看上去可以点击的样子

8. 要有一个站点地图用来提供整个站点内容的概况

9. 在任何页面都可以链接到站点地图

10. 站点地图提供一个简洁的网站概貌,而非主要导航的重复或各主题的简单罗列

11. 提供良好的导航反馈(例如显示当前位置)

12. 分类标签应当能准确描述该分类的信息

13. 链接或导航标签包含用户要达到目标所寻找的“触发字眼”

14. 术语和常规(例如链接颜色、字体大小等)应当(近似地)与互联网习惯用法保持一致

15. 在网站各个组成部分中的链接样子应当一致

16. 产品页面应当包含与当前产品相似或互补产品的链接,以实现交叉营销

17. 导航项和链接中的用词应当是无歧义的,并且使用术语

18. 用户可以排序和过滤目录页面(例如按价格排序或最热门排序)

19. 当鼠标放在某个可点击的元素上时,元素应当有明显变化(包括光标的变化)

20. 重要内容可以通过不止一个链接访问到(不同的用户有可能需要不同的链接标签)

21. 仅用于导航的页面(例如首页)可以再不滚动的情况下浏览

22. 触发事件的超链接应当与链接到其它页面的超链接(例如:下载)在外观上有明显区分

23. 在网站每个页面清晰标注退出入口,允许用户从当前任务中退出,而不必通过一 个额外的对话框

24. 网站不可禁用浏览器的“后退”按钮,“后退”按钮应当在每个页面的浏览器工具栏上都有显示

25. 用户点击浏览器后退按钮时,总能回到他之前所在页面

26. 购物车(basket)和结账(checkout)链接应当在每个页面中都可以看的十分清楚

27. 如果网站有打开新窗口,那么这个动作不应使用户困惑(例如:新窗口应该是一个设定大小的对话框或并可以轻松关闭)

28. 菜单的使用说明、提示、相关信息应当在每个屏幕的同一位置显示

4表单和数据输入测试

1. 数据输入框在适当的时候应当包含默认值,显示要填的数据格式和输入框允许输入的长度

2. 如果任务设计有源文件(例如纸张形式的发货单、订单等),那么界面应当与源文件的规格一致

3. 网站能自动完成格式化数据的输入(例如货币符号等),用户不需要输入类似£ 或 %的符号

4. 表单域的标签应当清楚的说明该输入框希望输入什么

5. 表单中的文本框应该为预期答案设定合理长度

6. 表单中的必填项和选填项应当有明显的区分

7. 登陆和注册应当用相同的表单

8. 如果完成表单需要外部信息的话应当提前告知用户(例如证件号等)

9. 表单中的输入框应当按逻辑分组,并且每组都有一个标题

10. 表单域应包含提示、示例或样例答案,告知用户输入框期望输入什么

11. 在表单中,相对于文本输入框,应当优先使用下拉菜单、单选按钮、复选框(文本输入框不应当使用过度)

12. 在数据输入页面,光标应当被放置在需要输入的地方

13. 数据输入(例如日期)和输出(例如数值单位)的格式应当被清晰标明,或者采用控件代替手动输入

14. 用户可以在输入一些基本必要信息就可以完成简单的任务(系统可以默认补充一些不重要的信息)

15. 表单允许用户尽可能久的保持一种简单的交互方式(例如,用户不必在键盘鼠标间不停的切换)

16. 文本输入框需指出要输入数据的数量和格式

17. 表单在提交前执行数据验证

18. 数据输入界面,在适当的时间执行表单域级别验证和表单级别验证

19. 网站应可以轻松地更正输入错误(例如,当验证表单未完成,应当将光标放置在需要输入的位置)

20. 数据输入和数据显示应当保持一致性

21. 表单域标签应当靠近输入域(例如:标签左对齐)

5可信度测试

1. 内容应当是最新的、权威的、可信赖的

2. 网站有第三方(例如引用、第三方使用见证)来说明信息的准确性

3. 公司有一些认证专家(可以使用一些凭证)

4. 网站应避免广告,尤其是弹出式广告

5. 在结账的最一开始就突出提示运送费用

6. 网站应当避免空洞的营销辞令

7. 每个页面都应当清晰显示站点标识,保证用户确认他仍然在同一个网站上

8. 通过网站可以轻松联系到某人以获取帮助,并可尽快得到回复(如在线客服、呼叫中心等)

9. 内容是新鲜的,网站应经常更新,总包含最近的内容

10. 网站应当避免版式错误和拼写错误

11. 用可视化设计来补充商品和线下营销信息

6写作和内容质量测试

1. 网站有能引起别人兴趣的、独一无二的内容

2. 正文是简明的,没有不必要的说明和欢迎辞令

3. 每个内容页应以内容结论或内容意义启示作为开端,正文以倒金字塔方式书写

4. 相对于叙述式的文本,网页应当优先使用无序列表和有序列表

5. 列表应当以简短的说明作为开始,帮助用户意识到该列表是如何与其它关联起来的

6. 那些最重要的列表项应当放在列表的前面

7. 信息应当分层次组织,从一般的到具体的,组织结构应当是清晰的、符合逻辑的

8. 产品展示页面应当包含购买须了解的信息,用户可缩放产品图片

9. 使用超文本适当地组织内容

10. 以主动语态书写语句

11. 网页应当易于快速浏览,充分使用标题、副标题和较短的段落

12. 相对于文本式的语言,优先使用地图、图表、图形、流程图和其它视觉元素

13. 每个网页都应有描述信息,以及有用的标题,用以支持书签

14. 链接及链接描述应当具有描述性或推测性,不应当出现“点击我”这样的链接

15. 标题不应当故作风雅、故作聪明或含义隐晦

16. 链接文本应当与目标页面的标题相符,这样用户就可以在到达目标页面时心里有数

17. 按钮文本及链接文本以动词开头

18. 标题和副标题应当是简短的、直截了当的、具有描述性的

19. 遣词造句及用到的概念应当为典型用户所熟悉

20. 有序列表从1开始,而不是0

21. 第一次使用的缩写词汇应当加以说明

7 页面布局和可视设计测试

1. 布局可以帮助用户把注意力集中在下一步要做的动作上

2. 在所有页面,最重要的信息(例如经常用的主题、特色和功能)放在屏幕的第一个满屏

3. 网站在不水平滚动的情况下就可以使用

4. 可点击的元素(例如按钮),应当设计成明显可点击的样子

5. 按钮或控件的功能从他们的标签或设计上就可以明显看出来

6. 超文本链接可以轻松被辨认(例如下划线),而不需要大面积扫视。

7. 网站字体使用应当具有一致性

8. 控件和它所具备的操作之间的关系是显而易见的

9. 图标和图形是标准的,或直观的(具体的和为人熟悉的)

10. 在每一个页面上都应有一个清晰的视觉“起点”

11. 网站的每个页面共享一致的布局

12. 网页为打印格式化,或者有一个为打印准备的版本

13. 按钮或链接能显示出他们被点击过了

14. 所用字体应当是阅读性强的

15. 网站应当避免使用斜体字,并只为超文本添加下划线

16. 信息密度和留白应当有一个良好的平衡

17. 网站看上去应是让人愉悦的

18. 网页应避免出现“滚动障碍物”(标题或其它页面元素给用户造成在页面顶部或底部的错觉)

19. 网站应当避免大量使用大写文本

20. 网站应当有一致性的、清晰可识别的外观和感觉,以吸引用户

21. 借助颜色来组织和分组页面元素

22. 网站图形不应当与banner广告混杂不清

23. 对于重要的主题分类加重显示

24. 在标准宽度的浏览器窗口中,内容页面一行不要太短(小于50字)也不要太长(大于100字)

25. 页面依据栅格设计,所有页面元素和部件水平对齐、垂直对齐

26. 有意义的文本标签,令人印象深刻的背景配色,边框和留白的恰当使用,这些一起来帮助用户把网页元素分别出不相关联的功能区域

27. 网页配色合理搭配,避免过于复杂的背景设计

28. 较为独立的网页应当避免杂乱不相干的信息

29. 标准页面元素(例如页面标题、站点导航、页面导航、隐私策略等)可轻松找到

30. logo放置在每个页面的相同位置,点击logo后返回最合情理的页面(比如首页)

31. 吸引人注意力的特色元素(例如动画、醒目的色调、明显的字体大小差异)应当保守的使用,并只在恰当的地方使用

32. 图标要在视觉上和概念上有所区分,但又要与页面和谐

33. 相关信息和功能集中放置,每一组可以在一个视野浏览到(大约直径为4.4厘米的屏幕区域)

8搜索可用性

1. 默认搜索应当是可以直观地配置

2. 在搜索结果页面向用户展示搜索到的内容,并且在该页可以编辑检索词并重新提交搜索

3. 检索结果应是清晰地、有用的、并依据相关度分级

4. 检索结果页面应清晰告诉用户检索到多少条记录,每一页显示的记录数可以由用户配置

5. 如果没有返回结果,系统依据用户输入的检索词存在的可辨认问题提供建议和可选输入项

6. 搜索引擎可以优雅地处理空检索串的情况

7. 网站应当包含一个功能更强大的搜索页面,帮助用户更加完善他们的检索(可以把它叫做“高级搜索”)

8. 检索结果页面不显示重复结果

9. 检索输入框应当足够长,可以应对常用检索词的长度

10. 检索应当覆盖整个站点,而不是站点的一部分

11. 如果网站允许用户创建复合检索,那么这些检索应当是可保存,定期被执行的(这样用户就可以跟踪动态信息的最新动态)

12. 检索界面应当放置在用户期望的地方(一般是页面的右上区域)

13. 检索框及他的控件应清晰列出(多检索框可能会难以理解)

14. 在检索结果页面应当明确当前检索的范围,并且用户可以约束这个范围

15. 结果页面显示有用的元信息,例如文档的大小、创建的日期、文件类型(word、pdf等)

9 帮助、反馈和容错测试

1. 常见问题解答或在线帮助提供循序渐进地指导,帮助用户完成最重要的任务

2. 在恰当的地方和恰当的时间可以轻松获取帮助

3. 提示应当是简洁的、表达清楚的

4. 用户不需要求助于用户手册或其它外部信息来使用站点

5. 网站在必要时(例如校验时)提供良好的反馈信息(例如进度提示或一些信息)

6. 用户在执行由潜在“危险”操作(例如删除什么)之前提供用户确认

7. 用户确认页面是清晰的

8. 错误信息包含下一步该做什么的清晰指示

9. 在提交购买的前一个时刻,网站向用户清晰地展示概览页面,这个页面应当与购买确认页面区分开来

10. 当用户需要在不同的选项(例如在一个对话框)前抉择时,这些选项应当是明确的

11. 在网站响应时间时产生的不可避免的延迟应当告知用户(例如授权信用卡交易时)

12. 错误信息以非嘲弄的语气书写,并且不要责怪用户的错误

13. 页面可以快速加载(5秒或更短)

14. 网站提供对用户输入或其他操作的及时反馈

15. 在加载比较慢的大页面应当提示用户(例如:“正在加载……”),最重要的信息应当首先显示

16. 当使用工具提示条(tool tips)时,应当提示对用户有用的额外帮助,而不是简单的重复图标、链接或字段域标签中的文本

17. 当给用户一些帮助提示时,告诉他们要做什么,而不是避免做什么

18. 网站在适当的地方向用户展示如何做常见任务(例如:提供网站的功能示例)

19. 网站通过提供反馈信息(例如“您知道吗?”),帮助用户了解怎样使用网站

20. 网站提供上下文敏感帮助

21. 帮助应当是直截了当的,用直白简单的方式表达,避免使用行话和流行语

22. 当一个任务成功完成后,网站提供清晰地反馈信息

23. 必要时重要提示信息应当在屏幕上保留,使用户有足够时间记录下这些信息

24. 遵循“菲茨法则”(控件之间的距离和控件的大小应当是适宜的,大小与距离成比例)

25. 目标对象间有足够空间,防止用户点击了多个目标或错误的目标

26. 可点击元素之间至少有两个像素的距离

27. 当网站发生错误时,应当是显而易见的(例如,当表单未完成,高亮未完成的表单域)

28. 网站提供适当的选择方式(例如下拉列表)来代替用户输入

29. 网站应努力把防止用户出错的工作做好

30. 网站在纠正用户错误输入前提示用户(例如,google的“您是不是要查找…”)

31. 网站应当确保任务不是令人困惑的

32. 错误信息应当用直白的语言描述,并给与问题足够的解释

33. 用户在一个任务中可以推迟解决错误至一个较晚的时间

34. 如果有必要的话,网站提供错误信息更多的细节

35. 可以非常容易撤销(或取消)、重做(Redo)操作

MySQL slave状态之Seconds_Behind_Master

来源:互联网

在MySQL的主从环境中,我们可以通过在slave上执行show slave status来查看slave的一些状态信息,其中有一个比较重要的参数Seconds_Behind_Master。那么你是否明白它的真正含义以及它是怎么计算的呢?

在之前我一直误以为Seconds_Behind_Master是表示slave比master落后多少,如果这个值为0的表示主从已经处于一致了(在非 同步模式下,现在官方最多也只在5.5中增加了半同步复制)。但是最近我终于认识到之前的错误理解。首先我们需要明白的一 点:Seconds_Behind_Master表示slave上SQL thread与IO thread之间的延迟,我们都知道在MySQL的复制环境中,slave先从master上将binlog拉取到本地(通过IO thread),然后通过SQL thread将binlog重放,而Seconds_Behind_Master表示本地relaylog中未被执行完的那部分的差值。手册上的定义:

In essence, this field measures the time difference in seconds between the slave SQL thread and the slave I/O thread.

所以如果slave拉取到本地的relaylog(实际上就是binlog,只是在slave上习惯称呼relaylog而已)都执行完,此时通过 show slave status看到的会是0,那么Seconds_Behind_Master的值为0是否表示主从已经处于一致了呢?答案几乎是否定的!为什么几乎是否定 的?因为绝大部分的情况下复制都是异步的,异步就意味着master上的binlog不是实时的发送到slave上,所以即使 Seconds_Behind_Master的值为0依然不能肯定主从处于一致,这也是我之前强调非同步复制的原因(现在已经有公司在做同步复制了,比如 网易自己实现了VSR,VirtualSynchronized Replication,由于同步复制性能较差,所以网易再实现同步复制的同时还打了group commit的补丁)。所以如果我们要以这个参数来估计主从延迟多久的话至少得在一个比较好的网络环境中,这样才能保证几乎master上的binlog都已经发送到slave上。

上面解释了Seconds_Behind_Master这个值的真正含义,那么它的值到底是怎么计算出来的呢?实际上在binlog中每个binlog events都会附上执行时的timestamp,所以在在确定Seconds_Behind_Master的值时MySQL是通过比较当前系统的时间戳 与当前SQL thread正在执行的binlog event的上的时间戳做比较,这个差值就是Seconds_Behind_Master的值。也许你会有疑问那要是两台服务器之间的时钟不一致怎么办? 确实会存在这种情况,那么此时这个值的可靠性就不大了,手册上对此也进行了说明:

This time difference computation works even if the master and slave do not have identical clock times, provided that the difference,
computed when the slave I/O thread starts, remains constant from then on. Any changes—including NTP updates—can lead to clock
skews that can make calculation of Seconds_Behind_Master less reliable

Seconds_Behind_Master的值除了是非负数之外还可能是NULL,它是由如下几种情况导致的:SQL thread没运行/IO thread没运行/slave没有连接到master。

接下来再简单介绍一下异步复制/半同步复制之间的区别。

异步复制,master上的操作记录binlog的同时不关心binlog是否已经被slave接收。

半同步复制,master上的操作记录binlog的同时会关心binlog是否被slave接受。但是由于它的处理逻辑问题可能丢一个事务,如下图所示:

 

这样的处理流程存在一个问题,当存储引擎提交(storage commit)后,此时如果master挂了那么会存在主从不一致,对于这个问题orczhou好像自己对源码进行了修改更改storage commit的顺序来达到一个增强的半同步复制。

对Seconds_Behind_Master就解释到这里,希望对你也能有点帮助。

MySQL server has gone away 问题的解决方法

今天在备份自己blog的 数据库时发生错误, 信息如下:

mysqldump: Error 2020: Got packet bigger than 'max_allowed_packet' bytes when dumping table `xxx_posts` at row: 716
mysqldump: Couldn't execute 'show table status like 'xxx\_posts\_2\_bak'': MySQL server has gone away (2006)
-- Warning: Couldn't get status information for table xxx_posts_2_bak (MySQL server has gone away)
-- Retrieving table structure for table xxx_posts_2_bak...
mysqldump: Couldn't execute 'SET OPTION SQL_QUOTE_SHOW_CREATE=1': MySQL server has gone away (2006)
mysqldump: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (MySQL server has gone away)
mysqldump: Couldn't execute 'SELECT `COLUMN_NAME` AS `Field`, `COLUMN_TYPE` AS `Type`, `IS_NULLABLE` AS `Null`, `COLUMN_KEY` AS `Key`, `COLUMN_DEFAULT` AS `Default`, `EXTRA` AS `Extra`, `COLUMN_COMMENT` AS `Comment` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE TABLE_SCHEMA = 'xxxrowing' AND TABLE_NAME = 'xxx_posts_2_bak'': MySQL server has gone away (2006)
-- Skipping dump data for table 'xxx_posts_2_bak', it has no fields
mysqldump: Couldn't execute 'show table status like 'xxx\_posts\_tmp'': MySQL server has gone away (2006)
-- Warning: Couldn't get status information for table xxx_posts_tmp (MySQL server has gone away)
-- Retrieving table structure for table xxx_posts_tmp...
mysqldump: Couldn't execute 'SET OPTION SQL_QUOTE_SHOW_CREATE=1': MySQL server has gone away (2006)
mysqldump: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (MySQL server has gone away)
mysqldump: Couldn't execute 'SELECT `COLUMN_NAME` AS `Field`, `COLUMN_TYPE` AS `Type`, `IS_NULLABLE` AS `Null`, `COLUMN_KEY` AS `Key`, `COLUMN_DEFAULT` AS `Default`, `EXTRA` AS `Extra`, `COLUMN_COMMENT` AS `Comment` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE TABLE_SCHEMA = 'xxxrowing' AND TABLE_NAME = 'xxx_posts_tmp'': MySQL server has gone away (2006)
-- Skipping dump data for table 'xxx_posts_tmp', it has no fields
mysqldump: Couldn't execute 'show table status like 'xxx\_statpress'': MySQL server has gone away (2006)
-- Warning: Couldn't get status information for table xxx_statpress (MySQL server has gone away)
-- Retrieving table structure for table xxx_statpress...
mysqldump: Couldn't execute 'SET OPTION SQL_QUOTE_SHOW_CREATE=1': MySQL server has gone away (2006)
mysqldump: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (MySQL server has gone away)
mysqldump: Couldn't execute 'SELECT `COLUMN_NAME` AS `Field`, `COLUMN_TYPE` AS `Type`, `IS_NULLABLE` AS `Null`, `COLUMN_KEY` AS `Key`, `COLUMN_DEFAULT` AS `Default`, `EXTRA` AS `Extra`, `COLUMN_COMMENT` AS `Comment` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE TABLE_SCHEMA = 'xxxrowing' AND TABLE_NAME = 'xxx_statpress'': MySQL server has gone away (2006)
-- Skipping dump data for table 'xxx_statpress', it has no fields
mysqldump: Couldn't execute 'show table status like 'xxx\_term\_relationships'': MySQL server has gone away (2006)
-- Warning: Couldn't get status information for table xxx_term_relationships (MySQL server has gone away)
-- Retrieving table structure for table xxx_term_relationships...
mysqldump: Couldn't execute 'SET OPTION SQL_QUOTE_SHOW_CREATE=1': MySQL server has gone away (2006)
mysqldump: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (MySQL server has gone away)
mysqldump: Couldn't execute 'SELECT `COLUMN_NAME` AS `Field`, `COLUMN_TYPE` AS `Type`, `IS_NULLABLE` AS `Null`, `COLUMN_KEY` AS `Key`, `COLUMN_DEFAULT` AS `Default`, `EXTRA` AS `Extra`, `COLUMN_COMMENT` AS `Comment` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE TABLE_SCHEMA = 'xxxrowing' AND TABLE_NAME = 'xxx_term_relationships'': MySQL server has gone away (2006)
-- Skipping dump data for table 'xxx_term_relationships', it has no fields
mysqldump: Couldn't execute 'show table status like 'xxx\_term\_taxonomy'': MySQL server has gone away (2006)
-- Warning: Couldn't get status information for table xxx_term_taxonomy (MySQL server has gone away)
-- Retrieving table structure for table xxx_term_taxonomy...
mysqldump: Couldn't execute 'SET OPTION SQL_QUOTE_SHOW_CREATE=1': MySQL server has gone away (2006)
mysqldump: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (MySQL server has gone away)
mysqldump: Couldn't execute 'SELECT `COLUMN_NAME` AS `Field`, `COLUMN_TYPE` AS `Type`, `IS_NULLABLE` AS `Null`, `COLUMN_KEY` AS `Key`, `COLUMN_DEFAULT` AS `Default`, `EXTRA` AS `Extra`, `COLUMN_COMMENT` AS `Comment` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE TABLE_SCHEMA = 'xxxrowing' AND TABLE_NAME = 'xxx_term_taxonomy'': MySQL server has gone away (2006)
-- Skipping dump data for table 'xxx_term_taxonomy', it has no fields
mysqldump: Couldn't execute 'show table status like 'xxx\_terms'': MySQL server has gone away (2006)
-- Warning: Couldn't get status information for table xxx_terms (MySQL server has gone away)
-- Retrieving table structure for table xxx_terms...
mysqldump: Couldn't execute 'SET OPTION SQL_QUOTE_SHOW_CREATE=1': MySQL server has gone away (2006)
mysqldump: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (MySQL server has gone away)
mysqldump: Couldn't execute 'SELECT `COLUMN_NAME` AS `Field`, `COLUMN_TYPE` AS `Type`, `IS_NULLABLE` AS `Null`, `COLUMN_KEY` AS `Key`, `COLUMN_DEFAULT` AS `Default`, `EXTRA` AS `Extra`, `COLUMN_COMMENT` AS `Comment` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE TABLE_SCHEMA = 'xxxrowing' AND TABLE_NAME = 'xxx_terms'': MySQL server has gone away (2006)
-- Skipping dump data for table 'xxx_terms', it has no fields
mysqldump: Couldn't execute 'show table status like 'xxx\_usermeta'': MySQL server has gone away (2006)
-- Warning: Couldn't get status information for table xxx_usermeta (MySQL server has gone away)
-- Retrieving table structure for table xxx_usermeta...
mysqldump: Couldn't execute 'SET OPTION SQL_QUOTE_SHOW_CREATE=1': MySQL server has gone away (2006)
mysqldump: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (MySQL server has gone away)
mysqldump: Couldn't execute 'SELECT `COLUMN_NAME` AS `Field`, `COLUMN_TYPE` AS `Type`, `IS_NULLABLE` AS `Null`, `COLUMN_KEY` AS `Key`, `COLUMN_DEFAULT` AS `Default`, `EXTRA` AS `Extra`, `COLUMN_COMMENT` AS `Comment` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE TABLE_SCHEMA = 'xxxrowing' AND TABLE_NAME = 'xxx_usermeta'': MySQL server has gone away (2006)
-- Skipping dump data for table 'xxx_usermeta', it has no fields
mysqldump: Couldn't execute 'show table status like 'xxx\_users'': MySQL server has gone away (2006)
-- Warning: Couldn't get status information for table xxx_users (MySQL server has gone away)
-- Retrieving table structure for table xxx_users...
mysqldump: Couldn't execute 'SET OPTION SQL_QUOTE_SHOW_CREATE=1': MySQL server has gone away (2006)
mysqldump: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (MySQL server has gone away)
mysqldump: Couldn't execute 'SELECT `COLUMN_NAME` AS `Field`, `COLUMN_TYPE` AS `Type`, `IS_NULLABLE` AS `Null`, `COLUMN_KEY` AS `Key`, `COLUMN_DEFAULT` AS `Default`, `EXTRA` AS `Extra`, `COLUMN_COMMENT` AS `Comment` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE TABLE_SCHEMA = 'xxxrowing' AND TABLE_NAME = 'xxx_users'': MySQL server has gone away (2006)
-- Skipping dump data for table 'xxx_users', it has no fields
mysqldump: Couldn't execute 'use `xxxrowing`': MySQL server has gone away (2006)
mysqldump: Couldn't execute 'UNLOCK TABLES': MySQL server has gone away (2006)
-- Disconnecting from 127.0.0.1...
2013-06-25 23:29:49 命令开始
tar: Removing leading `/' from member names
/home/sch/sch.bak/xxx.sch.sql.tmp.20130625232949.sql

 

经过google的搜索等, 最后参照如下文章修改备份脚本:

修改前:mysqldump -h 127.0.0.1 -uroot -pxxx kk -F -i -n -R -e -f -v --max_allowed_packet=1000000 --net_buffer_length=8000  --no-autocommit > $todaysqltmpbak
修改后:mysqldump -h 127.0.0.1 -uroot -pxxx kk -F -i -n -R -e -f -v --max_allowed_packet=100000000 --net_buffer_length=8000  --no-autocommit > $todaysqltmpbak

 

 

文章如下:

 

MySQL server has gone away 问题解决方法,需要的朋友可以参考下。

应用程序(比如PHP)长时间的执行批量的MYSQL语句。执行一个SQL,但SQL语句过大或者语句中含有BLOB或者longblob字段。比如,图片数据的处理。都容易引起MySQL server has gone away。今天遇到类似的情景,MySQL只是冷冷的说:MySQL server has gone away。

大概浏览了一下,主要可能是因为以下几种原因:
一种可能是发送的SQL语句太长,以致超过了max_allowed_packet的大小,如果是这种原因,你只要修改my.cnf,加大max_allowed_packet的值即可。

还有一种可能是因为某些原因导致超时,比如说程序中获取数据库连接时采用了Singleton的做法,虽然多次连接数据库,但其实使用的都是同一个连接,而且程序中某两次操作数据库的间隔时间超过了wait_timeout(SHOW STATUS能看到此设置),那么就可能出现问题。最简单的处理方式就是把wait_timeout改大,当然你也可以在程序里时不时顺手mysql_ping()一下,这样MySQL就知道它不是一个人在战斗。

解决MySQL server has gone away

1、应用程序(比如PHP)长时间的执行批量的MYSQL语句。最常见的就是采集或者新旧数据转化。
解决方案:
在my.cnf文件中添加或者修改以下两个变量:
wait_timeout=2880000
interactive_timeout = 2880000
关于两个变量的具体说明可以google或者看官方手册。如果不能修改my.cnf,则可以在连接数据库的时候设置CLIENT_INTERACTIVE,比如:
sql = "set interactive_timeout=24*3600";
mysql_real_query(...)

2、执行一个SQL,但SQL语句过大或者语句中含有BLOB或者longblob字段。比如,图片数据的处理
解决方案:
在my.cnf文件中添加或者修改以下变量:
max_allowed_packet = 10M(也可以设置自己需要的大小)
max_allowed_packet 参数的作用是,用来控制其通信缓冲区的最大长度。

最近做网站有一个站要用到WEB网页采集器功能,当一个PHP脚本在请求URL的时候,可能这个被请求的网页非常慢慢,超过了mysql的 wait-timeout时间,然后当网页内容被抓回来后,准备插入到MySQL的时候,发现MySQL的连接超时关闭了,于是就出现了“MySQL server has gone away”这样的错误提示,解决这个问题,我的经验有以下两点,或许对大家有用处:
第 一种方法:
当然是增加你的 wait-timeout值,这个参数是在my.cnf(在Windows下台下面是my.ini)中设置,我的数据库负荷稍微大一点,所以,我设置的值 为10,(这个值的单位是秒,意思是当一个数据库连接在10秒钟内没有任何操作的话,就会强行关闭,我使用的不是永久链接 (mysql_pconnect),用的是mysql_connect,关于这个wait-timeout的效果你可以在MySQL的进程列表中看到 (show processlist) ),你可以把这个wait-timeout设置成更大,比如300秒,呵呵,一般来讲300秒足够用了,其实你也可以不用设置,MySQL默认是8个小 时。情况由你的服务器和站点来定。
第二种方法:
这也是我个人认为最好的方法,即检查 MySQL的链接状态,使其重新链接。
可能大家都知道有mysql_ping这么一个函数,在很多资料中都说这个mysql_ping的 API会检查数据库是否链接,如果是断开的话会尝试重新连接,但在我的测试过程中发现事实并不是这样子的,是有条件的,必须要通过 mysql_options这个C API传递相关参数,让MYSQL有断开自动链接的选项(MySQL默认为不自动连接),但我测试中发现PHP的MySQL的API中并不带这个函数,你重新编辑MySQL吧,呵呵。但mysql_ping这个函数还是终于能用得上的,只是要在其中有一个小小的操作技巧:
这是我的的数据库操 作类中间的一个函数

复制代码 代码如下:
function ping(){
if(!mysql_ping($this->link)){
mysql_close($this->link); //注意:一定要先执行数据库关闭,这是关键
$this->connect();
}
}

我需要调用这个函数的代码可能是这样子的

复制代码 代码如下:
$str = file_get_contents('http://www.jb51.net');
$db->ping();//经过前面的网页抓取后,或者会导致数据库连接关闭,检查并重新连接
$db->query('select * from table');

ping()这个函数先检测数据连接是否正常,如果被关闭,整个把当前脚本的MYSQL实例关闭,再重新连接。
经 过这样处理后,可以非常有效的解决MySQL server has gone away这样的问题,而且不会对系统造成额外的开销。
__________________________________________________________________________________________________
今天遇到类似的情景,MySQL只是冷冷的说:MySQL server has gone away。
大概浏览了一下,主要可能是因为以下几种原因:
一种可能是发送的SQL语句太长,以致超过了max_allowed_packet的大小,如果是这种原因,你只要修改my.cnf,加大max_allowed_packet的值即可。
还有一种可能是因为某些原因导致超时,比如说程序中获取数据库连接时采用了Singleton的做法,虽然多次连接数据库,但其实使用的都是同一个连接,而且程序中某两次操作数据库的间隔时间超过了wait_timeout(SHOW STATUS能看到此设置),那么就可能出现问题。最简单的处理方式就是把wait_timeout改大,当然你也可以在程序里时不时顺手mysql_ping()一下,这样MySQL就知道它不是一个人在战斗。
解决MySQL server has gone away
1、应用程序(比如PHP)长时间的执行批量的MYSQL语句。最常见的就是采集或者新旧数据转化。
解决方案:
在my.cnf文件中添加或者修改以下两个变量:
wait_timeout=2880000
interactive_timeout = 2880000  关于两个变量的具体说明可以google或者看官方手册。如果不能修改my.cnf,则可以在连接数据库的时候设置CLIENT_INTERACTIVE,比如:
sql = "set interactive_timeout=24*3600";
mysql_real_query(...)
2、执行一个SQL,但SQL语句过大或者语句中含有BLOB或者longblob字段。比如,图片数据的处理
解决方案:
在my.cnf文件中添加或者修改以下变量:
max_allowed_packet = 10M(也可以设置自己需要的大小)
max_allowed_packet参数的作用是,用来控制其通信缓冲区的最大长度。
1、应用程序(比如PHP)长时间的执行批量的MYSQL语句。
最常见的就是采集或者新旧数据转化。
解决方案:

在my.ini文件中添加或者修改以下两个变量:
wait_timeout=2880000
interactive_timeout = 2880000

关于两个变量的具体说明可以google或者看官方手册。
如果不能修改my.cnf,则可以在连接数据库的时候设置CLIENT_INTERACTIVE,比如:
sql = "set interactive_timeout=24*3600";
mysql_real_query(...)

2、执行一个SQL,但SQL语句过大或者语句中含有BLOB或者longblob字段。
比如,图片数据的处理
解决方案

在my.cnf文件中添加或者修改以下变量:
max_allowed_packet = 10M (也可以设置自己需要的大小)

max_allowed_packet 参数的作用是,用来控制其通信缓冲区的最大长度。

------------ 以下是网络搜索的资料 -------------------
也许其他人遇到这个问题,不一定是这儿的原因,那么,就把我在网上找到比较全面的分析放到下面:
有两篇,第一篇比较直观,第二篇比较深奥。
解决MySQL server has gone away 2009-01-09 16:23:22
来自:http://www.webjx.com/database/mysql-8817.html
今天遇到类似的情景,MySQL只是冷冷的说:MySQL server has gone away。
大概浏览了一下,主要可能是因为以下几种原因:
一种可能是发送的SQL语句太长,以致超过了max_allowed_packet的大小,如果是这种原因,你只要修改my.cnf,加大max_allowed_packet的值即可。
还有一种可能是因为某些原因导致超时,比如说程序中获取数据库连接时采用了Singleton的做法,虽然多次连接数据库,但其实使用的都是同一个连接,而且程序中某两次操作数据库的间隔时间超过了wait_timeout(SHOW STATUS能看到此设置),那么就可能出现问题。最简单的处理方式就是把wait_timeout改大,当然你也可以在程序里时不时顺手mysql_ping()一下,这样MySQL就知道它不是一个人在战斗。
解决MySQL server has gone away

1、应用程序(比如PHP)长时间的执行批量的MYSQL语句。最常见的就是采集或者新旧数据转化。

解决方案:

在my.cnf文件中添加或者修改以下两个变量:

wait_timeout=2880000
interactive_timeout = 2880000
关于两个变量的具体说明可以google或者看官方手册。如果不能修改my.cnf,则可以在连接数据库的时候设置CLIENT_INTERACTIVE,比如:

sql = "set interactive_timeout=24*3600";
mysql_real_query(...)

2、执行一个SQL,但SQL语句过大或者语句中含有BLOB或者longblob字段。比如,图片数据的处理

解决方案:

在my.cnf文件中添加或者修改以下变量:

max_allowed_packet = 10M
(也可以设置自己需要的大小)

max_allowed_packet
参数的作用是,用来控制其通信缓冲区的最大长度

MySQL: 诡异的MySQL server has gone away及其解决
来自:http://fz9493.blog.sohu.com/38472203.html

jimmy | 15 三月, 2007 20:32

在Mysql执行show status,通常更关注缓存效果、进程数等,往往忽略了两个值:

Variable_name Value
Aborted_clients 3792
Aborted_connects 376

通常只占query的0.0x%,所以并不为人所重视。而且在传统Web应用上,query错误对用户而言影响并不大,只是重新刷新一下页面就OK了。最近的基础改造中,把很多应用作为service运行,无法提示用户重新刷新,这种情况下,可能就会影响到服务的品质。

通过程序脚本的日志跟踪,主要报错信息为“MySQL server has gone away”。官方的解释是:

The most common reason for the MySQL server has gone away error is that the server timed out and closed the connection.

Some other common reasons for the MySQL server has gone away error are:

You (or the db administrator) has killed the running thread with a KILL statement or a mysqladmin kill command.

You tried to run a query after closing the connection to the server. This indicates a logic error in the application that should be corrected.

A client application running on a different host does not have the necessary privileges to connect to the MySQL server from that host.

You got a timeout from the TCP/IP connection on the client side. This may happen if you have been using the commands: mysql_options(..., MYSQL_OPT_READ_TIMEOUT,...) or mysql_options(..., MYSQL_OPT_WRITE_TIMEOUT,...). In this case increasing the timeout may help solve the problem.

You have encountered a timeout on the server side and the automatic reconnection in the client is disabled (the reconnect flag in the MYSQL structure is equal to 0).

You are using a Windows client and the server had dropped the connection (probably because wait_timeout expired) before the command was issued.

The problem on Windows is that in some cases MySQL doesn't get an error from the OS when writing to the TCP/IP connection to the server, but instead gets the error when trying to read the answer from the connection.

In this case, even if the reconnect flag in the MYSQL structure is equal to 1, MySQL does not automatically reconnect and re-issue the query as it doesn't know if the server did get the original query or not.

The solution to this is to either do a mysql_ping on the connection if there has been a long time since the last query (this is what MyODBC does) or set wait_timeout on the mysqld server so high that it in practice never times out.

You can also get these errors if you send a query to the server that is incorrect or too large. If mysqld receives a packet that is too large or out of order, it assumes that something has gone wrong with the client and closes the connection. If you need big queries (for example, if you are working with big BLOB columns), you can increase the query limit by setting the server's max_allowed_packet variable, which has a default value of 1MB. You may also need to increase the maximum packet size on the client end. More information on setting the packet size is given in Section A.1.2.9, “Packet too large”.

An INSERT or REPLACE statement that inserts a great many rows can also cause these sorts of errors. Either one of these statements sends a single request to the server irrespective of the number of rows to be inserted; thus, you can often avoid the error by reducing the number of rows sent per INSERT or REPLACE.

You also get a lost connection if you are sending a packet 16MB or larger if your client is older than 4.0.8 and your server is 4.0.8 and above, or the other way around.

It is also possible to see this error if hostname lookups fail (for example, if the DNS server on which your server or network relies goes down). This is because MySQL is dependent on the host system for name resolution, but has no way of knowing whether it is working — from MySQL's point of view the problem is indistinguishable from any other network timeout.

You may also see the MySQL server has gone away error if MySQL is started with the --skip-networking option.

Another networking issue that can cause this error occurs if the MySQL port (default 3306) is blocked by your firewall, thus preventing any connections at all to the MySQL server.

You can also encounter this error with applications that fork child processes, all of which try to use the same connection to the MySQL server. This can be avoided by using a separate connection for each child process.

You have encountered a bug where the server died while executing the query.

据此分析,可能原因有3:

1,Mysql服务端与客户端版本不匹配。

2,Mysql服务端配置有缺陷或者优化不足

3,需要改进程序脚本

通过更换多个服务端与客户端版本,发现只能部分减少报错,并不能完全解决。排除1。

对服务端进行了彻底的优化,也未能达到理想效果。在timeout的取值设置上,从经验值的10,到PHP默认的60,进行了多次尝试。而Mysql官方默认值(8小时)明显是不可能的。从而对2也进行了排除。(更多优化的经验分享,将在以后整理提供)

针对3对程序代码进行分析,发现程序中大量应用了类似如下的代码(为便于理解,用原始api描述):

$conn=mysql_connect( ... ... );

... ... ... ...

if(!$conn){ //reconnect

$conn=mysql_connect( ... ... );

}

mysql_query($sql, $conn);

这段代码的含义,与Mysql官方建议的方法思路相符[ If you have a script, you just have to issue the query again for the client to do an automatic reconnection. ]。在实际分析中发现,if(!$conn)并不是可靠的,程序通过了if(!$conn)的检验后,仍然会返回上述错误。

对程序进行了改写:

if(!conn){ // connect ...}

elseif(!mysql_ping($conn)){ // reconnect ... }

mysql_query($sql, $conn);

经实际观测,MySQL server has gone away的报错基本解决。

BTW: 附带一个关于 reconnect 的疑问,

在php4x+client3x+mysql4x的旧环境下,reconnet的代码:

$conn=mysql_connect(...) 可以正常工作。

但是,在php5x+client4x+mysql4x的新环境下,$conn=mysql_connect(...)返回的$conn有部分情况下不可用。需要书写为:

mysql_close($conn);

$conn=mysql_connect(...);

返回的$conn才可以正常使用。原因未明。未做深入研究,也未见相关讨论。或许mysql官方的BUG汇报中会有吧。

~~呵呵~~

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/brightsnow/archive/2009/03/17/3997705.aspx

description:
remember that your MySQL "max_allowed_packet" configuration setting (default 1MB)
mysql 默认最大能够处理的是1MB
如果你在sql使用了大的text或者BLOB数据,就会出现这个问题。 php手册上的注释

When trying to INSERT or UPDATE and trying to put a large amount of text or data (blob) into a mysql table you might run into problems.
In mysql.err you might see:
Packet too large (73904)
To fix you just have to start up mysql with the option -O max_allowed_packet=maxsize
You would just replace maxsize with the max size you want to insert, the default is 65536

mysql手册上说

Both the client and the server have their own max_allowed_packet variable, so if you want to handle big packets, you must increase this variable both in the client and in the server.

If you are using the mysql client program, its default max_allowed_packet variable is 16MB. To set a larger value, start mysql like this:

shell> mysql --max_allowed_packet=32M That sets the packet size to 32MB.

The server's default max_allowed_packet value is 1MB. You can increase this if the server needs to handle big queries (for example, if you are working with big BLOB columns). For example, to set the variable to 16MB, start the server like this:

shell> mysqld --max_allowed_packet=16M You can also use an option file to set max_allowed_packet. For example, to set the size for the server to 16MB, add the following lines in an option file:

[mysqld]max_allowed_packet=16M

使用mysql做数据库还原的时候,由于有些数据很大,会出现这样的错误:The MySQL Server returned this Error:MySQL Error Nr.2006-MySQL server has gone away。我的一个150mb的备份还原的时候就出现了这错误。解决的方法就是找到mysql安装目录,找到my.ini文件,在文件的最后添加:max_allowed_packet = 10M(也可以设置自己需要的大小)。 max_allowed_packet 参数的作用是,用来控制其通信缓冲区的最大长度。

关于用户体验的思考

来源:互联网

用户体验是一个很大的话题,先从一个故事说起。周末参加了两天的PMP培训,听课期间注意到老师的一个细节,在讲选择题的时候,选项A、C读音正常, 而"B"老师读为Boy,"D"老师读为Dog。刚听到的时候大家莞尔一笑,以为这是个善意的玩笑。但是以后的题目都是这样读音。很快,我想明白了,B和 D的发音类似,容易混淆;Boy和Dog是简单的单词,发音能够明确区分,也没有类似Bog和Doy的读音混淆。这是什么?这就是用户体验。

1. 页面布局

常规上来说,我们把网页布局按照分栏的多少分为一栏式,二栏式和三栏式。

对于一栏式页面布局来说,一般在页面上放置一个具有冲击力的图片或者Flash来给用户留下深刻的印象,但是,这样的页面所能够容纳的信息量非常有限。所 以常用于企业网站,以及一些小网站的首页,用于让用户记住你的站。此外,对于功能性比较单一的页面,也一般用一栏式布局,比如搜索引擎,注册和登录页面等 等。

二栏式布局是最为常见的布局方式,二栏式又分为左宽右窄和左窄右宽式。这两种模式的选择是由于网站的性质所决定的。对于用户来说,他的浏览关注顺序是从左 到右,那么窄的部分一般来说都是导航栏,而宽的部分则是主体内容部分,那么用哪一种方式将取决于你的站是内容占主体还是导航占主体,换句话说,是内容驱动 导航还是导航来驱动内容。

对于三栏式布局来说,最大的好处就在于容纳的信息量比较大,但是重点不突出,降低了用户对网站的可控性,因此一般意义上不推荐。

当然,如果当用户需要比较多样化的时候,也可以让用户自由来设计布局,多常见于个人博客。

2. 页面的通透性

页面的通透性是指尽量使整个页面的模块比例统一,同时通过线条,颜色等视觉元素增加各模块间的区分度,使得用户的视线轨迹可以有规则地通过各个模块,而不会被模块之间不规则的交叉所打断。

此外,根据"F"原则,也应该尽量将重要地,用户所关系地内容放在页面的左上角位置。

3. 页面的配色方案

每个网站都要有自己的主色调,主色调指的就是页面色彩的主要色调,总趋势,其他配色的综合不能超过主色调的50%(白色背景除外)。

在选择颜色的时候,不仅仅要考虑颜色本身所代表的含义,如安全,浪漫等,还有考虑以下几种因素。

目标用户群体。不同的用户群体对于颜色的审美爱好以及理解都不同,其中包括性别,年龄,职业等。

当地文化风俗。如中国把红色作为喜庆的颜色,而欧洲大部分却把红色作为杀戮的象征。

网站的类型。如电子商务站一般用暖色调来刺激用户购买,而SNS站则营造一个轻松的氛围。而垂直类网站一般都与自己的领域特色相关。

品牌形象。我总结一句话就是根据自己的Logo以及企业形象来选择色调。比如IBM就一定会选择蓝色作为主色调。

4. 页头和页尾

页头分为设计型头部和简约型头部。一般的大型网站,由于已经有着一定的网站知名度,所以无需在通过渲染头部来提高网站对用户的吸引力,加深印象。所以一般 采用比较简单的简约型头部,比如新浪,腾讯,都是这样的效果。对于一些小网站来说,采用设计性头部给用户留下深刻印象,创造品牌效应,但是当设计性头部过 于繁杂时,却使得内容的容纳量变小,从而造成一种头重脚轻的感觉。所以这个需要设计师的一种折中。

在页头上最重要的就是Logo,在现代网站的设计中,Logo起到两个作用,一个是标识,一个是让用户回到首页。

页尾一般来说并不重要,用户可到达的机会也少,所以尽量地去简化它,避免它占用内容所占据的位置。

5. 搜索区

现在的网站一般都带有站内搜索的功能,目前有两种设计方式。

一种将搜索淡化,因为搜索只是一种手段,适用于浏览型网站,我并不鼓励你搜索,而是希望你一条一条地看下去。比如说豆瓣。我希望你去看社区的动态,而不是希望你来豆瓣为了找人。

一种是搜索为主,最简单的就是淘宝。一般来说用户来电子商务站都是有着明确的目的,所以搜索是用户找到他想要商品的最主要方式。

另外,对于搜索框来说,如果你鼓励用户使用搜索框,在页面刚刚打开的时候,就可以让光标在搜索框上,这样用户可以直接搜索内容,而省去了一次操作。但是如果并非如此,就不要让光标在文本框上,因为这样用户变没有办法使用键盘来让整个页面下移。

6. 登陆和注册

首先是究竟是淡化登陆注册还是强调登陆注册,这个取决于该站点的目的。两个典型便是新浪和豆瓣。对于新浪来说,需要的只是网站的浏览量,与是否注册关系不 大,所以只是将登陆弱化,没有登录一样可以享受基本所有权利,其中包括"匿名"评论等功能。而豆瓣以及很多SNS站点都需要来通过用户注册来扩展好友关 系,所以在豆瓣的首先都是将登陆注册放在最显眼的位置,然后用一些优点来煽动用户注册。

但是个人认为随着SNS站点的逐渐做大,虽然不会像新浪等资讯站一样如此弱化用户的登陆注册,但是也不会在将登陆注册变为浏览,发帖等必须的一部,而会将匿名作为可选的一项。而新浪等资讯站随着发展,也会逐渐地走向社交网络,从而在网络中达到一种资讯站与SNS的折中。

7. 关于广告

广告从来都是互联网的主要盈利手段之一。可是不得不承认,没有人喜欢看广告。因此广告主和用户之间总是存在着无可避免的直接矛盾,而且一定意义上,网络广告没有任何约束,这也就导致了网站广告的混乱和不合理性。

但是我们在网站中穿插广告时,应该保证我们自己网站不会影响用户的浏览。

首先,据调查,用户最能接受的广告形式是游动式广告和横幅式广告,而弹出广告和邮件广告是用户最讨厌的。

其次,从布局上看,我们不能让广告切断页面的相关内容,因为很多用户一旦看到广告就会习惯性地认为该页面的内容已经中止,不在继续浏览了,所以这样的话会影响整个网站内容的关联性。

然后,我们要避免过多的广告同时出现。也要规范网站广告的尺寸大小。

8. 表单的布局设计

这里就从注册来看,这个是最典型的表单。

从布局上讲分为三种方式,其中包括垂直对齐,左对齐和右对齐。

垂直对齐的优势在于可大量减少眼睛一动和填写表单的时间,但是缺点在于增加了垂直的空间,当注册项较多时,会增加页面的滚动。适用于搜集的信息和资料是熟悉的,需要较少的完成时间。

左对齐便于用户浏览标签,同时会减少垂直空间。但是如果某标签过长,则会造成文字与文本框距离过远。适用于对所需的信息不熟悉,而且标签文字不会太长。

右对齐则让左边参差不齐的空包让用户很难快速检索表单要填写的内容。

另外,在设计时,最好将注册时相关的项进行分组,这样可以让用户以尽可能少的视觉元素来分出关系,避免视觉噪音。

对于很多选项来说,不妨提供默认选项,来尽量减少用户的操作。并且给予适当的提示来给予用户帮助,记得一定是适当的,不要过多。

此外,还可用一些较大的字体以及间距,不要让用户产生局促感。

9. 模块标签

模块标签,就是用于页面内某模块中,在内容上方使用一列标签形式的链接进行切换。

使用模块标签时,首先一定要具备一个最基本的前提,内容必须都相对独立,不能存在上下文的关系。

在设计模块标签与下面模块内容时,我总结为两点:突出对比和加强关联。

突出对比是说,突出已选中标签和未选中标签的对比,而加强关联是说加强以选中标签和其内容模块的关联。

10. 按钮

首先要用较大的,与背景色形成鲜明对比的按钮来使所需主要强调的按钮从网页中跳跃出来。

其次,我们需要根据按钮的主次来选择性强调和弱化某按钮。但是同一个方式的弱化,可能到另一个方面则会是强调。这个需要根据经验来结合之前的知识来考虑。

还有也要注意按钮的摆放位置,比如说用户的视线是从上向下,从左至右,这样用户也会依照这样的顺序做出选择。

11. 反馈

Nielsen可用性原则中有一条痕重要的原则,就是系统必须提供必要的反馈。其中包括成功提示和失败提示。

成功提示是最简单的一种提示,他应该仅仅起到提示的作用,而不该中断用户的操作。我们应该只需要让用户知道就可以了。不应该让用户进行任何不必要的操作,比如弹层就是一个非常愚蠢的做法。

失败提示是很重要的提示,从理论上说分为两种方式,一种是直接在网页上用文字提示,一种是弹出警告框来提示。但是我个人认为弹出警告框是非常不可取的,因为最重要的一点是alert的时候会发出声音,这样的用户体验是非常差的,所以自己做一个弹出层倒是一个折中的做法。

还有一个很重要的是错误页面,比如说404页面,优秀的404页面应该能够改善用户的不良体验,减少用户的挫败感,还应该将用户引导到他原本打算去往的相关联的去处,以减少用户的流失率。

关于进度条,据研究表明,超过1秒就要提供相应的提示信息,比如进度条,而超过10秒就不仅仅需要提示信息,还需要提供完成的百分比。

12. 其他个人想法About验证码

比如说验证码,验证码是用来防止恶意注册的,但是不是用来防止正常用户的,我们不应该让用户因为验证码产生挫败感。如果让我设计一个验证码,我会将英文的"O"和数字的"0",英文的"L"和数字的"1"都排除在验证码之外。

此外我有个想法是觉得,首先,密码是在post回去的过程中是无法保存原有状态的,所以唯一的办法只能是ajax回发验证。但是在何时Ajax,只能是在失去焦点时。所以我认为最好把验证码放在页面最顶端,这样用户比较容易离开焦点从而触发Ajax验证。

13. 总结

不管这个产品成功还是失败,一定要做阶段总结,这样才有可能越做越好。实际上,找一个有做产品经验的人(比如Jobs或者周鸿祎)可能比学习所谓的"最佳实践",做成产品靠谱得多,这就是总结的作用。