使用 unique key 可以保证
但是不使用唯一 key 的情况并且在并发提交的情况下怎么防止重复插入呢?
比如浏览器卡了一下,导致用户重复点击提交了
![]() | 1 JacFrak 2019-05-17 10:46:10 +08:00 如果是 ajax 提交,点击提交按钮事件里面将按钮设置为不可操作 |
3 DovaKeen 2019-05-17 11:02:24 +08:00 引入事务,在插入前先搜索一下有没有重复,如果有的话就取消插入,没有再插入?但是这样的话似乎要把隔离级别设置的很高… |
4 DovaKeen 2019-05-17 11:03:27 +08:00 |
![]() | form 埋个 token form 提交后就把这个 token 删了 token 不存在即是重复提交 |
6 peyppicp 2019-05-17 11:04:06 +08:00 分布式锁 |
![]() | 7 hlwjia PRO 没有 unique 的情况下只能先查重再插了 |
![]() | 8 Immortal 2019-05-17 11:05:50 +08:00 服务端搞个 token 存到 session 或者什么地方 然后发给前端 前端提交表单的时候一起提交着个 token 如果一致就处理 不一致当成重复提交 不处理 以上是一个成熟且常规的做法 |
![]() | 10 eluotao 2019-05-17 11:08:06 +08:00 插入或忽略 如果我们希望插入一条新记录( INSERT ),但如果记录已经存在,就啥事也不干直接忽略,此时, 可以使用 INSERT IGNORE INTO ...语句: INSERT IGNORE INTO students (id, class_id, name, gender, score) VALUES (1, 1, '小明', 'F', 99); |
11 jorneyr 2019-05-17 11:10:00 +08:00 根据业务数据特点建立唯一索引 |
![]() | 12 aitaii 2019-05-17 11:12:22 +08:00 via iPhone ![]() 幂等 |
13 fl0w 2019-05-17 11:13:42 +08:00 insert into table(field1,field2) select value1,value2 from dual where not exists( select 1 from table where field1 = value1 and field2 = value2) |
![]() | 15 vance 2019-05-17 11:26:18 +08:00 分布式锁,单个数据库个可以 insert into XX ... select x from dual where not exists( select from xx ) |
![]() | 19 tabris17 2019-05-17 11:28:06 +08:00 一次性 token |
20 Hellert 2019-05-17 11:30:41 +08:00 难道不应该是在每次提交前手动检查业务键是否重复吗?比如一些 编号 字段。 |
![]() | 21 eziooooo 2019-05-17 11:34:55 +08:00 1. 请求锁(这个请求这个人 N 秒内只能请求一次) 2. 事务 |
![]() | 22 xuanbg 2019-05-17 11:40:07 +08:00 先查后写是需要加锁作为前提的,没有锁,就有幻读的可能。如果是分布式系统,那这个锁就必须是分布式锁才行。 前端防重发是标准配置,不做的都不是合格的前端。 |
23 dilu 2019-05-17 11:56:55 +08:00 前端防连点,后端做个锁,记得开事务,表上加个唯一索引 |
![]() | 24 est 2019-05-17 12:00:12 +08:00 1. 楼主问的是表单提交如何防止重复,这个其实很简单。用 E-tag 这个 http 头控制即可。根本 不用太涉及 db 层面的东西。在 session 就处理了。 2. 如果是 db 层面需要防止重复,我个人遇到更麻烦的问题是批量插入的时候。没有主键和 uniq key 可以用来鉴别。很麻烦。 |
![]() | 25 jowan 2019-05-17 12:00:31 +08:00 CSRF_TOKEN 可以解决这个问题,顺便还能解决跨站的表单提交 |
![]() | 26 Weixiao0725 2019-05-17 12:17:52 +08:00 只有 uniq key 一条路子要想真正有效。 |
![]() | 27 sun1991 2019-05-17 12:28:53 +08:00 从数据库层面上, 用 unique key 解决此类问题是最合适的, 为什么要给自己找不痛快呢? |
![]() | 28 glfpes 2019-05-17 12:40:33 +08:00 via Android 为何不能设置 unique ? |
![]() | 29 AngryPanda 2019-05-17 12:40:37 +08:00 ![]() |
30 fmumu 2019-05-17 12:41:34 +08:00 先查重再插入,并发时候有重复插入的可能 应该先插入再查重(使用隔离级别 read commit)吧 |
![]() | 31 Comdex 2019-05-17 12:44:40 +08:00 via Android 使用队列使并发请求串行 |
![]() | 32 jason19659 2019-05-17 12:45:23 +08:00 前端是用户表单的重复提交还是什么?无意的还是故意的? 浏览器卡一下。。每次刷新生成一个 id 就完了,提交了这个 id 就不再处理 |
![]() | 33 R18 2019-05-17 12:47:47 +08:00 via Android 悲观锁 |
![]() | 34 pudgedoor 2019-05-17 12:50:59 +08:00 via Android 数据库锁怎么样,乐观锁 |
![]() | 35 opengps 2019-05-17 12:55:38 +08:00 如果是浏览器卡了一下多点击了提交,那么先查询在写入可以应对 |
36 BestSera 2019-05-17 14:06:24 +08:00 for update 悲观锁 乐观锁都行 |
37 799635347 2019-05-17 14:06:35 +08:00 分布式锁,或者丢消息队列串行消费,或者数据库级别加 unique 约束,token 这种应该不能解决 |
![]() | 39 luwies 2019-05-17 14:15:10 +08:00 貌似有一种办法是刷出这个提交信息的页面的时候给前端一个唯一值,提交信息的时候把找个值带上,如果是重复的就忽略了。 |
![]() | 40 kiddult 2019-05-17 14:20:38 +08:00 @AngryPanda 他想的是在每次提交前的页面访问都重新生成 CSRF Token,解除和 session 的绑定 |
![]() | 41 momocraft 2019-05-17 14:37:03 +08:00 实施难度和风险和效果看 unique key 还不错? |
42 loveCoding 2019-05-17 14:44:41 +08:00 数据库层 唯一约束 应用层 分布式锁 |
![]() | 43 arthas2234 2019-05-17 14:56:06 +08:00 重复提交这个事,不应该用 unique key 来防御,建议使用 token |
![]() | 44 rockyou12 2019-05-17 15:07:54 +08:00 ![]() 纯 rest,直接请求里带一个 requestId,由前端生成的 uuid。如果表(或者放 redis 或直接后端缓存下)已经出现,就直接拒绝 |
45 seanpan 2019-05-17 17:33:25 +08:00 via iPhone 表单令牌 |
![]() | 46 lusi1990 2019-05-17 18:35:36 +08:00 via Android 用锁或者队列 ,插入前判断 |
![]() | 47 JohnYehyo 2019-05-23 17:05:54 +08:00 服务器生成 token 存入表单隐藏字段 表单提交 服务器端获取该值与 token 比较 一致则进行业务处理并在 session 删掉 token |