PHP 在高并发的时候同时写入同一条数据,会不会出现数据遗漏的问题?

2018-06-19 13:53:02 +08:00
 cstome

项目 ThinkPHP+MySQL

具体是这样,有个文章后台,每条文章有个字段存着已读人员,是数组形式存着 UID,然后 json_encode 存进数据库。

当访问文章的时候,读取该字段,json_decode 后,判断当前 UID 是否在数组中,不存在则 push 上去,然后再 json_encode 进数据库。

问题就是当出现高并发的时候(最高大概也就每秒上千个访问),会不会出现多个 PHP 进程同时读取了该字段,然后又同时写入数据库,导致部分数据被覆盖过去。

同时也想知道有哪些资料可以了解一下 PHP 以及 MySQL 的线程、执行顺序问题。

2427 次点击
所在节点    问与答
8 条回复
feiyuanqiu
2018-06-19 13:58:24 +08:00
跟 PHP 没关系,数据库层面可以看看悲观锁、乐观锁,小流量网站用悲观锁一般就解决了
KgM4gLtF0shViDH3
2018-06-19 14:02:25 +08:00
用队列
feiyuanqiu
2018-06-19 14:03:29 +08:00
不过我觉得其实应该把已读人员单独弄张表,表里面做个 文章 ID + 用户 ID 的唯一键,插入冲突就表示已经存在这个关系了,直接返回已存在的已读关系,这样接口也幂等了
allenhu
2018-06-19 14:28:22 +08:00
每秒上千个访问, 你的 uid 字段存得下么?
cstome
2018-06-19 14:32:10 +08:00
@allenhu #4 实际情况是文章刚发布的时候会有大概最高每秒 1000 的高并发,后面会慢慢下降,UID 也不长,用 TEXT 类型完全够存。
puritania
2018-06-20 00:14:50 +08:00
强行制造并发……
cstome
2018-06-20 14:43:42 +08:00
@feiyuanqiu #3 之前想过这么弄,但是考虑到后面可能数据库条数比较多,影响速度,就没这么弄了。
feiyuanqiu
2018-06-20 15:07:09 +08:00
@cstome

怕数据库慢就用 redis,用文章表字段存这个真不太好,我现在能想到的问题就不少了:

1. 会影响文章表的查询效率,尤其是在阅读人数变多之后,每条文章记录都平白无故增加几 K 的内容
2. 无法检索用户已读的文章,因为是 json_encode 到 text 里面的,没法做查询,以后产品有这个需求的时候又要改又要做数据迁移
3. 更新阅读记录效率低下,要先检索出文章,再 decode,再往里面添加内容,再 encode,再更新,还要加锁放并发;比直接插入一条阅读记录效率低多了
4. text 的长度是 65536,你的 uid 长度是多少,假设是 32,最多可以存 2048 个 uid,实际肯定存不了这么多,因为你还做了 json_encode,也就是一篇文章上限只能存一千多个阅读记录

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/464078

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX