Column 'username' in field list is ambiguous、邮件漏发等问题的分析及解决

问题1.Column ‘username‘ in field list is ambiguous

### The error may involve com.fx.oa.module.per.leave.api.shared.domain.PositiveEntity.queryListForPage-Inline

### The error occurred while setting parameters

### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column ‘username‘ in field list is ambiguous

; SQL []; Column ‘username‘ in field list is ambiguous; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolat

  今天正式系统更新后,打开新建工作,页面报出500错误。打开日志有如上错误。负责处理问题的工程师跟我说,可能是有同事在测试系统数据和代码里都增加了一个名为userName的字段,但没有在正式系统数据库更新表结构导致的。我拿到日志信息,看到是ambiguous,这个单词的意思是username这个字段是不明确、有歧义的。这种错误往往是多个表之间关联查询,而表中有相同字段名称,未为该字段指定所属表引起的。在新建工作页面的底端,有查询办理历史的表格。查询历史时会先将所有任务拿出,由于任务的审批人存储的是用户名,需要进一步关联到用户表取出用户姓名,如下:

SELECT 
			task.processExecutionId,
			process.name as processDefineName,
			task.activityName,
			user.userName as createUserCode,
			task.status,
			task.description,
			task.finishTime,
			task.createTime
		FROM T_BPM_PROCESS_TASK task
		LEFT JOIN T_BPM_PROCESS_EXECUTION execution ON task.processExecutionId = execution.id
		LEFT JOIN t_bpm_process_define process ON execution.processDefineId = process.id
		LEFT JOIN T_SYS_USER user ON task.createUserCode = user.userCode
		WHERE task.processExecutionId = #{id}
		ORDER BY task.createTime DESC, task.finishTime DESC

在这个版本上线里,我们新上线了高级查询的基于用户的管理权限控制,负责的杜工在t_bpm_process_define中新增加了两个字段,他仿照已经存在的roleCode、roleName,增加了userCode、userName两个字段,而这两个字段至少在档案和用户相关的表广泛被使用。其中这两个字段在我们的系统里就可以被看做是保留字,其他表尽量不要使用。我建议将这两个专用于高级查询的字段加上前缀,而不必修改sql。

表结构修改后该问题消失。

问题2.sql:截取中出现的问题

本期OA在正式系统上线后,与moss系统并行了一段时间。在这段时间里oa的所有流程及表单均为测试,正式单据在moss里填写。所以我们在流程的显示名称在表单页面均添加了“(测试)”字样,而且页面中凡包含“(测试)”字样的表单,在填写和审批时都会提示“该表单是测试表单,请到moss里填写”。3月12号是OA表单正式启用,需要将所有的测试字样从系统里抹去。在测试字样添加的时候,由各流程负责同事在系统前端手动添加和保存。如果再在系统页面每张表单打开删除会非常麻烦。经过观察,我发现所有流程的显示名都包含(测试单据)或(测试字样),且几十个流程均未有在名称中包含以上字样。而在测试单据的html和template中,均包含<span style="color:#ff0000;">(测试表单)</span>,所以我写了以下sql:

update t_bpm_process_define set name=SUBSTR(NAME FROM 1 FOR INSTR(name,"(测试单据)")-1) where INSTR(name,"(测试单据)")!=0;
update t_bpm_form_define set template=REPLACE(template, ‘(测试单据)‘,‘‘)where INSTR(template,‘(测试单据)‘)!=0;
update t_bpm_form_define set html=REPLACE(html, ‘<span style="color:#ff0000;">(测试表单)</span>‘,‘‘)where INSTR(html,‘<span style="color:#ff0000;">(测试表单)</span>‘)!=0;

  执行后,表单倒是没有问题,但第一句的执行出现了可怕的现象,很多流程名称是空的。

第一句中我使用的是字符串的截取,第二、第三句都是替换部分字符串。我最初想可能跟这个有关,实际也确实有关,如果我也用replace函数是没有问题的,原因很简单,如果文本中不包含目标字符串肯定是不会替换的。但用字符串截取从逻辑上也讲得通,为什么会出现这么可怕的结果呢?

  原因就在于我们update没有使用表内联,sql在执行的时候根本没有什么数据去关联它到底该修改哪条数据。

  如果我们将第一条数据修改成这样,就没有问题了:

update t_bpm_process_define a,(select id,name from t_bpm_proces_define where  INSTR(name,"(测试单据)")!=0) )b set a.name=SUBSTR(NAME FROM 1 FOR INSTR(name,"(测试单据)")-1) where a.id = b.id;

问题3.由于我们公司使用的邮件服务器是Zimbra服务器,由云计算部门购买和维护。OA中的提醒邮件也是通过Zimbra往外发送。对于一些某时段的大批量邮件,比如逾期工作和考勤异常都是在某个时间点上由quartz触发,同时会发出数百封以至上千封邮件。可能对成熟的商用邮件服务器这点压力算不上什么,但对于Zimbra可能已经吃不消了。在云计算和IT的同事协助下,由我对邮件服务器进行了测试,测试用例如下:

测试用例1:100封,总用时约:16min;实收97封,失败3次,3次错误信息均为:javax.mail.MessagingException: Could not connect to SMTP host

测试用例2:100封,总用时约:16min;实收100封,失败2次,错误同上。加失败重发机制,失败后等待10s重发,最多重发3次;

测试用例3:每发一封,停留10s,总用时32min;实收100封,失败1次,错误同上;重发机制同用例2.

  关于MessagingException的问题:

  我看了一下几种解释:1.网络;2.防火墙;3.服务器的自我保护,比如防止大批量发送时挂掉或者垃圾邮件,我觉得第三种解释靠谱一些。

后来又做了一些其他压力强度的测试,而且针对MessagingException的错误,一步步跟踪代码,也进行了相关分析

  具体错误信息如下:

javax.mail.MessagingException:   Could   not   connect   to   SMTP   host:   mail.cn.phicomm.com,   port:   25; 
    nested   exception   is: 
                java.net.SocketException:   Software   caused   connection   abort:   connect 
                at   com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1282) 
                at   com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:37 
0) 
                at   javax.mail.Service.connect(Service.java:297) 
                at   javax.mail.Service.connect(Service.java:156) 
                at   javax.mail.Service.connect(Service.java:105)

  我通读了一下代码,发现是这样的,首先会连接生成serverSocket:

	if (serverSocket != null)
			openServer(); // only happens from connect(socket) else
							// openServer(host, port);
		else
			openServer(host, port);

  以下是openServer中的代码:

if (debug) 
			out.println("DEBUG SMTP: got bad greeting from host \"" + 
		    server + "\", port: " + 
		    port + ", response: " + 
		    r + "\n"); 
			throw new MessagingException( "Got bad greeting from SMTP host: " + server + 
			", port: " + 
			port + ", response: " + 
			r); 
		}

  而debug是一个全局变量,是session的一个属性,其值

Since the debug setting can be turned on only after the Session has been created

  也就是说session未建立就会报MessagingException这个错误。所以我进一步怀疑,我们的发送邮件代码每次都会去重连认证,这个也是代码的问题之一,所以我加了session失效才重连。

  接下来又进行了一次测试,用例如下:

用例1.代码修改如下

	if (session == null || session.getDebug()) {
			System.out.println("第" + j + "次重连");
			session = Session.getDefaultInstance(prop, auth);
		}

结果:没有失败

用例2.仍用1的代码,

结果:但失败1次,失败后未重新获得session,可见失败后session仍有效;

用例3.代码修改如下:

if (session == null || session.getDebug()) {
			// 如果需要身份验证,创建一个账号密码验证器
			if (mail.isValidate()) {
				auth = new MailAuthenticator(mail.getUserName(),
						mail.getPassword());
			}
			System.out.println("第" + j + "次重连");
			session = Session.getDefaultInstance(prop, auth);
		}

结果:有1次失败,失败后未重连。

  通过以上测试,是否每次重新获得session对效率 没有影响,对异常的发生也没有影响。异常报出后,session仍有效,并且可以重发。

  经过三轮测试,其实我们可以发现重发机制已经可以保证邮件的完全送达。

重发的代码如下:

/**
		 * Temporary mechanism: automatic resend mail
		 * @author chao.gao
		 * @date 2015-2-4 上午9:27:59
		 * @param mail
		 * @return
		 */
		public static boolean sendHtmlMail(BasicMail mail){

			if(sendHtmlMail_(mail)){
				return true;
			} else{
				int i = 0;
				while(!sendHtmlMail_(mail) && i < 3){
					try {
						i++;
						Thread.sleep(1000*60);
					} catch (InterruptedException e) {
						LOGGER.error("resend mail error", e);
					}
				}
				return true;
			}
		}

  加入重发机制运行了一段时间,未再发现类似的漏发现象。

Column 'username' in field list is ambiguous、邮件漏发等问题的分析及解决

时间: 2024-10-30 09:03:16

Column 'username' in field list is ambiguous、邮件漏发等问题的分析及解决的相关文章

错误代码: 1052 Column &#39;stu_id&#39; in field list is ambiguous

1.错误描述 1 queries executed, 0 success, 1 errors, 0 warnings 查询:select stu_id, (SELECT stu_name FROM t_student_info t WHERE t_student_info.stu_id = t.stu_id) stu_name from t_student_info t, t_... 错误代码: 1052 Column 'stu_id' in field list is ambiguous 执行

转 column &#39;id&#39; in field list is ambiguous的问题

column 'id' in field list is ambiguous 这个错误,是因为你查询语句里面有id字段的时候,没有说明是哪个表的id字段,应该加上表名(或者别名)来区分. 用表名进行区分的例子: select student.id, student.name, score.total from student, score where student.id = score.id 使用别名的例子: 用表名进行区分的例子: select s.id, s.name, c.total f

column &#39;id&#39; in field list is ambiguous

column 'id' in field list is ambiguous 这个错误,是因为你查询语句里面有id字段的时候,没有说明是哪个表的id字段,应该加上表名(或者别名)来区分. 用表名进行区分的例子:select student.id, student.name, score.totalfrom student, scorewhere student.id = score.id 使用别名的例子:用表名进行区分的例子:select s.id, s.name, c.totalfrom st

【MySQL 线上 BUG 分析】之 多表同字段异常:Column ‘xxx’ in field list is ambiguous

一.生产出错! 今天早上11点左右,我在工作休息之余,撸了一下猫.突然,工作群响了,老大在里面说:APP出错了! 妈啊,这太吓人了,因为只是说了出错,但是没说错误的信息.所以我赶紧到APP上看看. 这果然是出错了,而且还是简单而粗暴的500,太吓人了. 二.本地赶紧调试起来! 既然线上出错了,我们又不能直接进行调试,那当然得马上在本地搞起来了! 1.代码是否有错? 立马启动本地的项目,访问对应的接口,看看是不是代码哪里出错了. 好了,本地的代码和 SQL 都是没错的! 2.SQL 是否有错? 那

错误:Column &#39;Id&#39; in field list is ambiguous

SELECT `渠道名称` , SUM(`当日其他`) AS 当月其他 FROM `渠道信息` as A , `一线数据汇总` AS B WHERE A.`渠道名称` = B.`渠道名称` GROUP BY `渠道名称` 错误原因:表A和表B里都有'渠道名称',select时要指明是哪个表里的. SELECT A.`渠道名称` , SUM(`当日其他`) AS 当月其他 FROM `渠道信息` as A , `一线数据汇总` AS B WHERE A.`渠道名称` = B.`渠道名称` GROU

错误代码 1052 Column &#39;stu id&#39; in field list is ambiguous

1.错误描述 1 queries executed, 0 success, 1 errors, 0 warnings 查询:select stu_id, (SELECT stu_name FROM t_student_info t WHERE t_student_info.stu_id = t.stu_id) stu_name from t_student_info t, t_... 错误代码: 1052 Column 'stu_id' in field list is ambiguous 执行

Integrity constraint violation: 1052 Column &#39;status&#39; in where clause is ambiguous

public function roleManage($search,$tpage,$num) { //查询一个角色所对应的多个用户,联表查询 $result=Db::name('role') ->field('r.rid,r.rolename,u.username') ->alias('r') ->join('user u','u.rid=r.rid','') ->where($search) ->select(); //数据总条数 $count=Db::name('rol

Python Flask 向MySQL表里插入一条记录,提示Unknown column &#39;XXX&#39; in &#39;field list

sql =' INSERT INTO `blog`.`user` (`id`, `username`) VALUES (%d, %s)' %(1,username) 我在给username赋值aaabbb后提示:"Unknown column 'aaaabbb' in 'field list'" 找了半天问题,原来是%s没加双引号. 改为如下 sql =' INSERT INTO `blog`.`user` (`id`, `username`) VALUES (%d, "%s

Mybatis操作数据时出现:java.sql.SQLSyntaxErrorException: Unknown column &#39;XXX&#39; in &#39;field list&#39;

这个错误比较重要,而且很常见,故单独进行说明: Mybatis出现:Unknown column 'xxx' in 'field list' 先来看一下程序的内部: dao.addUser("ll111", "ll11");// 添加用户l main函数测试 //添加用户 成功1 失败0 public int addUser(String userPhoneNumber, String userPassword) throws IOException { //用户的