news 2026/10/1 3:41:16

SpringBoot+Vue+MyBatis工资系统实战:数据库设计到部署全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot+Vue+MyBatis工资系统实战:数据库设计到部署全流程

去年秋天帮一个学弟改毕业设计,他用SSM写了个工资管理系统,页面丑不说,动不动就数据库连接超时。我花了两个晚上帮他重构到SpringBoot+Vue,顺手整理了一套完整的源码结构。后来好几个朋友找我要这份东西,今天干脆把设计思路和实现要点一次性写清楚——这就是这篇文章的来历。

这套基于SpringBoot+Vue+MySQL+MyBatis的工资信息管理系统,适合三类人看:正在做Java全栈毕业设计的在校生、想快速上手企业级前后端分离开发的自学者、以及需要给公司内部搭建一套轻量工资管理工具的非专业开发人员。它能让你从零跑通“数据库设计→后端接口→前端页面→部署上线”的完整链路,而不是停留在跟着教程敲Demo的层面。

我做这套系统时有几个明确目标:表结构要经得起推敲,不能是那种只为了CRUD硬凑出来的;权限逻辑要真实,财务人员的操作记录必须留痕;前后端要真正分离,Vue打包后能独立部署;代码量控制在合理范围,一个认真学的人两周能看完看懂。下面按我实际开发的顺序来讲,这样更贴近你从头做一个项目的真实节奏。

1. 工资管理系统和普通CRUD Demo的本质区别

很多人觉得工资系统无非就是把员工工资加加减减存进数据库,真正动手后发现完全不是这么回事。这个项目我之所以推荐作为进阶练手项目,恰恰是因为它的业务复杂度恰到好处——比图书管理难,但又没到电商那种量级,做完以后你对“管理系统”这四个字的理解会彻底改变。

1.1 工资计算里藏着的业务复杂度

先说工资结构本身。一份真实的工资单至少包含基本工资、岗位工资、绩效奖金、加班费、餐补、交通补贴、考勤扣款、社保个人部分、公积金个人部分、个税这十来个字段。其中社保公积金各地区的缴费比例不一样,个税又涉及起征点和累进税率,这还不是最麻烦的——麻烦的是不同公司对这些字段的定义千差万别,有的公司把绩效算进基本工资,有的公司单独列项。

从数据库设计的角度,这就引出了一个关键决策:工资字段是直接做成表的列,还是用“工资项+金额”的纵向表?我做过三个项目,最终全部选择了显式字段设计——就是每个工资项占一列。原因很简单:工资系统的查询模式高度固定,按月查询、按员工查询、按部门汇总,横向表结构用一条SQL就能把整张工资单查出来,配合MyBatis的ResultMap映射非常直观。纵向表虽然灵活,但查一次工资单要GROUP_CONCAT或者多次JOIN,写起来费劲,性能还差。

个税计算这块,我直接用BigDecimal封装了一个TaxCalculator工具类。很多人图省事用double算钱,这是大忌。double的二进制浮点表示会导致0.1+0.2不等于0.3这类问题,工资算错一分钱在财务那里都是事故。BigDecimal配合setScale(2, RoundingMode.HALF_UP)四舍五入到分,这是Java金额计算的铁律。

1.2 “管理”二字体现在权限和审计上

工资系统不只是算工资,它是企业内部敏感度最高的系统之一。财务人员能看到全员工资,部门主管只能看到自己部门的,普通员工只能看到自己的。这就是基于角色的访问控制(RBAC)模型,我把它具体化为三个角色:管理员(ADMIN)、财务(FINANCE)、普通员工(EMPLOYEE)。

管理员负责维护员工信息、部门信息、账号分配;财务负责工资录入、核算、发放、导入导出;普通员工只能查看自己的工资条,连别人的月薪总额都不应该出现在列表里。这个权限模型看着简单,但我在后端的Service层做了双重校验——不只靠前端隐藏按钮,每次查询工资列表时Mapper层自动拼接当前用户的部门ID条件,防止有人绕过前端直接调接口。

审计这块容易被忽略。工资数据出了争议,你得能回答“这笔数据是谁在什么时候改的”。我加了一张操作日志表,用Spring的AOP切面统一记录关键操作,修改工资、删除工资、导入数据、导出数据都会落日志。这个功能不需要额外引框架,一个自定义注解加一个Aspect类,几十行代码搞定,但整套系统的可信度完全不一样。

2. 技术栈选型的思考过程:为什么是SpringBoot+Vue+MyBatis

这套技术栈现在几乎是Java全栈开发的标配,但标配不等于没有选型逻辑。我在定方案时做了几组对比,把当时的判断依据写出来,你参考的时候能更明白每一层为什么是它。

2.1 后端:SpringBoot的“约定优于配置”和MyBatis的灵活SQL

后端框架候选方案无非SpringBoot和SSM。SSM的痛点你写一次配置就懂了——spring-mvc.xml、mybatis-config.xml、web.xml三个配置文件来回折腾,光搭环境就能劝退一大半人。SpringBoot用自动配置把这些全部干掉,内嵌Tomcat,一个Application类启动整个Web应用,这对快速搭建和后期维护都是降维打击。

持久层我用MyBatis而不是JPA/Hibernate,核心原因是工资系统里有大量多表关联查询和月度汇总报表,SQL的灵活性太重要了。举个例子,查询某个月的工资汇总,按部门分组统计应发合计、实发合计、社保合计,这种SQL用MyBatis写在XML里看得清清楚楚,调优也方便。JPA那种Entity关联查询在这种场景下写起来绕,还不容易控制最终生成的SQL。当然,单表CURD用MyBatis-Plus更香,这个建议你也采纳,省下的BaseMapper方法足够你多写两个页面。

2.2 前端:Vue加Element UI是效率最优解

前端选Vue2还是Vue3,我纠结了一阵子。如果你的毕设或者项目没有历史包袱,直接上Vue3加Element Plus,组合式API写起来确实比Vue2的选项式API顺手,Vite的构建速度也比Webpack快好几倍。我当时给学弟重构时他项目里还是Vue2,迁移成本高才保留Vue2。新写项目我不推荐再开Vue2了。

Element UI这套组件库我必须多说一句。你用原生HTML+JS开发过管理系统的话会明白它的价值——一个带搜索、分页、批量操作的Table组件,原生写至少要两百行JavaScript,Element UI三行代码搞定,而且样式统一、交互规范。加上Axios做HTTP请求,Vue Router做路由,正好凑齐前后端分离开发的核心拼图。

2.3 中间件和工具链的选型

数据库我选MySQL 8.0。5.7和8.0的语法绝大部分兼容,但8.0的窗口函数对做工资月度同比、部门排名这类报表非常有用,既然是新项目就没必要守着老版本。Navicat做可视化工具见仁见智,它收费,社区版足够用,或者用开源的DBeaver,功能上完全够。

这里需要提醒一个坑:MySQL 8.0默认使用caching_sha2_password认证插件,老版本的JDBC驱动连接时会报SSL错误或者认证失败。解决办法要么在连接URL加useSSL=false来跳过SSL验证,要么换成mysql-connector-java 8.0以上版本的驱动。我后面部署章节还会详细讲。

3. 数据库设计:工资业务怎么建模才叫合理

数据库是这套系统的地基,我花的时间比写代码还多。核心原则只有一条:面向查询设计表,而不是面向录入设计表。工资系统录入是一次性的,查询是反复的,设计时优先保证查询的效率和便利。

3.1 六张核心表的结构和关联关系

我最终落了六张表:用户表、员工表、部门表、工资表、工资明细表(历史版本)、操作日志表。用Navicat建完表之后再在MySQL Workbench里生成ER图看关系,方便后期写文档。这里直接把核心表结构贴出来。

用户表管理登录账号,和员工表一对一关联,密码用MD5加盐存储。注意用户名要建唯一索引,这是安全底线:

CREATE TABLE `sys_user` ( `id` int NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL COMMENT '登录账号', `password` varchar(128) NOT NULL COMMENT '密码加盐后MD5', `salt` varchar(20) NOT NULL COMMENT '盐值', `role` varchar(20) NOT NULL DEFAULT 'EMPLOYEE' COMMENT '角色', `employee_id` int DEFAULT NULL, `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`), KEY `idx_employee` (`employee_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

员工表存基础人事信息,字段包括姓名、工号、部门ID、职位、入职日期、状态。工号不能用自增主键替代,因为公司内部流转时工号不变,但员工ID可能因为数据整理而变化。部门表简单得多,就ID、名称、负责人三个字段。

工资表是核心业务表,设计时用了唯一联合索引:

CREATE TABLE `salary` ( `id` int NOT NULL AUTO_INCREMENT, `employee_id` int NOT NULL COMMENT '员工ID', `salary_month` varchar(7) NOT NULL COMMENT '工资月份,如2024-05', `base_salary` decimal(10,2) NOT NULL COMMENT '基本工资', `post_salary` decimal(10,2) NOT NULL COMMENT '岗位工资', `perf_salary` decimal(10,2) NOT NULL COMMENT '绩效工资', `overtime_salary` decimal(10,2) DEFAULT '0.00', `meal_allowance` decimal(10,2) DEFAULT '0.00', `transport_allowance` decimal(10,2) DEFAULT '0.00', `attendance_deduction` decimal(10,2) DEFAULT '0.00', `social_insurance` decimal(10,2) NOT NULL COMMENT '社保个人部分', `housing_fund` decimal(10,2) NOT NULL COMMENT '公积金个人部分', `tax` decimal(10,2) DEFAULT '0.00' COMMENT '个税', `gross_salary` decimal(10,2) NOT NULL COMMENT '应发合计', `net_salary` decimal(10,2) NOT NULL COMMENT '实发工资', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_emp_month` (`employee_id`, `salary_month`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

3.2 为什么工资明细要单独做一张历史表

工资数据一个显著特点是“发了就不能改”——至少正式发出去的版本得保留原样。如果财务核算出错需要调整,正确的做法不是UPDATE原记录,而是生成一条修正记录,保留历史。所以工资明细表的设计思路是:每月首次核算时插入初始版本,后续每次修正插入新版本,通过版本号区分。

实际开发中这个需求经常被简化掉,很多毕设就一张工资表,改了就改了。如果系统只是课堂作业无所谓,但你想让项目在企业内部真正跑起来,这条设计是关键的加分项。我的做法是加了一个salary_history表,核心字段和salary表一致,额外加version、change_reason、operator_id三个字段。按月份+员工查询时,优先取最高版本。

3.3 工资汇总报表的一条SQL

部门月度汇总报表是财务最常用的功能。左连接员工表拿部门信息,按部门和月份分组聚合,一条SQL完成:

SELECT d.name AS dept_name, s.salary_month, COUNT(s.id) AS person_count, SUM(s.gross_salary) AS total_gross, SUM(s.social_insurance) AS total_social, SUM(s.housing_fund) AS total_fund, SUM(s.tax) AS total_tax, SUM(s.net_salary) AS total_net FROM salary s LEFT JOIN employee e ON s.employee_id = e.id LEFT JOIN department d ON e.department_id = d.id WHERE s.salary_month = #{month} GROUP BY d.id, s.salary_month

这条SQL走的是联合索引uk_emp_month,当月数据量在几百条的情况下毫秒级返回。后续如果公司规模扩大,可以考虑按月份做分区表,但这是后话,项目初期不建议过度设计。

4. 后端实现要点:分层、鉴权、导入导出

后端我用标准的Controller-Service-Mapper三层架构,包结构按照com.example.salary来组织,下面分controller、service、mapper、entity、common、config、aspect几个子包。分层清晰是老生常谈,但它直接决定你排bug的效率,一个请求从Controller进来,Service处理业务逻辑,Mapper操作数据库,每一层只做自己的事,出问题能立刻锁定层次。

4.1 JWT令牌加拦截器,Spring Security放到什么时候用

登录鉴权的方案我选的是JWT加拦截器,而不是直接上Spring Security。原因非常现实:Spring Security的学习曲线陡峭,配置不当会出现各种诡异的过滤链问题,对于一个核心需求清晰的业务系统来说,它的80%功能你都用不到。JWT的方案更透明——登录成功发一个带过期时间的Token,后续每个请求都在拦截器里校验Token,这个逻辑你能完全掌控。

放行逻辑必须在拦截器里配置清楚。登录接口、静态资源要放行,工资相关接口全部拦截,同时把预请求OPTIONS放行,否则前端跨域请求会二次预检。下面这段是我拦截器的核心写法:

public class JwtInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { if ("OPTIONS".equals(request.getMethod())) { return true; } String token = request.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ")) { token = token.substring(7); } try { Claims claims = JwtUtil.parseToken(token); request.setAttribute("userId", claims.get("userId")); request.setAttribute("role", claims.get("role")); return true; } catch (Exception e) { response.setStatus(401); response.getWriter().write("{\"code\":401,\"msg\":\"登录已过期,请重新登录\"}"); return false; } } }

密码存储的处理也给个建议:不要明文存,不要只做一次MD5。我的方案是每个用户随机生成一个盐值,salt加密码做MD5,这样就算数据库泄露,彩虹表也解不出原始密码。MD5在现代安全标准下不够强,但配合随机盐在中小型系统里是成本和安全的平衡点。

4.2 工资导入导出:EasyExcel省下两个通宵

工资数据的录入如果靠表单一页页填,一个月几十上百人就得填到崩溃。所以批量Excel导入是刚需。POI和EasyExcel我相信你都听说过,我的建议是直接用EasyExcel,没有悬念。

EasyExcel是阿里开源的,底层还是POI,但把大文件处理的OOM问题解决了。它最重要的优势是API设计极简,读一行回调一行,不像原生POI要自己遍历Row和Cell。写一个导出工具也很方便,用注解标注实体类字段即可:

@ExcelProperty(value = "工号", index = 0) private String employeeNo; @ExcelProperty(value = "姓名", index = 1) private String employeeName; @ExcelProperty(value = "基本工资", index = 2) private BigDecimal baseSalary;

实际开发中导出工资条还有一个细节:模板文件里可能包含公式或者合并单元格,EasyExcel对这类模板写操作不如POI灵活。如果只是数据列表导出(表头加数据行),EasyExcel完胜;如果要输出复杂版式,才需要用POI手写Workbook。我项目里做的是工资条导出,用EasyExcel足够,每个员工一张工资单区块做不到,我用的是一行一个员工的数据导出版本,财务拿Excel再套打。

导入的校验环节说了真金白银的经验。Excel里的数据不能直接入库,至少三道关卡:格式校验——金额列必须能转成BigDecimal;逻辑校验——社保不能大于工资;唯一性校验——同一员工同一月份不能重复导入。有一行数据不合法,我默认全批回滚,不要出现部分成功部分失败的情况。否则财务拿着半截数据去发工资,账目对不上就是事故。

4.3 Service层的事务边界划分

工资计算的整个流程涉及多个表的更新,事务边界必须清晰。Spring的@Transactional注解默认只回滚RuntimeException,这点容易踩坑。如果事务方法抛出的是检查异常,或者你自己catch住了异常没往上抛,事务是不会回滚的。

我的处理原则是:事务内不能吞异常。Service层做工资核算时,先算应发合计和实发合计,再插入明细表,再写日志表,任何一个环节失败都要让整个操作回滚,保证不出现半张工资单。Controller层负责捕获Service抛出的业务异常,转成统一的JSON返回给前端。业务异常的基类我命名BusinessException,在全局异常处理器里统一拦截,返回格式形如{code:500, msg:"社保字段不能为空"}。

5. 前端页面实现:开发顺序和权限控制的完整链路

Vue前端这部分,我按实际开发顺序来讲。先搭骨架、再写登录、最后填充业务页面,每一步解决什么问题说清楚。

5.1 Vite创建项目到Axios封装的完整链路

创建项目这步现在用Vite已经是共识了,一句命令即可:

npm create vite@latest salary-web -- --template vue

但有个细节我踩过坑:Vite默认创建的项目没有加路由依赖,也没有配路径别名@。你要自己装vue-router和axios,并改vite.config.js。路径别名长这样:

resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } }

不配的话,你import组件时只能用相对路径一层层往上跳,一旦目录层次深,改起路径来想死的心都有。

Axios封装要解决的核心问题是统一处理Token和错误响应。请求拦截器里从localStorage取Token加进Header,响应拦截器里判断HTTP状态码,401就清空登录状态并跳回登录页,500就弹出后端返回的错误信息。这套逻辑在任何项目里都是直接挪用的,一次封装,终身受益。

跨域问题如果你前端口口声声说要“解决”,其实开发模式下最简单的方案就是Vite的proxy代理,把/api前缀的请求转发到后端8080端口,生产环境部署时再交给Nginx处理同源策略。在vite.config.js里这样配:

server: { proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } }

5.2 登录页、路由守卫和动态菜单

登录页的逻辑很简单,把表单数据POST到后端登录接口,拿回Token存进localStorage,跳转到首页。但你要理解一个现代前后端分离系统的本质——登录页只是入口,真正的防线在路由守卫。

路由守卫写在router/index.js里,用router.beforeEach钩子判断:如果目标路由需要认证而本地没有Token,跳登录页;如果已经登录而访问的是登录页,跳首页;如果已登录但角色不匹配,提示无权限。这个守卫生效后,用户绕过前端直接改地址栏访问财务页面就做不到了——当然后端接口的权限校验才是最后的兜底,前端路由守卫只是用户体验层面的双层保障。

菜单我坚持动态渲染:后端登录后返回角色,前端根据角色动态生成侧边栏菜单。管理员能看到系统管理菜单,财务能看到工资管理菜单,普通员工只能看到我的工资菜单。这个动态菜单逻辑一开始就写好,后面加页面只需要在路由表加配置,不需要动菜单代码。

5.3 工资列表页的开发顺序

工资列表页是系统的核心页面,开发顺序我建议从后往前倒着做:先确定表格要展示的列,再确定筛选条件,再写表单弹窗,最后处理分页。总列数别超过12列,太多就横向滚动了,财务操作起来也不方便。

查询区我用三个筛选条件就够了:月份(一个月份选择器)、部门(下拉选)、员工姓名或工号(模糊输入)。查询按钮触发列表重新加载,重置按钮清空条件。工资的录入和编辑用同一个Dialog弹窗,表单Item根据是否编辑状态决定是否禁用——编辑已有工资时,员工和月份不允许改,这是财务逻辑上的红线(防止把5月的工资改到6月去)。

分页组件我用的是Element Plus的Pagination,注意两个关键事件:current-change和size-change都要触发重新查询,而且查询条件变了要手动把页码重置到第一页。这个细节看似微小,但实战中特别影响体验。

5.4 ECharts报表:让工资数据“看得见”

报表功能是整个项目最亮眼的部分,也是答辩时加分最明显的地方。我用ECharts做了两个图:部门平均工资柱状图、近半年工资总额趋势折线图。

柱状图的数据来源是后端汇总接口,返回部门名和平均实发工资。折线图的数据来源是另一个汇总接口,按月份聚合实发工资总额。Vue里使用ECharts的方式很简单,先npm install echarts,然后在组件里导入并用ref绑定DOM容器,setOption填充配置。这里核心心得是一个组件里别写死图表配置,一个页面多图时按图表拆子组件,数据和配置通过props传入,这样代码可维护性高很多。

6. 部署上线:从打包到跑通的完整链路与排错实录

系统开发完不是终点,跑不起来一切都白搭。我部署时踩了一堆坑,按“打包→静态资源→数据库连接→启动”的顺序整理出来。

6.1 前端打包和后端jar包的配合方式

前后端分离项目生产环境有两种部署方案:

第一种是把前端构建产物放到后端的static目录下,后端直接托管静态页面,打成一个jar包发布。这种方案小规模内网系统完全够用,部署最省事,一个java -jar命令全搞定。

第二种是前端独立部署到Nginx,后端jar包单独跑,Nginx配置反向代理把/api请求转发到后端端口。这是更标准的实践,也是我在项目中推荐的方式,理由有二:前端页面更新只需替换静态文件,不用重启后端服务;Nginx处理静态文件性能远优于Tomcat,还能顺带做请求日志、负载均衡。

我的建议是,如果你在本地测试或者答辩演示,用第一种。如果你想要完整的企业级部署经验,用Nginx方案。两个方案都跑通一遍,等于把运维知识也温习了一次。

6.2 我踩过的MySQL连接坑和解决办法

部署时数据库连接报错是最常见的,搜热词里“mysql ssl连接错误”出现频率很高。原因我之前提过——MySQL 8.0的默认认证插件是caching_sha2_password,而应用连接的JDBC驱动版本如果太老,协商协议不匹配直接报错。

解决方式是在application.yml的数据库连接串上配置useSSL=false和allowPublicKeyRetrieval=true。后者的作用是允许客户端在需要使用公钥来传输密码时从服务器请求公钥。这个配置在本地开发时可能没暴露问题,一部署到服务器就炸,因为本机MySQL版本可能和服务器不一样。

还有一个常见错误是连接串里的timezone问题。数据库和服务器的系统时区不一致时,插入时间字段会差8个小时。解决方案是在JDBC URL显式指定serverTimezone=Asia/Shanghai,前端显示的时间就永远对齐北京时间了。

6.3 端口被占用与会话失效的排查

java -jar启动时最常见的错误就是8080端口被占用。Linux下先netstat -tunlp | grep 8080找进程号,kill掉就好。Windows下netstat -ano | findstr 8080查PID再进任务管理器结束进程。这个排查步骤几乎每个项目都会遇到,记牢即可。

会话失效的问题比较隐蔽。JWT的过期时间我设的是8小时,但用户操作中途超过8小时再点按钮,请求被拦截返回401。前端响应拦截器捕获401后不只是跳登录页,还要把localStorage清干净,否则用户登录不了还会报旧Token的错误。我当时排查这个花了一下午,最后发现是响应拦截器里没清旧Token,换新Token和新旧数据混在一起导致的。

6.4 上线前的自测清单

最后给你一份我每次上线前都要过的自测清单,照着检查一遍能避免大多数尴尬问题:

  • 管理员能否正常新增员工并分配账号
  • 财务能否导入一份带错误数据的Excel,验证回滚机制
  • 普通员工登录后能否看到修改工资的按钮(应该看不到)
  • 修改工资后操作日志表是否追加了记录
  • 导出Excel后重新导入是否正常
  • 强制刷新浏览器再操作,是否出现Token失效报错
  • 重启后端服务,前端页面是否仍能正常打开

最后说一点个人体会。这套系统做完之后我没让它停在毕业设计或者Demo的阶段,而是真的部署到公司内网用了三个多月。期间财务提了几次需求,比如批量修改岗位工资、工资条按部门分批查看、复盘上个月的漏发补发记录,这些需求最后都落成了新表和接口。我最大的感受就是,管理系统的价值不在于代码写得有多“高级”,而在于它能不能真正贴合业务流转的每一步。你照着这套设计做出自己的版本后,建议也把源码留好,后续加功能时你会庆幸当初表结构留了足够的设计空间。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 3:41:16

基于SpringBoot+Vue的动漫信息管理系统:设计与部署全解析

做动漫资料站这些年,我最大的感受是:一个网站能不能长期维持下去,内容管理能力远比技术花活重要。新番上线前后有一大堆事要做——资料录入、封面图处理、分类调整、连载状态变更、评论审核,这些工作如果靠手工改代码或者Excel表格…

作者头像 李华
网站建设 2026/10/1 3:40:01

专科生降AI率实用指南:9款工具真实测评与论文改写技巧

专科的同学们,如果你最近正在纠结毕业论文、结课报告写不出来,想着“先让AI写一段,我再改改”,那你大概率已经听过一个词:降AI率。说实话,2026年找实习、搞毕业设计,时间本来就紧,用…

作者头像 李华
网站建设 2026/10/1 3:39:28

MySQL查询锁表全解析:从MVCC到MDL锁,排查与规避实战

先聊个真实的场景。有一天凌晨两点,运维群里突然有人喊“线上订单查询全都卡死了”,我上去一看,一个再普通不过的SELECT * FROM orders WHERE order_id ...在被锁等待折磨了六十多秒。当时第一反应是:查询怎么会锁表?…

作者头像 李华
网站建设 2026/10/1 3:38:14

信号与系统基本信号全解析:分类、典型信号与能量功率判定

我读书那会儿,刚开始学《信号与系统》,最怕的就是不知道一个信号该用哪套方法去分析。后来工作了,主要接触射频和嵌入式相关的信号处理,回头再看这门课,才明白教材一开始把“基本信号”单独拎出来讲,并不是…

作者头像 李华
网站建设 2026/10/1 3:37:54

计算机网络自学路线:从教材选型到面试与排障实战

开写之前先交代一下背景。前阵子公司后端接口偶发超时,我一开始的直觉是加机器、调超时时间,折腾半天问题依旧。后来抓包一看,才发现是TCP重传在作祟,服务器端的队头阻塞把请求堵成了一条线。那一刻我挺感慨:当年在学校…

作者头像 李华
网站建设 2026/10/1 3:37:19

Haar级联上半身检测实战:从模型加载到参数调优与避坑指南

简介:这份资源是OpenCV 4.x中用于人体上半身检测的Haar级联分类器模型包,面向计算机视觉初学者与需要快速集成人体部位检测功能的开发者。包内共2个文件,包含1个xml模型文件与1个txt使用说明,压缩包约768KB,xml文件即训…

作者头像 李华