问一个关于 MySQL 锁的问题

2020-07-19 08:30:32 +08:00
 codebigbang

一张表每天月有一千万多的数据量,第二天重新写之前需要把表里存着的数据量给全删掉再把今天需要写的数据按一定尺寸分批利用多线程写入数据库。

在清表这个阶段,一开始先用 delete from tableName 来实现清空同时返回清空的数据量的。但是走完清表步骤获得删除数据量开始分批往数据库写数据的阶段,写了几个数据之后,数据库就报死锁错误。结果只能使用 truncate 来删数据,才能确保之后写数据阶段没有锁的问题。

请教有相关经验的 V 友:在网上搜了很多资料都是说删数据的时候会加锁,这样在往表里插数据的时候会导致死锁。可是我的程序是在获取了已经删除的数据量之后才往表重新插数据,难道说这个时候其实 delete 产生的锁还没有解锁吗?如果还没有解锁,那是否有办法在 Java 端获取 MySQL 删除后真正解锁状态的办法?

3640 次点击
所在节点    程序员
27 条回复
johnj
2020-07-20 07:50:28 +08:00
显然应该先插入临时表 再通过 rename 来替换 rename 可以做到原子操作(旧表改其他名字 临时表改为旧表名 最后把其他名字表 drop )
awanganddong
2020-07-20 12:10:56 +08:00
想判断死锁的问题,把 mysql log 慢日志贴出来让大家分析。
rename 是一个比较好的方案
sha4yu
2020-07-20 15:43:11 +08:00
可以贴下死锁信息和执行的相关 SQL 不
hejw19970413
2020-07-20 16:20:55 +08:00
如果是那么大数据量,为什么不每天都创建一个新表,创建完后 删除以前的表不就可以吗
codebigbang
2020-07-20 22:18:31 +08:00
@awanganddong
@sha4yu
这是前期开发时候遇到的问题,当时就用 truncate 解决掉这个问题了。项目都上线很久了,问题日志啥哪里还能拿到呢。但是后面项目复盘的时候就留意了这点,想向 V 友取取经。

SQL 大概就是先 delete from tableName, 然后多线程利用 jdbc 连接池建立连接,把一定尺寸的数据用 insert 写入,执行则是 PreparedStatement.executeLargeUpdate()这个方法,最后 commit 。

@hejw19970413
@johnj
应用和运维都不能随心所欲随意删表建表
codebigbang
2020-07-20 22:21:26 +08:00
@npe
带上索引列可以让 MySQL 删数据的时候不加锁吗?
johnj
2020-07-21 11:32:17 +08:00
事务怎么控制的?
因为数据很多 所以不要搞大事务 delete 和 insert 都要分批 比如 每 50 条一批 每批的事务都要单独提交

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

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

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

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

© 2021 V2EX