Compartilhamento de tecnologia

Existem problemas de segurança de thread no banco de dados de operação do pool de threads

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Índice

1. Introdução

2. Pergunta

3. Solução

3.1. Método 1: Restrições do banco de dados

3.2. Método 2: Use bloqueios para restringir threads

4. Resumo


1. Introdução

Os requisitos atuais são: processar dados e armazenar os dados no banco de dados Durante o processo de armazenamento, ele primeiro consultará se os dados foram armazenados no banco de dados. Como os dados a serem processados ​​​​são muito grandes, um conjunto de threads precisa ser. usado para processamento simultâneo.

2. Pergunta

Ao escrever lógica usando os métodos acima, haverá problemas de segurança de thread: inserção durante a verificação (problema de inconsistência de dados de consulta de banco de dados), resultando em inserção repetida de dados. Portanto, é necessário adotar meios para limitar o problema da duplicação de dados.

3. Solução

3.1. Método 1: Restrições do banco de dados

Projete um campo no banco de dados como um índice exclusivo, mesmo que o registro de dados correspondente não seja encontrado durante a consulta (na verdade já existe no banco de dados), uma exceção de erro de campo duplicado será relatada durante a inserção, causando falha na inserção do registro de dados. Para resolver o problema da desduplicação.

3.2. Método 2: Use bloqueios para restringir threads

Escolha uma estratégia de bloqueio apropriada com base em cenários reais de negócios. O bloqueio otimista é adequado para cenários com menos conflitos de gravação, e o bloqueio pessimista é adequado para cenários com mais conflitos de gravação.

Sincronização de thread: use mecanismos de sincronização comoReentrantLocksynchronized etc., para garantir que apenas um thread possa realizar operações de consulta e inserção ao mesmo tempo. O seguinte usa o mecanismo de sincronização de thread e o design de exibição de código:

Código da interface mybatis:

  1. import org.apache.ibatis.annotations.*;
  2. public interface UserMapper {
  3. @Select("SELECT COUNT(*) FROM user WHERE username = #{username}")
  4. int countByUsername(@Param("username") String username);
  5. @Insert("INSERT INTO user (username, password, email) VALUES (#{username}, #{password}, #{email})")
  6. @Options(useGeneratedKeys = true, keyProperty = "id")
  7. int insertUser(User user);
  8. }

Crie o código da classe de serviço:

  1. import org.apache.ibatis.session.SqlSession;
  2. import org.apache.ibatis.session.SqlSessionFactory;
  3. import java.util.concurrent.ExecutorService;
  4. import java.util.concurrent.Executors;
  5. public class UserService {
  6. private final ExecutorService executorService;
  7. private final SqlSessionFactory sqlSessionFactory;
  8. public UserService(SqlSessionFactory sqlSessionFactory) {
  9. this.sqlSessionFactory = sqlSessionFactory;
  10. // 创建固定大小的线程池
  11. this.executorService = Executors.newFixedThreadPool(10);
  12. }
  13. public void addUser(User user) {
  14. executorService.submit(() -> {
  15. try (SqlSession session = sqlSessionFactory.openSession()) {
  16. UserMapper userMapper = session.getMapper(UserMapper.class);
  17. synchronized (UserService.class) {
  18. // 在同步块内执行查询和插入操作
  19. if (userMapper.countByUsername(user.getUsername()) == 0) {
  20. userMapper.insertUser(user);
  21. session.commit(); // 提交事务
  22. }
  23. }
  24. }
  25. });
  26. }
  27. }

O texto acima é apenas um pequeno caso, o cenário de uso real depende de suas necessidades.Explique o código acima: usandoUserService.class Como um objeto de bloqueio para garantir que apenas um thread possa realizar operações de consulta e inserção ao mesmo tempo. Isto evita problemas de simultaneidade, mas pode causar gargalos de desempenho, especialmente em cenários de alta simultaneidade. Você pode considerar o uso de bloqueios mais refinados ou bloqueios em nível de banco de dados (como bloqueios pessimistas) para otimizar o desempenho.

4. Resumo

A lógica do banco de dados de operação do pool de threads é projetada de acordo com os requisitos, mas há problemas de segurança de thread em todo o processo. Portanto, duas soluções são brevemente apresentadas: ① Definir campos de índice exclusivos na tabela do banco de dados ② Usar bloqueio para garantir a sincronização do thread. Ao usá-lo, ajuste-o de acordo com o cenário real. O processo é escrito de forma relativamente ampla e apenas dois métodos são introduzidos. Se você quiser entendê-lo em profundidade, será necessário estudar mais. Claro, espero poder dar-lhe uma pequena resposta à sua confusão através das minhas pequenas dicas.


A razão pela qual você tem vontade de dormir quando estuda é porque é aí que começam os sonhos.
ଘ(੭ˊᵕˋ)੭ (feliz) ଘ(੭ˊᵕˋ)੭ (feliz) ଘ(੭ˊᵕˋ)੭ (feliz) ଘ(੭ˊᵕˋ)੭ (feliz) ଘ(੭ˊᵕˋ)੭ (feliz)
------Xiao Liu, que não se destacará se não escrever código