MySQL 8.0驱动导致所有表问题

nullCatalogMeansCurrent=true

最近在搭建Spring boot + ne4Spring的开发框架,为了方便生成Model Bean写了生成器,结果报错找不到相关的表信息,仔细check了发现当前数据库中并没有相关的表信息,第一反应是难道串表了?

  • 使用 DatabaseMetaData 中 getTables方法时疯狂报错,一路追下来发现表多到发指……

后来查询资料发现,MySQL8.0+的驱动默认返回的是用户具有权限的所有表的信息,如果只返回当先数据库的表信息,需要配置nullCatalogMeansCurrent 参数。

在连接参数加上nullCatalogMeansCurrent=true

现在又可以愉快的生成Model代码了。

git地址:https://github.com/moto72/ne4SpringBoot-pro

Java中访问控制符的作用域问题

java中访问控制符的作用域问题

很多新人关于访问控制符根本不知道有什么作用,所以在写代码的时候不能很好的控制自己提供的类库给别人使用,在更多的项目中,大家似乎更加倾向于public来显示开放性?我倒是觉得可能根本弄不清楚作用域,所以干脆就public好了,但是在架构设计的时候,我认为如果不能很好的理解作用域范围,那么逻辑分层也会分不清。

首先要知道Java中访问控制符有哪几种:public、protected、缺省、private。

这里我盗个图来比较一下,更方便记忆。

这里我们看到只有子类,并没有子包的概念,比如:com.tmsps.ne4spring.orm 与 com.tmsps.ne4spring.orm.model 到底是什么关系?

在java中我没有找到子包的定义,针对包名来说,仅仅是命名空间而已,他们只是看起来好像是一条线,但是其实是两个独立的空间。

mysql 增量备份

mysql增量备份

随着数据量的变大,每天一次的全量备份太坑爹鸟,所以周全量+日增量的办法比较划算,如果可以的话还是用云端吧,毕竟省的折腾自己啦。

首先开启binlog日志吧,毕竟这个在增量备份,数据恢复,甚至主从同步都要用的到。登录MySQL查看一下binlog开启情况:

show variables like '%log_bin%';

看到log_bin是没有开启的。开启的方式在 my.cnf [mysqld]配置下增加:

server_id = 1
log-bin = /data/mysql/mysql-bin
binlog-format = ROW
log-bin-index = /data/mysql/logindex
binlog_cache_size=32m
max_binlog_cache_size=512m
max_binlog_size=512m

注意这个坑爹的server_id。重启你的mysql,你可以看到已经开启了binlog。

通过:show master status; 可以看到当前的binlog,通过flush logs刷新一个新的binlog出来,那么就已经完成了增量备份和数据还原的基础工作了,剩下的就是通过shell来实现脚本自动化方案了。

spring boot 配置文件加载顺序

spring boot 配置文件加载顺序

近日spring boot项目上线问题良多,先不说打包问题,单纯配置文件使用问题就担惊受怕的。因为上线前解压了一下jar包看了一眼,发现properties文件也被打进去了,所以程序员不敢替换启动,生怕动了配置导致生产环境问题,这里对spring配置的加载文件做一个梳理:参考:https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

spring boot的配置文件加载顺序为

1.当前目录下的config子目录
2.当前目录
3.classpath下的config目录
4.classpath根路径

从上到下加载顺序,可以自行做个测试。

让我们抵制996

按照劳动法规定,996 工作制下只有拿到当前工资的 2.275 倍,才在经济账上不吃亏。

最近在程序员圈子中,抵制996的风潮越来越大,甚至在github上的Star已经十八万多了,甚至Python之父也期望能为天朝可怜的程序员做点什么。围观地址:https://github.com/996icu/996.ICU

圈外的人不太明白什么是996,这里解释一下什么是996:“996”工作制,即每天早 9 点到岗,一直工作到晚上 9 点,每周工作 6 天。

这是不人道的,因为有法可依:

按照劳动法规定,996 工作制下只有拿到当前工资的 2.275 倍,才在经济账上不吃亏。

什么是 996.ICU?工作 996,生病 ICU。

我们不谈996是不是应该(这个谁说都有道理),是不是人道(无脑强制加班肯定不人道),我想说的是你是不是热爱:

06年的时候我开始正式涉足程序员这个行业(我的第一个职业,至今还未转行),那个时候是一个非常菜非常菜的菜鸟(现在也很菜,只不过长胖了许多,就称之为菜鸡吧)。那时候进入这个行业是因为真的“热爱”,要说多热爱吧,只是那个时候非常热爱打游戏,做了程序员就有机会天天在电脑上打游戏了,毕竟那个时候电脑还真的不算普及,但是疯狂的玩过游戏后剩下的就是空虚,感叹开发游戏的是“疯子(天才)”,玩游戏的是“傻子”,荒废时间最终埋单的还是自己,我想既然说自己热爱,那就干脆假装一下热爱吧,因为那时候配一台不错的电脑也不便宜,就这样丢下也挺心疼的,于是乎,哎~呀~,假戏真做了。

是的,一发不可收拾,虽然我终究没有能够从事游戏的开发,但是对各种业务系统,对数据的处理,对能够帮助别人用程序解决繁杂的人力、脑力、体力问题产生了极大的兴趣。

然后仿佛打开了另一个世界的大门,简直太好玩了!一天到晚就在电脑前噼里啪啦的各种敲,各种调,各种生闷气又哈哈大笑,后来去了魔都从事酒店客房服务产品的开发,也拥有了第一台笔记本,我还记得是dell xps M1330,那个时候还没有996一说,加班也未被提到一个高度,只是当时研发部同事很少有人按时下班,偶尔按时一次,就像做贼一样,那种感觉好像学渣听见下课铃响了欢天喜地的要出去玩,但是发现学霸都在桌上认真学习自己又不好意思了,默默的坐下也读起书来。

因为热爱,所以热爱

是不是大家觉得很自虐?下班不回家,比赛加班?其实当时也没有意识,是因为真的热爱,所以没有意识到自己在加班,感觉自己有很多问题还没有解决,有很多技术点还没有攻克,桌子上还放着许多案头书,遇到问题抓起来就查阅资料,然后放下书去敲代码,调试,遇到问题再去查阅,这样反反复复,当你处理完一个问题之后才发现天已经黑了,再不回去就赶不上地铁了,回到家也是看技术文档书籍,晚上睡觉前还要review一下白天遇到的问题,走过的弯路,甚至晚上做梦都在思考未突破的技术点,忽然想到了解决方案从梦中惊醒,跳起来抓起笔就记在本子上,如果笔记本在身边立马开机调试。就是这样一个状态下去工作,真的很快乐,成长也很快。

随着时间的推移,年纪越来越大了,发际线越来越高了,手下的人也越来越多了,但是早年的那个氛围却不在了,早些年面试的时候我问你为什么选择这个行业,得到的答案是“我喜欢!”,这些年在面试的时候得到的答案五花八门了起来“我朋友做这个”,“我家人有做这个”,“人家说程序员工资高”,“这个好找工作”……

团队钻研的精神越来越少了,BUG越来越多了,现在一个项目团队的分工也越来越精细化,参与的人员也越来越多,但是进度却越来越慢了。我想知道,这个群体还有多少人是因为热爱才进入这个行业,你热爱的这个行业,你会计较你是否多做了半小时?一小时?

我觉得很多人仅仅是为了糊口,所以工作也变成了应付,甚至麻木,机械性的复制、粘贴,然后下一个模块。

很多人认为程序员30岁是一个坎,35岁就该转行了,还在敲代码太失败了,但是真的这样吗?难道年龄真的是一道坎吗?我想并不是,心态才是,年纪大还在坚持敲代码并不是能力不行,是因为他还热爱。

所以这个996抵制也没有意义,试想一下,你不爽可以离职,你看看后面排着队等着996的是不是一眼望不到头,在抵制之前你想一下自己是否尽力了,自己是否还在成长,还是自己已经到了混日子的状态了。

我想这个所谓的996也许会是一个筛选器,它会过滤掉混日子的人,留下真正有能力,热爱的人,他们绝对不会低效的加班,他们一定会高效的解决问题,他们不会纠结996与所谓的2.275倍工资,他们获得的是价值,这个价值不光包含薪酬,还有他的快乐和成就感。

我们是程序员,我们这个群体最擅长的就是思维活跃找到问题的解决方案,并不断的调试、修正,最终成功交付,所以这个996也绝对不是发起网络的抵制能解决的,最终还是会修正现状,朝着一个更好的方向发展的,因为热爱,所以你别放弃,如果你不热爱,请马上放弃,你做你热爱的事情,那样你就不会再纠结你是不是在加班?你该拿多少工资。

我怀念我刚入行时,大家还被称为    “软件工程师”。

2019-0409 备忘录

大约3800年前,《汉谟拉比法典》向我们传达一条人类进化的原则——在人与人的交往中建立对称关系,以防有人转嫁隐藏的“尾部风险”。古往今来,人类的任何一条法律,任何一项教谕都是基于“对称性”原则的,实际上,非对称风险一直存在于人类的历史之中。

在座的各位大家好,并不是很高兴坐在这参与这个会,因为这是反思会,我们为什么要开这样一个会呢?因为我们遇到了一些问题,而这些问题桎梏着我们,所以我们不得不在这做一个反思。
首先想问一下在座的各位两个问题:

1.如果公司挂掉了,你有什么打算?会去找一份新工作吗?我想会的除非你有矿。

2.如果公司成功了,各位实现了财务自由有什么打算?会去找一份新工作吗?我想不会的,因为你有矿了。


就目前的公司氛围来说大家应该能感觉到,我们在这讨论的是第一个问题,或许有些悲观,但是事实确实如此。在说这个问题之前我说一下《汉谟拉比法典》
大约3800年前,《汉谟拉比法典》向我们传达一条人类进化的原则——在人与人的交往中建立对称关系,以防有人转嫁隐藏的“尾部风险”。古往今来,人类的任何一条法律,任何一项教谕都是基于“对称性”原则的,实际上,非对称风险一直存在于人类的历史之中。
这里举两个法典中的例子,大家感觉是否公平?

  • 如果一个建筑师建造的房子倒塌并致屋主死亡,则建造该房屋的建筑师应该被处死。

大家感觉公平吗?大家觉得很公平吧?

  • 如果一个建筑师建造的房子倒塌并致屋主的儿子死亡,则建造该房屋的建筑师的儿子应该被处死。

怎么样?是不是这个就觉不太坚定了。


这里我们想一下,在座的各位有多少是享受公司成长带来的红利,但是却不承担公司失败带来的风险的呢?我们思考一下自己是否也在这个不对称中,你是否考虑过让自己进入风险共担(skin in the game)的状态呢? 假如公司挂了,我想有些人只是失业,有些人,甚至家庭都会陷入危机之中,请在座的各位考虑一下之与每个人,这是否公平?这就是之前说的,享受到公司成长带来的红利却不承担失败带来的风险,这就是权利和责任的不对称,最终导致的是有些人如履薄冰,有些人碌碌无为得过且过,你是否有达摩克斯利之剑的意识,因为靠承担风险营生的人终将会被风险吞噬,靠混日子过生活的人一定会被生活抛弃。
这就是我看到的问题现象,但是有问题并不代表完蛋了,恰恰相反,有问题才说明我们还在发展着,问题本身不是问题,如何应对才是问题,尤其是应对的这个人。
这里我说四点建议,与大家共勉:
1.接受现实,认识到问题,了解无知之错与无能之错,我们现在遇到的问题,之前是无知之错,假如我们视而不见,那就是无能之错了。所以还是要保持时刻学习的动力,不断让自己精进。
2.远离舒适圈和跳出能力陷阱:我们都是厌恶风险和不确定性的,我们暴露出来的是能力短板足够的短,但是能力的长板又不足够的长,这样我们就慢慢的蜷缩到了自己营造的舒适区里面不愿意出来,后果就是长板短板都不行,逐渐就失去了自己的位置了。
3.向身边的人学习,放下所谓的嫉妒和所谓面子,俗话说三人行必有我师,我们不能只看到别人的短处而不看别人的长处,我们不能构建自己的团队都在自己的能力之下,这样无异于武大郎开饼店,一个比一个矮的陶瓷娃娃现象,那就真的是将怂怂一窝了。
4.打开上升下沉的渠道,进了股东圈,上了管理层并不代表有特权了,相反是承担了更多的责任,这个责任就是不断提升自己的能力专长也同时做好管理与修正工作,解决传帮带问题,让有能力的人上来,倒逼你进步,假如你不愿意进步,那就做好下沉的准备。

最后我想说的就是:少说话多做事,宁可只做不说也不要只说不做,千言万语不如两横一竖,干就完事。
狼吃肉狗吃屎,这是自然界进化的法则,在座的各位都是想吃肉的,甚至都不是奔着喝汤来的吧,那如果都是小白兔,注定是吃不到肉的,我想这里是可以达成共识的,既然大家在这条船上,那就一起努力,以奋斗者为本,因为你的对手不在这个团队里面,这里都是你的队友,希望大家共勉。
这时候我们再回过头来考虑一开始我提出的第二个问题:“财务自由你想做什么?”,请你认真想一想,那我们剩下的就是如何达成这个目标的过程了。你看,其实我们有一个共同的目标。

show databases; (errno: 13 – Permission denied) MySQL填坑记

安全等保要求云服务器有堡垒机,防火墙,有漏洞感知,有安全防护,入口需要有负载,服务器需要有冗余,数据库需要主备…… 同时还要保留5年的所有日志(真叫人头大)。

一系列扫描,修复漏洞Fixed,然后告知在本地在弄一个容灾以及备份机。

嗯,以上是背景,有很多同学过来已经不耐烦了,妈蛋!老子遇见的是 show databases; (errno: 13 – Permission denied) 这个糟心的错误。

恩是的,这个BUG困扰了我一下午。那就梳理一下问题的几个关键点:

首先是起因:本地容灾服务器安装好了各种环境,MySQL数据库版本也统一为5.6,为了以后的日志保存500年,所以讲默认村主路径做了调整,由原来的/var/lib/mysql 调整到/data/mysql 下。然后就是修改mysql.cnf中[mysqld]下的datadir以及socket保存路径。然后就是一通操作 cp -rp /var/lib/mysql/*  /data/mysql   然后确认就是权限,文件夹下的用户属性,用户组属性。这些相比大家都应该踩过了。

然后启动mysql,接下来可能会遇到两个问题:

1.Can’t open the mysql.plugin table. Please run mysql_upgrade to create it.

2.启动成功,登录mysql后使用show databases;的时候 出现errno: 13 – Permission denied,同时你使用 use mysql;切换数据库竟然正常。(这时候你应该有些波澜了)。

解决:首先一遍一遍的确认配置文件,文件夹权限,启动用户,然后每次启动都会都是一样的错误(假如时间超过1小时工程师会崩溃的)

然后就是把你的错误日志一遍一遍的扔进百度,得到的答案永远都是让你确认权限,文件夹属性(不知道他们真的解决了还是抄无脑转载的),然后你开始怀念Google在的日子(怀念一下被GFW封杀的ssh Proxy网站和那上万的会员。)

在无奈之后还是转向了Google,终于找到几点痕迹。

万恶的SELinux和同样坑爹的apparmor

关闭SELinux  使用 setenforce 0  然后永久关闭,修改/etc/selinux/config文件中设置SELINUX=disabled 重启。

如果是 apparmor 修改/etc/apparmor.d/usr.sbin.mysqld文件里面新增:

#这里面写新的datadir目录,写2行,一行r,一行rwk。
/data/mysql/ r,
/data/mysql/** rwk,

然后重启,填完回家。

系统id迁移

最近一段时间原平铝厂的系统发生id重复事件,起因是负载均衡造成的。查找id server 的时候,无意间发现了twitter的id生成器。决定将系统改造一版。

一路走来感觉很艰辛,但是值得了。主表t_pm一万条,级联表t_pm_item十万条。

优化前:

select * from t_pm_1 t left OUTER join t_pm_item_1 tpi on t.kid=tpi.pm_id where t.pm_name like ‘%a%’ limit 501,200;

200 rows in set (1.17 sec)

优化后:

200 rows in set (0.56 sec)

多次执行,时间偏差不大。查询速度提升给力,效果可观,值了!

下面说具体的ID迁移过程:

1.备份库.同时将数据导出 sql.txt

java写个函数:提取sql.txt所有的uuid,替换为newid。

记录替换过程,old_id <–> new_id 替换表。

将sql.txt导入数据库, 记录为新库 ndb .

2.修改java model类

*****特别注意****:将主键、链接键由 uuid String 改为 Long

*****特别注意****:区分model类型: 日期全部用 long , id方式全部为 Long

3.再写一个java函数,读取所有model long类型数据,逐个修改表结构

alter table @table change `@column` `@column` bigint

4.java json 方式向网页发送的 newid 太长 ,18位, js无法识别

需要在 转换json 的时候批量替换 long类型为string类型

5.最后是系统的全流程测试。

需要迁移的伙伴私聊我qq 398479251 发代码。

jquery validationEngine Ajax 动态参数问题

Jquery validationEngine 是个不错的验证插件,不过ajax相对坑较多,列举一个简单的ajax的代码示例

$("#form2").validationEngine({
	scroll : false,
	promptPosition : 'topCenter: -80, 0',
	ajaxFormValidation : true,
	ajaxFormValidationURL:"${path}/mp/user/edit.htm",
	ajaxFormValidationMethod:"post",
	onAjaxFormComplete:doEdit,
	onBeforeAjaxFormValidation:readySubmit
});

可以看到表单使用ajax验证,方式是 POST,验证完成提交的方法是 doEdit();
我们在 表单的代码如下:

checkUserName 的 js代码如下:

"checkUserName" : {//判断用户账号是否可用
  'url' : $("#basePath").attr("val")+'/ajaxCheck/checkUserName.htm', /* 验证程序地址 */
  'extraDataDynamic' : ['#uid'], /* 额外参数 */
  'alertText' : '该用户已经存在',
  'alertTextLoad' : '正在验证是否可用'
}

可以看到有个参数“extraDataDynamic”,这个是可以在表单中关联验证的,例如判断账号:因为自己的账号本身就存在,如果这里不做关联判断,是无法提交的,
因为文档大部分参数是“extraData”,直到看了源码才发现这块,以后大家躲一躲吧。

var errorSelector = rules[i + 1];
var rule = options.allrules[errorSelector];
var extraData = rule.extraData;
var extraDataDynamic = rule.extraDataDynamic;

使用jvisualvm 监控服务器VM

最近业务服务器在早上并发时出现地区性无法响应问题,初步推断是内存爆掉,导致swap交换不过来了,为了寻找占用内存的怪兽,使用jvisualvm协助监控。

环境JDK1.8,在jdk下的bin目录提供了很多优秀的工具,例如:jvisualvm

然后在服务端启动jstatd。在当前目录下心间jstatd.all.policy文件

grant codebase "file:${java.home}/../lib/tools.jar" {  
   permission java.security.AllPermission;  
};

命令启动:

./jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.hostname=192.168.1.233

然后本地使用jvisualvm连接吧:)
69eaf9d5-5de0-42ee-a938-fcd5fbf50c4f