ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

合工大数据库课程设计实战:从ER建模到事务优化的闭环训练

合工大数据库课程设计实战:从ER建模到事务优化的闭环训练 简介本资源是合肥工业大学数据库课程设计实践项目——基于Java与MySQL的学生管理系统完整开发包面向计算机专业本科生及数据库初学者解决课程设计中从需求分析、数据库建模到前后端集成落地的全流程实践难题。压缩包共180个文件含21个核心Java源码、16个JSP页面、10个HTML前端页、48个依赖JAR包、42个编译后CLASS文件以及SQL建表脚本、XML配置、CSS/JS样式与脚本等全面覆盖MVC架构下ServletJSPMySQL的技术栈实现包体大小26.57MB。已有1180人学习下载资源提供可直接运行的完整工程结构含IntelliJ IDEA项目配置、典型业务模块学生/课程/选课/成绩管理的分层代码实现、关键Servlet与DAO类的双份编译文件如UserDaoImpl.class、loginServlet.class以及配套SQL初始化脚本和基础测试用例便于快速部署、调试与二次开发。1. 合肥工业大学数据库课程设计不是交个SQL文件就完事而是用真实业务逻辑把ER图、范式、事务隔离、索引优化全串起来的一次硬核闭环训练在合工大翡翠湖校区计算机学院的机房里每年都有上百名学生在DDL前夜对着Navicat反复执行INSERT INTO student VALUES (...)以为“增删改查跑通课程设计及格”。但真正带过这门课设计的老师和助教都知道只要没在MySQL中亲手模拟出“选课系统并发抢课导致超限”、没为“成绩统计报表慢到卡死”加过复合索引、没把原始Excel导入后手动拆分出符合第三范式的5张表——这个设计就还没落地。这不是数据库原理的纸上谈兵而是用合工大教务系统真实字段命名规范如stu_id而非student_id、用校内MySQL 5.7环境非本地SQLite、按《合肥工业大学课程设计评分细则》中“数据完整性约束占20%”“事务处理占15%”“查询性能分析占10%”三块硬指标来倒推技术选型的实战项目。适合刚学完《数据库系统原理》但没写过200行以上SQL脚本、对FOREIGN KEY ON DELETE CASCADE和READ COMMITTED隔离级别只有概念印象的大三学生——它不考你背范式定义考你面对“教师信息表里混着教研室电话和邮箱”时敢不敢一刀切出department_contact子表。2. 从教务系统真实字段出发用ER建模工具画出能通过答辩的实体关系图课程设计最常被退回的起点就是ER图里还写着“用户表”“订单表”这种互联网黑话。合工大要求必须基于校内可验证的业务场景比如“本科生毕业设计管理系统”或“实验室设备预约平台”而这两个系统的字段在教务处公开文档里都能查到。我带过的小组里80%的失败源于第一步用PowerDesigner随手拖出几个方框连弱实体、基数约束、属性依赖都标错。下面带你用最稳妥的方式过审。2.1 用真实字段反推实体与联系以“毕业设计管理系统”为例先别急着打开建模工具。打开合工大教务系统截图或回忆登录后的页面把看到的所有字段抄下来按业务归类业务模块原始字段来自教务系统界面归类依据学生端stu_id,stu_name,major,class_no,tel,email学号唯一标识姓名/专业/班级可变电话邮箱属联系信息教师端teacher_id,teacher_name,dept,title,office_tel教师ID主键职称/院系可变办公室电话属联系信息课题管理topic_id,topic_title,topic_desc,max_stu_num,current_stu_num课题ID唯一标题描述可变人数限制与当前人数需实时计算选题记录record_id,stu_id,topic_id,apply_time,status记录ID主键学生与课题多对多状态含“待审核/已通过/已拒绝”提示合工大评分标准明确要求“实体命名须与校内系统一致”所以stu_id不能写成student_idtopic_id不能写成project_id。这是答辩时老师第一眼会盯的点。2.2 用draw.io画出带基数约束的ER图零成本替代PowerDesignerPowerDesigner要装破解版且导出PDF常乱码而draw.io在线版app.diagrams.net直接支持MySQL ERD模板且能导出符合合工大格式要求的A4横向PDF。关键是要标清三要素实体间连线旁标注基数例如学生与课题是“N:M”必须在线上写N和M不能只画双线弱实体用双矩形如“选题记录”依赖“学生”和“课题”存在必须用双线矩形虚线指向父实体派生属性打虚线current_stu_num是通过统计record表得出的必须用虚线连接到topic实体。!-- draw.io导出的XML片段粘贴进draw.io即可渲染 -- mxGraphModel dx1426 dy709 grid1 gridSize10 guides1 tooltips1 connect1 arrows1 fold1 page1 pageScale1 pageWidth1169 pageHeight827 background#ffffff math0 shadow0 root mxCell id0/ mxCell id1 parent0/ mxCell id2 valuestudent styleswimlane;fontStyle0;childLayoutswimlaneLayout;horizontal1;startSize26;fillColornone;horizontalStack0;resizeParent1;resizeLast0;collapsible1;marginBottom0;swimlaneFillColor#ffffff; parent1 vertex1 mxGeometry x40 y40 width160 height150 asgeometry/ /mxCell mxCell id3 valuestu_id styletext;strokeColornone;fillColornone;alignleft;verticalAligntop;spacingLeft4;spacingRight4;overflowhidden;rotatable0;points[[0,0.5],[1,0.5]];portConstrainteastwest; parent2 vertex1 mxGeometry y26 width160 height26 asgeometry/ /mxCell mxCell id4 valuestu_name styletext;strokeColornone;fillColornone;alignleft;verticalAligntop;spacingLeft4;spacingRight4;overflowhidden;rotatable0;points[[0,0.5],[1,0.5]];portConstrainteastwest; parent2 vertex1 mxGeometry y52 width160 height26 asgeometry/ /mxCell mxCell id5 valuemajor styletext;strokeColornone;fillColornone;alignleft;verticalAligntop;spacingLeft4;spacingRight4;overflowhidden;rotatable0;points[[0,0.5],[1,0.5]];portConstrainteastwest; parent2 vertex1 mxGeometry y78 width160 height26 asgeometry/ /mxCell mxCell id6 valueclass_no styletext;strokeColornone;fillColornone;alignleft;verticalAligntop;spacingLeft4;spacingRight4;overflowhidden;rotatable0;points[[0,0.5],[1,0.5]];portConstrainteastwest; parent2 vertex1 mxGeometry y104 width160 height26 asgeometry/ /mxCell mxCell id7 valuetopic styleswimlane;fontStyle0;childLayoutswimlaneLayout;horizontal1;startSize26;fillColornone;horizontalStack0;resizeParent1;resizeLast0;collapsible1;marginBottom0;swimlaneFillColor#ffffff; parent1 vertex1 mxGeometry x320 y40 width160 height124 asgeometry/ /mxCell mxCell id8 valuetopic_id styletext;strokeColornone;fillColornone;alignleft;verticalAligntop;spacingLeft4;spacingRight4;overflowhidden;rotatable0;points[[0,0.5],[1,0.5]];portConstrainteastwest; parent7 vertex1 mxGeometry y26 width160 height26 asgeometry/ /mxCell mxCell id9 valuetopic_title styletext;strokeColornone;fillColornone;alignleft;verticalAligntop;spacingLeft4;spacingRight4;overflowhidden;rotatable0;points[[0,0.5],[1,0.5]];portConstrainteastwest; parent7 vertex1 mxGeometry y52 width160 height26 asgeometry/ /mxCell mxCell id10 valuemax_stu_num styletext;strokeColornone;fillColornone;alignleft;verticalAligntop;spacingLeft4;spacingRight4;overflowhidden;rotatable0;points[[0,0.5],[1,0.5]];portConstrainteastwest; parent7 vertex1 mxGeometry y78 width160 height26 asgeometry/ /mxCell mxCell id11 valuerecord styleswimlane;fontStyle0;childLayoutswimlaneLayout;horizontal1;startSize26;fillColornone;horizontalStack0;resizeParent1;resizeLast0;collapsible1;marginBottom0;swimlaneFillColor#ffffff; parent1 vertex1 mxGeometry x180 y240 width160 height124 asgeometry/ /mxCell mxCell id12 valuerecord_id styletext;strokeColornone;fillColornone;alignleft;verticalAligntop;spacingLeft4;spacingRight4;overflowhidden;rotatable0;points[[0,0.5],[1,0.5]];portConstrainteastwest; parent11 vertex1 mxGeometry y26 width160 height26 asgeometry/ /mxCell mxCell id13 valuestu_id styletext;strokeColornone;fillColornone;alignleft;verticalAligntop;spacingLeft4;spacingRight4;overflowhidden;rotatable0;points[[0,0.5],[1,0.5]];portConstrainteastwest; parent11 vertex1 mxGeometry y52 width160 height26 asgeometry/ /mxCell mxCell id14 valuetopic_id styletext;strokeColornone;fillColornone;alignleft;verticalAligntop;spacingLeft4;spacingRight4;overflowhidden;rotatable0;points[[0,0.5],[1,0.5]];portConstrainteastwest; parent11 vertex1 mxGeometry y78 width160 height26 asgeometry/ /mxCell mxCell id15 value styleendArrowclassic;html1;exitX1;exitY0.5;entryX0;entryY0.5; parent1 source2 target11 edge1 mxGeometry width50 height50 relative1 asgeometry mxPoint x40 y490 assourcePoint/ mxPoint x90 y440 astargetPoint/ /mxGeometry /mxCell mxCell id16 valueN styletext;html1;resizable0;points[];aligncenter;verticalAlignmiddle; parent15 vertex1 mxGeometry x-0.25 y-2 relative1 asgeometry mxPoint x-16 y10 asoffset/ /mxGeometry /mxCell mxCell id17 value styleendArrowclassic;html1;exitX0;exitY0.5;entryX1;entryY0.5; parent1 source7 target11 edge1 mxGeometry width50 height50 relative1 asgeometry mxPoint x290 y490 assourcePoint/ mxPoint x340 y440 astargetPoint/ /mxGeometry /mxCell mxCell id18 valueM styletext;html1;resizable0;points[];aligncenter;verticalAlignmiddle; parent17 vertex1 mxGeometry x-0.25 y-2 relative1 asgeometry mxPoint x-16 y10 asoffset/ /mxGeometry /mxCell /root /mxGraphModel这段XML可直接粘贴进draw.io菜单栏 → Arrange → Insert → Advanced → XML生成带N:M标注的标准ER图。注意record实体必须用双矩形在draw.io中右键该框 → Edit Style → 添加shapeext;double1否则答辩时会被质疑“没理解弱实体”。2.3 避坑ER图被退稿的3个高频原因及现场补救法现象 → 原因 → 解决全是合工大近年真实扣分点现象ER图里“教师”和“教研室”画成两个独立实体连线标1:N但答辩时老师问“教研室电话变更所有教师记录是否要批量更新”答不上来。原因混淆了“强实体”与“属性”。教研室dept在合工大系统中是枚举值如“计算机与信息学院”“仪器科学与光电工程学院”无独立生命周期应作为teacher实体的属性而非实体。解决立即删掉dept实体框在teacher框内新增一行dept VARCHAR(50)并在报告中注明“依据《合工大组织机构代码表》第3.2条院系为固定编码不设独立维护”。现象record表里写了status ENUM(pending,approved,rejected)但ER图中未体现该枚举约束。原因ER图只画结构不画取值范围但合工大评分细则要求“约束条件需在ER图中显式标注”。解决在record实体下方加注释框写status: {pending, approved, rejected}用虚线连接到status属性。这是答辩时加分项。现象用Visio画ER图导出PDF后字体变成方块老师看不清stu_id。原因Visio默认嵌入字体失败而合工大打印室只认标准字体。解决用draw.io导出时勾选“Export as PDF (with embedded fonts)”或导出SVG后用Inkscape转PDF免费开源支持字体嵌入。血泪经验DDL前2小时发现此问题用Inkscape重转PDF救回一命。3. 从ER图到MySQL建表语句手写DDL必须满足合工大三道硬性约束很多同学用PowerDesigner自动生成SQL结果CREATE TABLE里全是INT和VARCHAR(255)连主键都没设AUTO_INCREMENT。合工大《数据库课程设计指导书》第4.3条白纸黑字“建表语句须体现完整性约束缺失外键、非空、默认值等任一约束扣5分”。下面教你用最笨但最稳的手写法一条一条过审。3.1 主键与自增为什么stu_id不能用INT AUTO_INCREMENT合工大所有学号是10位数字如2021123456且由教务系统统一分配不是插入时自动生成的流水号。若设stu_id INT AUTO_INCREMENT会导致插入INSERT INTO student(stu_name) VALUES(张三)时stu_id变成1与真实学号冲突导入教务处Excel时stu_id列被覆盖为1,2,3...数据作废。正确做法是stu_id CHAR(10) PRIMARY KEY并加注释说明来源-- 学生表stu_id 来源教务系统统一编码不可自增 CREATE TABLE student ( stu_id CHAR(10) PRIMARY KEY COMMENT 学号10位数字例2021123456, stu_name VARCHAR(20) NOT NULL COMMENT 学生姓名, major VARCHAR(30) NOT NULL COMMENT 专业名称, class_no VARCHAR(15) NOT NULL COMMENT 班级编号例20210101, tel CHAR(11) COMMENT 手机号11位数字, email VARCHAR(50) COMMENT 邮箱地址 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学生基本信息表;参数说明CHAR(10)比VARCHAR(10)更优学号定长CHAR存取更快且避免VARCHAR的长度头开销COMMENT字段必须写合工大要求“每字段注释不少于5字”这是送分项ENGINEInnoDB强制指定MyISAM不支持外键和事务直接不及格。3.2 外键与级联ON DELETE CASCADE不是炫技是解决真实业务痛点“毕业设计管理系统”中当删除一个课题DELETE FROM topic WHERE topic_idCS2024001时若不设级联record表里残留的记录会变成“孤儿数据”导致SELECT COUNT(*) FROM record WHERE topic_idCS2024001返回非零但topic表已无此课题——这违反参照完整性。合工大案例库明确要求处理此类场景。-- 选题记录表stu_id和topic_id均为外键删除课题时自动清理记录 CREATE TABLE record ( record_id INT PRIMARY KEY AUTO_INCREMENT COMMENT 选题记录ID, stu_id CHAR(10) NOT NULL COMMENT 学生学号, topic_id CHAR(10) NOT NULL COMMENT 课题编号, apply_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 申请时间, status ENUM(pending,approved,rejected) DEFAULT pending COMMENT 审核状态, FOREIGN KEY (stu_id) REFERENCES student(stu_id) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY (topic_id) REFERENCES topic(topic_id) ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE KEY uk_stu_topic (stu_id, topic_id) COMMENT 同一学生不可重复选同一课题 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学生选题记录表;参数说明ON DELETE CASCADE删课题自动删其下所有选题记录ON UPDATE CASCADE课题编号变更极少见但需覆盖自动同步record表UNIQUE KEY uk_stu_topic强制业务规则防止学生重复提交——这是答辩时老师必问“如何保证不重复选题”的答案。3.3 字段类型精算TINYINT存状态比ENUM更兼容DATETIME比TIMESTAMP更可控合工大服务器用MySQL 5.7ENUM类型在跨版本迁移时易出问题如升级到8.0后排序规则变化且ENUM(a,b,c)实际存储的是数字1/2/3不利于调试。而TINYINT(1)存状态用注释标明含义既清晰又稳定-- 状态字段用TINYINT(1)替代ENUM兼容性更好 ALTER TABLE record MODIFY COLUMN status TINYINT(1) NOT NULL DEFAULT 1 COMMENT 审核状态1待审核,2已通过,3已拒绝;DATETIMEvsTIMESTAMPTIMESTAMP受时区影响合工大服务器时区为CSTNOW()插入时可能比本地时间快8小时DATETIME存字面值绝对可靠。所有时间字段一律用DATETIME。3.4 避坑建表语句被扣分的4个致命细节现象 → 原因 → 解决均来自合工大2023年课程设计抽查报告现象CREATE TABLE末尾漏写ENGINEInnoDB用默认MyISAM引擎。原因MySQL 5.7默认引擎是InnoDB但部分同学用旧版教程或本地MySQL配置被改过。解决执行SHOW VARIABLES LIKE default_storage_engine;确认若非InnoDB建表时必须显式声明。现象外键字段类型不一致如student.stu_id是CHAR(10)但record.stu_id是VARCHAR(10)建表时报错ERROR 1005。原因外键要求“完全相同的数据类型和长度”CHAR和VARCHAR虽都存字符串但底层实现不同。解决统一用CHAR(10)并用DESCRIBE table_name检查字段类型。现象UNIQUE KEY没起名字如UNIQUE(stu_id, topic_id)导致后续删约束时无法定位。原因MySQL会自动生成名字如uk_123456但答辩时老师让你“删掉重复选题约束”你根本不知道名字。解决强制命名UNIQUE KEY uk_stu_topic (stu_id, topic_id)名字见名知义。现象COMMENT写成中文句号“。”导致建表报错ERROR 1064。原因MySQL 5.7的COMMENT不支持全角标点必须用英文句号.。解决所有注释结尾用.如COMMENT 学号10位数字例2021123456.。4. 数据导入与初始化用Python脚本把教务处Excel变成符合范式的5张表交设计时老师第一件事就是SELECT * FROM student LIMIT 5;若看到NULL值满屏或major列里混着“计算机科学与技术卓越班”和“物联网工程”直接打回重做。合工大要求“初始数据不少于50条且符合业务逻辑”这意味着你不能手动INSERT 50次必须用脚本自动化清洗。4.1 用pandas读Excel并拆分弱实体从“教师信息表”提取教研室联系信息教务处给的原始Excel里“教师信息”Sheet有teacher_id,teacher_name,dept,title,office_tel,email。但dept院系和office_tel办公室电话属于教研室维度不应和教师强耦合——若某院系换楼所有教师记录都要UPDATEoffice_tel违反第三范式。正确做法是拆出department表# clean_teacher_data.py import pandas as pd import pymysql # 读取原始Excel df pd.read_excel(teacher_raw.xlsx, sheet_name教师信息) # 提取教研室信息去重 dept_df df[[dept, office_tel, email]].drop_duplicates().reset_index(dropTrue) dept_df[dept_id] range(1, len(dept_df) 1) # 生成教研室ID dept_df dept_df[[dept_id, dept, office_tel, email]] # 调整列序 # 教师表只保留教师维度字段并关联dept_id teacher_df df.merge(dept_df, on[dept, office_tel, email], howleft)[[teacher_id, teacher_name, title, dept_id]] teacher_df[dept_id] teacher_df[dept_id].fillna(0).astype(int) # 处理未匹配的异常数据 # 写入MySQL需提前建好表 conn pymysql.connect(hostlocalhost, userroot, password123456, databasegraduation_db) cursor conn.cursor() # 插入department表 for _, row in dept_df.iterrows(): cursor.execute( INSERT INTO department (dept_id, dept_name, office_tel, email) VALUES (%s, %s, %s, %s), (row[dept_id], row[dept], row[office_tel], row[email]) ) # 插入teacher表 for _, row in teacher_df.iterrows(): cursor.execute( INSERT INTO teacher (teacher_id, teacher_name, title, dept_id) VALUES (%s, %s, %s, %s), (row[teacher_id], row[teacher_name], row[title], row[dept_id]) ) conn.commit() cursor.close() conn.close()逻辑说明drop_duplicates()确保每个教研室只存一条避免冗余merge(..., howleft)将教师记录关联到教研室ID未匹配的设为0后续人工核查所有INSERT用参数化查询防SQL注入——合工大安全规范明确要求。4.2 用SQL生成测试数据不用第三方库纯MySQL造1000条选题记录手动插1000条太傻用MySQL的INSERT ... SELECT结合JOIN自动生成-- 先清空record表谨慎 TRUNCATE TABLE record; -- 用笛卡尔积生成测试数据100学生 × 10课题 1000条 INSERT INTO record (stu_id, topic_id, status) SELECT s.stu_id, t.topic_id, FLOOR(1 RAND() * 3) AS status FROM student s CROSS JOIN topic t LIMIT 1000;FLOOR(1 RAND() * 3)生成1/2/3随机数对应待审核/已通过/已拒绝。LIMIT 1000控制总量。此法比Python循环快10倍且数据分布均匀。4.3 避坑数据导入翻车的3个玄学时刻现象 → 原因 → 解决全是实测踩坑现象pandas.read_excel()读出的teacher_id是1.0,2.0浮点数插入MySQL时报错Data truncated for column teacher_id。原因Excel单元格格式为“常规”pandas默认读为float64。解决加dtype{teacher_id: str}参数或读完后df[teacher_id] df[teacher_id].astype(str).str.zfill(10)补零。现象INSERT INTO record时stu_id和topic_id值存在但外键约束报错Cannot add or update a child row。原因student和topic表数据未先插入或插入时stu_id有空格如 2021123456 导致外键不匹配。解决插入前加清洗df[stu_id] df[stu_id].str.strip()并用SELECT COUNT(*) FROM student WHERE stu_id2021123456验证存在性。现象TRUNCATE TABLE record后record_id自增ID没重置为1新插入记录ID从1001开始。原因TRUNCATE会重置自增但若表被其他事务锁住可能失效。解决执行ALTER TABLE record AUTO_INCREMENT 1;强制重置再插入。5. 查询优化与事务实战用慢查询日志定位“成绩统计卡死”用事务解决“并发抢课超限”合工大评分细则中“查询性能分析”和“事务处理”合计占25%是拉开分数的关键。很多同学只写SELECT * FROM record WHERE status2却不知当record表有10万行时这条语句要扫描全表。下面用真实场景教你怎么做。5.1 用EXPLAIN分析慢查询定位“统计各课题选题人数”为何卡死业务需求管理员要查看SELECT topic_title, COUNT(*) FROM topic t JOIN record r ON t.topic_idr.topic_id WHERE r.status2 GROUP BY t.topic_id但执行超3秒。-- 开启慢查询日志合工大服务器通常已开 SET GLOBAL slow_query_log ON; SET GLOBAL long_query_time 1; -- 记录超过1秒的查询 -- 执行慢查询 SELECT t.topic_title, COUNT(*) FROM topic t JOIN record r ON t.topic_id r.topic_id WHERE r.status 2 GROUP BY t.topic_id;然后查慢日志路径通常为/var/lib/mysql/localhost-slow.log找到该SQL再用EXPLAINEXPLAIN SELECT t.topic_title, COUNT(*) FROM topic t JOIN record r ON t.topic_id r.topic_id WHERE r.status 2 GROUP BY t.topic_id;输出关键列type:ALL全表扫描→ 问题在record表无索引key:NULL→ 没用上索引rows:102400扫描10万行→ 性能灾难。优化方案在record表的topic_id和status上建复合索引-- 创建复合索引先status后topic_id因WHERE条件是status2GROUP BY是topic_id CREATE INDEX idx_status_topic ON record (status, topic_id);再EXPLAINtype变为refrows降到1200查询从3秒降至0.02秒。参数说明复合索引顺序至关重要WHERE条件字段在前GROUP BY字段在后不用单列索引INDEX(status)只能加速WHEREINDEX(topic_id)只能加速JOIN复合索引一举两得。5.2 用事务解决“并发抢课超限”READ COMMITTED下的乐观锁实践业务痛点topic表有max_stu_num5record表已有4条status2记录此时两个学生同时点“确认选题”若不加事务可能都插入成功导致超限。-- 正确做法用事务SELECT ... FOR UPDATE悲观锁 START TRANSACTION; SELECT current_stu_num, max_stu_num FROM topic WHERE topic_id CS2024001 FOR UPDATE; -- 锁住这一行其他事务等待 -- 应用层判断if current_stu_num max_stu_num UPDATE topic SET current_stu_num current_stu_num 1 WHERE topic_id CS2024001; INSERT INTO record (stu_id, topic_id, status) VALUES (2021123456, CS2024001, 2); COMMIT;为什么不用READ UNCOMMITTED合工大服务器默认隔离级别是REPEATABLE READ但SELECT ... FOR UPDATE在READ COMMITTED下更高效锁范围小。可在连接时设置SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;5.3 避坑性能与事务的3个反直觉真相现象 → 原因 → 解决全是答辩时老师追问点现象加了idx_status_topic索引EXPLAIN显示typeref但查询还是慢。原因status字段只有3个值1/2/3选择性极低MySQL认为走索引不如全表扫描。解决强制使用索引SELECT ... FROM record FORCE INDEX(idx_status_topic) WHERE status2或增加WHERE status2 AND topic_id LIKE CS%提高选择性。现象SELECT ... FOR UPDATE在高并发下大量事务等待响应时间飙升。原因锁粒度太大FOR UPDATE锁整行而实际只需校验current_stu_num。解决改用乐观锁——UPDATE topic SET current_stu_num current_stu_num 1 WHERE topic_id ? AND current_stu_num max_stu_num若ROW_COUNT() 0则重试。合工大认可此方案因更轻量。现象TRUNCATE TABLE后EXPLAIN显示rows0但查询仍慢。原因TRUNCATE重置自增ID但表统计信息未更新MySQL优化器误判数据量。解决执行ANALYZE TABLE record;更新统计信息让优化器重新估算。6. 答辩前最后48小时用3个命令自检所有扣分点附合工大真题应答话术别再本文还有配套的精品资源点击获取
返回列表