多线程:多个线程与同一个表进行交互

时间:2019-07-02 11:10:49

标签: java sql multithreading executorservice

面试问题

说,我们有一个表,在Employee表中有200万条记录,我们需要削减每位员工的10%薪水(需要进行一些处理),然后将其保存回集合中。您如何有效地做到这一点。

我问他我们可以使用executor框架来创建多个线程,这些线程可以从表中获取值,然后我们可以对其进行处理并将其保存到列表中。

然后他问我,您将如何检查记录是否已处理,那里我一无所知(怎么办)。

即使我不确定自己的方法是否很好。

请帮助。

3 个答案:

答案 0 :(得分:1)

您可以做的一件事是使用生产者/消费者类型模型,在该模型中,您有一个线程在工作以向其他线程提供要更新的记录。这样,您不必担心重复处理。

答案 1 :(得分:1)

给出上述问题的最佳方法是使用纯SQL,例如:

update employees set
salary = salary * .9

很难想象需要对SQL无法处理的员工数据做些什么。

如果由于某些错误的设计怪异而真的需要对雇员类型的数据做一些SQL绝对无法做到的事情,那么您将打开一个游标并遍历行集,同步更新,因此您只需对数据进行一次传递。

使用伪代码:

cursor = forUpdate ("select for update * from employees")
while (cursor.next()) {
    cursor.salary = cursor.salary * .9
}

这是最简单且可能最快的执行方法。

-

关于日志记录

只有200万行,这是一个“小”数量,因此大多数DB可以在单个事务中处理它。但是,如果没有,请在查询中添加where子句,例如where id between <start> and <end>,以使用Shell脚本方法将流程分块为可记录数量。

如果使用代码方法,大多数数据库都允许您在打开游标的同时进行提交,因此只需每10K行左右提交一次。

关于锁定

与日志记录类似的方面。这种查询中的所有行在事务期间都被锁定。鉴于要花这么长时间才能运行,请选择一个安静的时间运行。如果确实很重要,请整理一下,但要意识到锁定是不可避免的。

答案 2 :(得分:0)

我将在此表中加载,然后为该状态添加一列。默认情况下,您可以将此列设置为“未处理”。一旦线程开始处理此员工,它将状态更改为“正在处理”,然后在完成后最终将其切换为“已处理”。

具有3种这样的状态还可以使您将其用作锁定,从而防止处理发生两次。