Ubuntu下使用heirloom-mailx发送邮件
基本使用
1 | install |
1 | # install |
通过crontab 命令,我们可以在固定的间隔时间执行指定的系统指令或 shell script脚本。时间间隔的单位可以是分钟、小时、日、月、周及以上的任意组合。这个命令非常适合周期性的日志分析或数据备份等工作。
1 | crontab [-u user] file crontab [-u user][ -e | -l | -r ] |
分 时 日 月 星期 要运行的命令
我个人惯例会把cron文件创建在/opt/cron
目录下
新创建的cron文件的副本会被放在/var/spool/cron/crontabs
目录下,文件名为用户名
1 | # 创建cron文件 |
新创建的cron job,不会马上执行,至少要过2分钟才执行。如果重启cron则马上执行。
当crontab失效时,可以尝试/etc/init.d/crond restart解决问题。或者查看日志看某个job有没有执行/报错tail -f /var/log/cron。
千万别乱运行crontab -r。它从Crontab目录(/var/spool/cron)中删除用户的Crontab文件。删除了该用户的所有crontab都没了。
在crontab中%是有特殊含义的,表示换行的意思。如果要用的话必须进行转义%,如经常用的date ‘+%Y%m%d’在crontab里是不会执行的,应该换成date ‘+%Y%m%d’。`
1 | # 实例1:每1分钟执行一次myCommand |
1 | # 创建定时任务文件 |
1 | sudo apt-get install mysql-server-5.7 |
1 | # root用户登录 |
1 | # e.g.1 |
1 | DROP USER 'jeffrey'@'localhost'; |
The MySQL Access Privilege System
When Privilege Changes Take Effect
1 | # e.g.1 |
1 | # 检查一下3个配置文件是否有host绑定 |
1 | # 查看编码设置 |
1 | mysql -u user -p |
分为物理备份和逻辑备份两种
物理备份是备份的数据元文件,备份恢复快,适合数据量大,压缩率低,占用空间多,需要快速恢复的场景。具体可参考 MySQL Enterprise Backup Overview
逻辑备份是备份DDL,DML语句,备份恢复慢,适合数据量小,压缩率高,占用空间少,恢复速度要求低的场景
具体选择的策略可参考MySQL Backup in Facebook
逻辑备份具体可选用主从复制的方式,从slave节点上进行备份.
贴个逻辑备份脚本
使用hibernate管理ORM时,如果某个映射实体字段为null保存时会报column ‘xx’ cannot be null之类的异常,导致存库失败,为解决这个问题,hibernate提供了动态SQL的机制。
在实体关系配置时,加入dynamic-insert
/ dynamic-update
(对应JPA中的@DynamicInsert
/ @DynamicUpdate
)会在执行插入或更新时动态判断字段是否为null(或是否有更新),如果为null(或没有更新)则不更新这类字段,也就不会产生异常。它的原理是在实体被加载到session中时会保存一份快照,如果在后续的更新操作检测到有更新,则动态生成更新部分涉及到的字段的sql。
就算使用了动态SQL机制,但如果字段在DDL中没有声明默认值,那么当实体字段为null时进行更新,依然会由db层面报出异常。因此要规范DDL,并结合动态SQL机制来避免业务代码出现实体保存时的空值异常。 案例如下:
1 | # java code |
动态SQL的使用是有前提条件的:需要在同一个Session中操作实体才能生效。 前面提到动态SQL的原理是在实体加载到Session中时保留了一份快照,后续操作时比对快照生成正确的sql操作,那么如果一个实体加载和回写使用的Session是不同的,那么自然无法进行快照比对,那么动态SQL的机制也就无法实施,hibernate只好按照默认规则更新全字段。
看个例子:如果我们在Controller层去写业务逻辑(__生产中请务必不要这么干!__)就极有可能会导致@DynamicUpdate
失效,比如下面这段代码。
1 | @RequestMapping("/queryAndUpdate") |
原因是我们一般会把事务控制在Service层,那么在Controller层的业务逻辑加载完一个对象,当对象返回到Controller层其实就已经穿透了事务边界,事务结束,hibernate默认会关闭Session;那么下面再次进入Service层更新这个对象就会开启新的事务,由新的Session来进行执行。
所以我们要想解决上述问题,目标很明确,在Controller中不会因为穿透了Service层而加载新的Session。
Spring为我们提供了OpenSessionInViewFilter
这个过滤器可以轻松的达到上述目的,它将开启一个Session绑定到当前请求线程,这个线程上的Session将会被TransactionManager
利用,因此事务结束(Service层穿透)也不会关闭Session,而是在整个请求周期中复用同一个Session。具体参考_Spring文档_,这里不展开。
至此,动态SQL在整个请求周期内可以正常运行。
另外值得注意的是动态SQL打开了以后,不同对象的sql语句会不一样,如果一次更新多条记录,hibernate将不能使用 executeBatch进行批量更新,这样效率将大打折扣。在这种情况下,多条sql意味着数据库要编译多次sql语句。
因此有批量更新的特殊场景时,建议单独使用hql或者sql进行操作。
一种增强git提交信息表达的图标
官网 https://gitmoji.carloscuesta.me
官方介绍:An emoji guide for your commit messages
基本语法 :word:
将语法写入commit任意位置,即可生成对应icon
icon | word e.g. | explain |
---|---|---|
:recycle: | :recycle: |
Refactoring code. |
✨ | :sparkles: |
Introducing new features. |
:construction: | :construction: |
Work in progress. |
🐛 | :bug: |
Fixing a bug. |
🔨 | :hammer: |
Refactoring code. |
⬆️ | :arrow_up: |
Upgrading dependencies. |
⬇️ | :arrow_down: |
Downgrading dependencies. |
:twisted_rightwards_arrows: | :twisted_rightwards_arrows: |
Merging branches. |
:fire: | :fire: |
Removing code or files. |
:white_check_mark: | :white_check_mark: |
Adding tests. |
⚡ | :zap: |
Improving performance. |
:wrench: | :wrench: |
Changing configuration files. … |
:tada: | :tade: |
Initial commit. |
:art: | :art: |
Improving structure / format of the code. |
生产环境(JDK8u144)中有部分公共数据存在xml中,使用时会将xml数据读取到内存,以 ArrayList
存储,多个用户(多线程)对同一个 ArrayList
使用了 Collections
的sort(List,Comparator)方法进行排序,从而触发了 ConcurrentModificationException
。其本质就是一个并发问题。
1 | @Test |
以上Test Case将复现 ConcurrentModificationException
异常
#ConcurrentModificationException
顾名思义,ConcurrentModificationException
是并发修改引起的异常。追溯 JDK8u144
的 Collections::sort
实现可以发现,最终调用的是ArrayList的sort方法
1 | //Collections::sort |
而在 JDK8u20
之前
1 | @Test |
CopyOnWriteArrayList
1 | @Test |
Api-Mocker
是 丁香园
前端团队开源的一款接口管理软件。集诸如阿里开源的Rap、Chrome的postman等接口相关工具的优点于一身。 github地址
1 | #先安装好mongo(略) |
部署 api-mocker
后服务一直运行,没有备份过数据。一次服务器断电重启后发现mongo的数据全部丢失。因此整个简单的备份方案。
有三种方案可以选择,参考方案选择。这里选用mongo自带的套装命令 mongodump
mongorestore
1 | #!/bin/zsh |
1 | mongorestore $mongo-bak-dir |
用以下命令可以简单测试备份及数据恢复
1 | # 进入mongo CLI |
1 | # 创建定时任务文件 |