MySQL 日期/时间类型选型与时区处理

适用版本:MySQL 8.0+ / Laravel 10+。MySQL 5.7 已 EOL,文中不再覆盖。 一句话结论 「物理时刻」(事件发生于何时)→ TIMESTAMP,自动跟随会话时区转换 「字面值」(合同上写的、用户输入的日期)→ DATETIME,原样存取不转换 仅日期 → DATE;仅时长 → TIME;JS/跨语言毫秒戳 → BIGINT 永远不要用 VARCHAR 存日期——无强制约束、无法范围查询、排序按字符串 选型对照表 类型 范围 字节 时区行为 小数秒 典型场景 DATETIME 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 5 + fsp 字符串原样存取,不转换 DATETIME(0~6) 合同生效时点、用户填写的本地时间、历史事件 TIMESTAMP 1970-01-01 00:00:01 UTC ~ 2038-01-19 03:14:07 UTC 4 + fsp 写入:会话时区 → UTC;读取:UTC → 会话时区 TIMESTAMP(0~6) created_at / updated_at、日志、跨时区事件戳 DATE 1000-01-01 ~ 9999-12-31 3 — — 生日、纪念日、报表日期 TIME -838:59:59 ~ 838:59:59 3 + fsp — TIME(0~6) 营业时长、计时器 YEAR 1901 ~ 2155 1 — — 罕用 BIGINT INT64 8 应用层控制 — JS 毫秒戳、Unix 微秒戳、跨语言互操作 小数秒(fsp,fractional seconds precision) 0~6 位,每 2 位多占 1 字节。Laravel 11+ 默认就用 DATETIME(6) / TIMESTAMP(6)。 ...

May 25, 2018 · 3 min · 468 words · Me, LLM

【Modern PHP】笔记

又回到 PHP Web 开发,使用 Laravel 框架,重读《Modern PHP》。 PHP 正在重生。 特性 命名空间 声明命名空间: <?php namespace Oreilly\ModernPHP; 导入和别名: <?php use Symfony\Component\HttpFoundation\Response as Res; $r = new Res('Oops', 400); $r->send(); PHP 5.6 开始可以导入函数和常量: <?php use func Namespace\functionName; use constant Namespace\CONST_NAME; functionName(); echo CONST_NAME; 使用接口 接口是两个 PHP 对象之间的契约,其目的不是让一个对象依赖另一个对象的身份,而是依赖另一个对象的能力。 使用接口编写更加灵活,能委托别人实现细节。 性状 trait 性状是类的部分实现,可以混入一个或者多个现有的 PHP 类中。性状有两个作用:表明类可以做什么(像是接口);提供模块化实现(像是类)。 如果想让两个无关的 PHP 类具有类似的行为,应该怎么呢?性状就是为了解决这种问题而诞生的。性状能把模块化的实现方式注入多个无关的类中。而且性状还能促进代码的重用。 这与创建一个接口,两个无关的类实现这个接口的优势在于:不用写相同的实现代码,符合 DRY 原则。 PHP 解释器在编译时会把性状复制粘贴到类的定义体中,但是不会处理这个操作引入的不兼容问题。如果性状假定类中有特定的属性和方法(在性状中没有定义),要确保相应的类中有对应的属性和方法。 生成器 Generator 是 PHP 5.5.0 引入的功能。生成器是简单的迭代器,仅此而已。 PHP 生成器不要求类实现 Iterator 接口,从而减轻了类的负担。生成器会根据需求计算并产生要迭代的值。这对应该的性能有重大影响。假如标准的 PHP 迭代器经常在内存中执行迭代操作,这要预先计算出数据集,性能低;此时我们可以使用生成器,即时计算并产出后续值,不占用宝贵的内存资源。 PHP 生成器不能满足所有迭代操作的需求,因为如果不查询,生成器永远不知道下一个要迭代的值是什么,在生成器中无法后退和快进。生成器还是一次性,无法多次迭代同一个生成器。不过,如果需要,可以重建或克隆生成器。 PHP 生成器是 PHP 函数,只不过要在函数中一次或者多次使用 yield 关键字。生成器从不返回值,值产出值。 function myGenerator() { yield 'value1'; yield 'value2'; yield 'value3'; } foreach (myGenerator() as $yieldedValue) { echo $yieldedValue, PHP_EOL; } value1 value2 value3 使用生成器处理 CSV: ...

May 8, 2018 · 3 min · 573 words · Me

用 Certbot 自动化 Let's Encrypt TLS 证书

Certbot 和 Let’s Encrypt 的关系 Let’s Encrypt 一个免费、自动化、开放的公共证书颁发机构(CA)。 通过 ACME(Automatic Certificate Management Environment,RFC 8555)协议向域名所有者颁发 DV(Domain Validation)TLS / SSL 证书。 Certbot 由 Electronic Frontier Foundation(EFF)维护的开源 ACME 客户端。 主要目标是简化与 Let’s Encrypt 之间的交互: 自动化域名验证(HTTP-01、DNS-01、TLS-ALPN-01) 安装并续期证书 更新 Web 服务器配置(Apache、Nginx、Lighttpd 等) Certbot 也能与任何兼容 ACME 的 CA 通信,不限于 Let’s Encrypt。 ACME 挑战怎么选 挑战 适用场景 限制 HTTP-01 80 端口可达、单域名 / 多域名(最常用) 不能签 wildcard DNS-01 任意域名 —— wildcard 唯一选项 需要 DNS provider API 或手动加 TXT TLS-ALPN-01 443 可达但 80 被封,常用于反代后端 较少用,需要 ACME-aware 反代支持 典型工作流程 解析参数并检测服务器类型。 选择并执行挑战(HTTP-01 例:在 /.well-known/acme-challenge/ 下写入 token)。 Let’s Encrypt 回访验证域名归属。 验证通过后签发证书;Certbot 下载并安装到本地。 创建 systemd timer(snap 安装会自动配置)周期性 certbot renew 续期。 开始实验 实验环境:Amazon Linux 2023(AL2023)。AL2023 没有官方 certbot 包,社区维护的 snap 仓库是当前最省事的安装路径。 ...

April 26, 2018 · 4 min · 815 words · Me, LLM

【Git 权威指南】读书笔记 - 协同

【Git 权威指南】“和声”+“协同模型"两章的精炼合并版:远程协议、推送与冲突解决、里程碑共享、分支协同、工作流模型、共用代码(submodule / subtree)。 本文沿用书中 master 作为默认分支名;Git 2.28+ 默认改为 main,行为完全一致。 远程协议与版本库 协议选择 协议 用途 现状 SSH 推 + 拉,需公钥认证 协作首选 HTTPS 推 + 拉,凭证由 helper 缓存 网络受限环境首选;个人项目常用 本地 file:// 或裸路径 备份 / 镜像 git:// 只读匿名协议 已弃用,GitHub 2022 年关停 FTP / RSYNC — 已弃用,忘了它们 ssh://[user@]example.com[:port]/path/to/repo.git [user@]example.com:path/to/repo.git # SSH 简写 https://example.com/path/to/repo.git 远程版本库管理 git remote -v # 列出 fetch/push URL git remote add <name> <url> # 注册 git remote set-url <name> <url> # 改 URL git remote set-url --push <name> <url> # 单独改 push URL(读写分离) git remote rename <old> <new> git remote rm <name> git remote update # 拉取所有 remote 的更新 git config remote.<name>.skipDefaultUpdate true # 排除某个 remote fetch / pull 的关系 git pull = git fetch + git merge # 默认 git pull --rebase = git fetch + git rebase 习惯用 rebase 整理历史的人,全局开启: ...

January 17, 2018 · 5 min · 952 words · Me, LLM

回顾 2017

2017 关键词:Birds、离职、狼人杀、白洋淀、iOS、自如。 Birds Birds 是自己编写时间最长的一个 Web 项目。项目接手、改版、重构、迭代、盈利,上半年每天工作都是面对它。 Birds 良好的表现与需求互相推动,这点很重要,假如有需求而项目没有成长,或项目成长没了需求,对工程来说都只能是纸上谈兵、无事可做。项目中的规范的重要性,无论是代码还是数据库,只要项目不是夭折终将显现,对于规范性我绝不会开倒车,做任何妥协,种种经历只说明:这里欠的东西总会还。如何应对需求的千变万化,小结几点:模块化、组件化思想,功能多可配置,功能可拔插,功能方法粒度要小;不要对程序肆意进行打补丁式的修改,减少对流程入侵;当某一处的逻辑增加时要及时重新修改、定义流程;对需求目的的正确理解更是能高效开发。 对前端重新认识的一年。现在的前端和大学时刚刚接触时,已经大不一样了。前端能做的事情越来越多,很多业务逻辑都在前端处理,服务端只需要提供接口,分工合作更容易。浅尝 React Vue Webpack 后,也许前端才是自己的归宿。 离职 离职的不是我。老人走,新人来,新人走。离职一词在我身边跟了一年都没有停下来。同事离职的原因很多,离开北京、公司发展、自我发展… 马云说离职的原因就两个:1. 钱没给够。2. 受了委屈。我起初是认同这一说法的,但是后来觉得 “人” 或者说 “人的思想” 或者说 “人性” 在其中影响作用非常的大。相同的事情不同的角度看,结果相去甚远,如果基本的理念不同,那事情基本是无法调和的。 对做的事情的认同感,对自我的定位与认识,对现实情况的冷静思考,这几点需要反复咀嚼。 分享一篇文章:公司没大牛带,需要离职么?。对于刚入门的我们,这是一个很有代表性的问题。太多时候我们期待别人,忘了自己。公司有大牛,能跟着学是幸运,没有是常态。先接受了这个设定,会更容易找提高自己的方法。有没有大牛并不重要,我们是为了那个更好的自己。 狼人杀 2017 火的游戏很多:狼人杀、守望先锋、王者荣耀、吃鸡。狼人杀这一杀,好像杀到了毕业前和同学舍友在一起臭 high 的日子。可说骚话、互相 diss、互相吹捧,真真假假其乐无穷。最赤鸡的是鱼炸出了个女盆友,各路同学亲上加亲,无法克说。 白洋淀 我想 你说 你不要在孤单 让我做你的伴 白洋淀去过四次,那里的温泉过去两次,年中 Team Building 再喜加一,而这一次让这里有了美丽故事。喷泉、沙发,出现了对的人。 iOS React Native 的一波尝试后,走上了移动开发的道。Swift 让上 iOS 车的门槛降低不少,Swift API 趋向稳定,可以说这是最好的时候。GitHub 应该是再也放不下了,外文的书籍、文档确实靠谱啊,推荐一个教程网站 iOS Tutorials - Ray Wenderlich 真的零基础入门。 我相信:一个人语言的界限,就是他世界的边界。 自如 一场大火让无数人无家可归,年末换房也受牵连。被自如圈粉,其他中介的房子真的太 low 了。自如订房子居然也要抢,一波三折、失而复得。在没抢到房子时,真的想走,想离开这里了,很凄凉。最终是在公司对面住下了,过上了在家吃中饭晚饭的日子。 2018 Happy New Year 2017 自己是幸运的,2018 猥琐发育,不要浪,胜利属于伏地魔。 ...

December 31, 2017 · 1 min · 73 words · Me

【Git 权威指南】读书笔记 - 独奏

【Git 权威指南】“初识 Git” + “独奏"两章的精炼合并本:背景、安装、初始化、暂存区、对象模型、引用游标(reset / checkout / stash)、里程碑、文件操作、历史查看、改变历史、克隆。 本文沿用书中 master 作为默认分支名。Git 2.28+ 默认改为 main,行为完全一致。 前传:diff、patch、分布式 Git 之前,源码协作靠 diff + patch 这套老组合: diff -u hello.old hello.new > hello.patch # -u: unified 格式,带上下文,是补丁的必备参数 patch hello.old < hello.patch # 升级到 new patch -R hello.old < hello.patch # -R: 反向,回到 old patch -p1 < changes.patch # -p1: 跳过路径首层,用于跨目录补丁 补丁文件长这样: --- hello.old 2026-05-14 10:00:00 +++ hello.new 2026-05-14 10:05:00 @@ -1,3 +1,3 @@ hello -world +git ! Git 的 git diff / git apply / git format-patch / git am 就是这套机制的强化版 —— 加了对象寻址、历史图谱、合并算法。 ...

July 19, 2017 · 9 min · 1742 words · Me, LLM

NGINX 启用 HTTP/2

简介 HTTP/2(RFC 7540,2015 年发布)是自 1999 年 HTTP/1.1 以来的第一次重大升级,目标是在不改变应用语义的前提下,改善延迟、并发和网络效率。浏览器端基本只在 TLS 上启用(h2),明文 h2c 仅用于内部服务间通信。 h2:HTTP/2 over TLS(最常见,浏览器只支持这一种) h2c:HTTP/2 over TCP(无加密) 设计背景 移动端和富媒体时代请求量激增,HTTP/1.1 的队头阻塞、多个 TCP 连接并行带来的慢启动 / 拥塞竞争成为瓶颈。 谷歌的 SPDY 原型验证了「单连接、多路复用、压缩头部」的思路;IETF 在 SPDY 3.1 基础上标准化为 HTTP/2。 核心特性 特性 作用 二进制分帧(Binary Framing) 把 HTTP 报文拆成小型 Frame,机器易解析、可并行 多路复用(Multiplexing) 多个请求 / 响应共享一个 TCP 连接,互不阻塞 流与优先级(Stream & Priority) 每个请求是双向 Stream,可指定权重与依赖 头部压缩(HPACK) 静态 Huffman + 动态表,大幅减少重复 Header 字节 服务器推送(Server Push) Chrome 106(2022-09)已移除,由 103 Early Hints 取代 流量控制 端到端窗口,避免单个大文件占满带宽 多路复用解决的是应用层队头阻塞 —— TCP 层的队头阻塞依然存在(任意一个包丢失,连接上所有 stream 全停),这正是 HTTP/3 改走 QUIC over UDP 要解决的问题。 ...

June 6, 2017 · 2 min · 326 words · Me, LLM

【摔跤吧,爸爸】随笔

周末看了《摔跤吧,爸爸》,也是第一次独自电影院看电影,试写一篇影评纪念下。 注意:严重剧透预警。 主角爸爸是印度全国摔跤冠军,一心想着为国家赢取一枚金牌。可自己没能实现梦想,把梦想转移给了自己还未出世的孩子。可事与愿违,想要男孩的主角爸爸的前三个孩子都是女孩,第四个还是女孩。主角爸爸近乎要放弃为国争取金牌的梦想时,却意外看的了大女儿、二女儿身上的摔跤天赋。 主角妈妈在得知主角爸爸准备将女儿们训练为拳击手时,道出了 “你不能将你的梦想施加在女儿们身上”,主角爸爸沉思片刻 “给我一年时间,其间你不要插手,如果没成功,我将有永远放弃我的梦想”。在主角爸爸说出这句话之前,我是反对父母将自己的梦想让孩子去实现的,也更没有去争取过孩子们的想法,现实中这样做的父母我是常为 Loser. 但是主角爸爸的回答让我看到的不是一个:被自己个人梦想冲昏头,用孩子的全部去成就自己的父亲。主角爸爸是讲道理的,一年后如果失败也会甘愿放弃。坚持与固执的区别也许就在此。 主角爸爸变身为女儿们的魔鬼摔跤教练,每天除了上学就是训练,跑步时衣服不合适换男生衣服,找侄子当陪练,没有力量加餐牛奶、鸡肉,长头发难清理剪成了寸头。受苦中的女儿们找妈妈求情,主角妈妈遵守承诺,不干预主角爸爸的训练。这里真的要给主角妈妈点赞,后面女儿们的成功,女儿们、主角爸爸的努力在明面放着,而主角妈妈的守诺不干预,对主角爸爸的信赖,是同样的伟大。不然那柔弱的耳边风不知乱了多少坚定的意志。 训练太辛苦的女儿们采用消极怠工对抗主角爸爸。破坏闹钟、破坏场地、假摔示弱。而旷工一天参加好友的婚礼现场被主角爸爸收拾。在与好友诉苦时,才发现了:对比其他女孩一望到底的家庭妇女人生,主角爸爸的狠心是那样让人羡慕。 观念改变的女儿们开始主动训练。大女儿首次参赛就初露锋芒,差一点将男孩对手打败。逐渐成长的大女儿愈战愈勇的直到赢得全国冠军。全国冠军都会进入国家体育学校学习,大女儿也要离开主角爸爸接受新教练的训练,备战世界大赛。从小镇走出来的大女儿,没了主角爸爸的严格管束,开始着迷于这外面多彩的世界。吃油炸食品、留起头发、逛街、电影院。假期回家的大女儿用自己新学的技巧击败了主角爸爸,更是产生自我膨胀,对主角爸爸传统技术技巧的不屑与不信任。 国际大赛上大女儿频频失利,无能教练将此归为命运。与此同时坚信主角爸爸训练方式的二儿女也获得全国冠军,进入国家队。在二儿女和主角妈妈的劝解下,一通电话化解了大女儿和主角爸爸的隔阂。主角爸爸亲自来到体育学校,为大女儿备战下次的国际大赛。 主角爸爸在仔细研究大女儿对手后,制定了针对性的战术帮助大女儿杀入决赛。无能教练为了不让主角爸爸抢了自己的功劳,在决赛开始前将主角爸爸骗入小黑屋,无法让主角爸爸指导大女儿比赛。决赛第二局大女儿没能把握赛点,让对手追平。主角爸爸继续被困,只能默默祈祷。决赛最后一局,大女儿大比分落后,最后 10 秒大女儿脑海闪现着主角爸爸的叮咛,一击 5 分绝杀翻盘,赢得世界冠军。冠军的国歌声奏起,小黑屋中的主角爸爸也被路人解救,冲入赛场的主角爸爸与大女儿四目相对,此时这已经不是大女儿或主角爸爸哪一个人的冠军,而是所有正在与命运抗战者的胜利。 主角爸爸:“你是我的骄傲” 电影的专业手法和技术自己不懂,但是自己有个感觉:影片后期有大量的摔跤比赛,时不时有种看奥运赛的感觉,但是自己并没有感到乏味。电影故事情节很寻常,但是娓娓道来,很多细节小事让节奏不拖沓。故事人物有主角爸爸的理性和坚持、主角妈妈的守诺不干预、女儿们自我的成长、侄子的酱油加醋、无能教练损人为己 电影给我也留下了几个现实问题: 父母的认识经验一定比子女高的多,主角爸爸在看到女儿们的摔跤天赋时,狠心训练与女儿本身的意愿如何选择? 父母逐渐变老,他们真的跟不上我们了吗? 如何辨别无能教练的瞎指挥? – EOF –

May 14, 2017 · 1 min · 26 words · Me

MySQL 管理用户与访问授权

适用版本:MySQL 8.0+。5.7 已于 2023-10-31 EOL,本文不再覆盖其语法(如 IDENTIFIED BY 嵌在 GRANT 里、PASSWORD() 函数等均已移除)。 速查 -- 建用户 + 授权(8.0 必须分两步,GRANT 不再支持隐式建用户/带密码) CREATE USER 'tom'@'%' IDENTIFIED BY 'pwd123'; GRANT ALL PRIVILEGES ON *.* TO 'tom'@'%' WITH GRANT OPTION; -- 查 / 改密 / 删 SHOW GRANTS FOR 'tom'@'%'; ALTER USER 'tom'@'%' IDENTIFIED BY 'new_pwd'; DROP USER 'tom'@'%'; 用户 创建 CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 字段 含义 username 账号名 host 允许从哪个主机登陆。localhost 仅本机;% 任意远端;192.168.1.% 限定网段 password 登陆密码,可省略(不建议) 8.0 的默认认证插件是 caching_sha2_password(5.7 是 mysql_native_password)。绝大多数现代客户端已支持;但 PHP mysqlnd < 7.2.8、部分老 ORM/客户端连不上时,单独为该账号回退插件: ...

April 11, 2017 · 3 min · 635 words · Me, LLM

让 Git 线图说话:pull rebase + merge no-ff

git log --graph 中清晰的提交线图方便 code review 和回退定位。两条互补的策略:git pull --rebase 把无意义的分叉抹平,git merge --no-ff 把一组相关提交刻意保留成一个"鼓包"。看起来矛盾,目的一致 —— 让线图表达意图,而不是过程。 pull –rebase:抹掉无意义的分叉 默认 pull 出了什么 本地和远端各自有了新提交,pull 时若不是 fast-forward,Git 默认 merge,会多出一个没有任何代码意义的"Merge branch ‘main’ of …“提交: 假设 pull 前: A---B---C origin/main / D---E---F---G main git pull(默认 merge)后多出 H: A---B---C / \ D---E---F---G---H main, origin/main git pull --rebase 后线图变平,F G 被基于 C 重放成 F’ G’: D---E---A---B---C---F'---G' main, origin/main 写进配置,不要每次记得加 git config --global pull.rebase true # pull 默认 rebase git config --global pull.ff only # 不能 fast-forward 就拒绝(避免误产生 merge commit) git config --global rebase.autostash true # rebase 前自动 stash 未提交修改 Git 2.27+ 起,未显式配置 pull.rebase 时每次 pull 会警告,等于在催你做一次明确选择。 ...

March 17, 2017 · 3 min · 519 words · Me, LLM