Ham*_*med 7 java mysql spring multithreading
场景很简单。
我有一个包含两个表的大型MySQL数据库:
-- Table 1
id (primary key) | some other columns without constraints
-----------------+--------------------------------------
1 | foo
2 | bar
3 | foobar
... | ...
-- Table 2
id_src | id_trg | some other columns without constraints
-------+--------+---------------------------------------
1 | 2 | ...
1 | 3 | ...
2 | 1 | ...
2 | 3 | ...
2 | 5 | ...
...
Run Code Online (Sandbox Code Playgroud)
id一个主键。该表包含大约1200万个条目。id_src和id_trg上都是主键,并且都在table1上具有外键约束,id并且还DELETE ON CASCADE启用了该选项。该表包含大约1.1亿个条目。好的,现在我要做的只是创建id要从表1中删除的s 列表,然后执行一个简单的DELETE FROM table1 WHERE id IN (<the list of ids>);
正如您可能已经猜到的那样,后一个过程也会从table2中删除相应的id。到目前为止,还不错,但是问题是,当我在多线程环境中运行它时,我得到了很多Deadlocks!
一些注意事项:
我已经尝试过SELECT ... FOR UPDATE,但是一个简单的过程DELETE可能需要30秒!(因此没有使用它的用途):
DELETE FROM table1
WHERE id IN (
SELECT id FROM (
SELECT * FROM table1
WHERE id='some_id'
FOR UPDATE) AS x);
Run Code Online (Sandbox Code Playgroud)我怎样才能解决这个问题?
我将不胜感激,在此先感谢:)
编辑:
java.util.concurrentSELECTs的说明,请参阅MySQL无法在FROM子句中指定目标表进行更新FOR UPDATE子句是我听说它锁定一行而不是锁定整个表DELETE ON CASCADEon id_src和id_trg(分别单独)将意味着对table1的每次删除id=x都会导致对table2 id_src=x和id_trg=x一些要求的代码:
public void write(List data){
try{
Arraylist idsToDelete = getIdsToDelete();
String query = "DELETE FROM table1 WHERE id IN ("+ idsToDelete + " )";
mysqlJdbcTemplate.getJdbcTemplate().batchUpdate(query);
} catch (Exception e) {
LOG.error(e);
}
}
Run Code Online (Sandbox Code Playgroud)并且myJdbcTemplate只是一个扩展的抽象类JdbcDaoSupport。
首先,您在其中传递 ids 的第一个简单删除查询,如果您将 ids 传递到像 1000 这样的限制(子表中的总行数也应该接近但不会太多,比如 10,000 等),则不应产生问题。 ),但如果你传递了 50,000 或更多,那么它可能会产生锁定问题。
为了避免死锁,您可以按照以下方法来处理此问题(假设批量删除不会成为生产系统的一部分)-
步骤1:通过选择查询获取所有id并保留在光标中。
Step2:现在将存储过程中cursor中存储的这些id一一删除。
注意:要检查为什么删除会获取锁,我们必须检查几项内容,例如您传递了多少个 id、在数据库级别设置的事务级别是什么、my.cnf 中的 Mysql 配置设置是什么等...
| 归档时间: |
|
| 查看次数: |
2780 次 |
| 最近记录: |