Berbagi teknologi

Ada masalah keamanan thread di database operasi kumpulan thread

2024-07-12

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

Daftar isi

1. Perkenalan

2. Pertanyaan

3. Solusi

3.1. Metode 1: Batasan basis data

3.2. Metode 2: Gunakan kunci untuk membatasi benang

4. Ringkasan


1. Perkenalan

Persyaratan saat ini adalah: memproses data dan menyimpan data dalam database. Selama proses penyimpanan, terlebih dahulu akan ditanyakan apakah data telah disimpan dalam database. Karena data yang akan diproses terlalu besar, maka diperlukan kumpulan thread digunakan untuk pemrosesan simultan.

2. Pertanyaan

Saat menulis logika menggunakan metode di atas, akan ada masalah keamanan thread: penyisipan saat pemeriksaan (masalah inkonsistensi data kueri database), mengakibatkan penyisipan data berulang kali. Oleh karena itu, perlu dilakukan upaya untuk membatasi masalah duplikasi data.

3. Solusi

3.1. Metode 1: Batasan basis data

Rancang bidang dalam database sebagai indeks unik. Bahkan jika catatan data terkait tidak ditemukan selama kueri (sebenarnya sudah ada dalam database), pengecualian kesalahan bidang duplikat akan dilaporkan selama penyisipan, menyebabkan penyisipan catatan data gagal. Untuk mencapai masalah deduplikasi.

3.2. Metode 2: Gunakan kunci untuk membatasi benang

Pilih strategi penguncian yang sesuai berdasarkan skenario bisnis aktual. Penguncian optimis cocok untuk skenario dengan konflik penulisan yang lebih sedikit, dan penguncian pesimis cocok untuk skenario dengan konflik penulisan yang lebih banyak.

Sinkronisasi thread: Gunakan mekanisme sinkronisasi sepertiReentrantLocksynchronized dll., untuk memastikan bahwa hanya satu thread yang dapat melakukan operasi kueri dan penyisipan secara bersamaan. Berikut ini menggunakan mekanisme sinkronisasi thread dan desain tampilan kode:

kode antarmuka 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. }

Buat kode kelas layanan:

  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. }

Di atas hanyalah kasus kecil, skenario penggunaan sebenarnya bergantung pada kebutuhan Anda.Jelaskan kode di atas: menggunakanUserService.class Sebagai objek kunci untuk memastikan bahwa hanya satu thread yang dapat melakukan operasi kueri dan penyisipan pada saat yang bersamaan. Hal ini menghindari masalah konkurensi, namun dapat menyebabkan hambatan kinerja, terutama dalam skenario konkurensi tinggi. Anda dapat mempertimbangkan untuk menggunakan kunci yang lebih terperinci atau kunci tingkat database (seperti kunci pesimistis) untuk mengoptimalkan kinerja.

4. Ringkasan

Logika database operasi kumpulan thread dirancang sesuai dengan kebutuhan, tetapi ada masalah keamanan thread di seluruh proses. Oleh karena itu, dua solusi diperkenalkan secara singkat: ① Menetapkan bidang indeks unik di tabel database ② Menggunakan penguncian untuk memastikan sinkronisasi thread. Saat menggunakannya, sesuaikan dengan skenario sebenarnya. Prosesnya ditulis secara relatif luas dan hanya dua metode yang diperkenalkan. Jika ingin memahaminya secara mendalam, Anda perlu mempelajarinya lebih lanjut. Tentunya saya berharap dapat memberikan sedikit jawaban atas kebingungan Anda melalui sedikit tips dari saya.


Alasan kenapa kamu merasa ingin tidur saat belajar adalah karena disitulah mimpi dimulai.
ଘ(੭ˊᵕˋ)੭ (senang) ଘ(੭ˊᵕˋ)੭ (senang) ଘ(੭ˊᵕˋ)੭ (senang) ଘ(੭ˊᵕˋ)੭ (senang) ଘ(੭ˊᵕˋ)੭ (senang)
------Xiao Liu, yang tidak akan menonjol jika dia tidak menulis kode