데이터베이스의 데이터를 동적으로 추가 및 삭제하여 페이징 쿼리 데이터 문제 분석 및 솔루션의 중복 또는 누락이 발생합니다.

1. 문제 분석

1. 데이터 요청

    일반적인 상황에서는 서버에 대한 부담을 줄이거나 표시를 용이하게 하기 위해 프런트 엔드에서 페이징을 통해 데이터를 요청하며 API 인터페이스를 호출할 때 매개변수 page 및 pageSize를 가져옵니다. 예를 들어, 특정 학급의 학생 데이터를 요청하고, 등록 시간의 역순으로 정렬했다고 가정하여 첫 페이지에 10명의 학생 데이터를 가져옵니다.

https://api.domain.com/class/student/list?page=1&pageSize=10

    페이지 매김 쿼리는 SQL 제한 문, 제한 사용으로 실현됩니다.

table_name 제한 [오프셋,] 행에서 *를 선택하세요.


offset: 첫 번째 레코드 줄의 오프셋(즉, 반환할 줄)을 지정합니다. 참고: 첫 번째 줄의 오프셋은 0입니다.
행: 특정 행 수를 반환합니다.

    데이터의 첫 번째 페이지를 요청합니다. 페이지 = 1, 오프셋은 (1 - 1) * 10, 즉 0입니다.

tb_student 순서에서 *를 선택하세요. Register_time 설명 제한 0, 10으로;

    데이터의 두 번째 페이지를 요청합니다. 페이지 = 2, 오프셋은 (2 - 1)*10, 즉 10입니다.

tb_student 순서에서 *를 선택하세요. Register_time 설명 제한 10, 10;

2. 데이터가 중복되거나 누락된 경우

    첫 번째 페이지의 데이터를 획득했다고 가정하면 두 번째 데이터를 요청하기 전에 백그라운드에서 새로운 학생이 새로 등록되는데, 등록 시간의 역순으로 정렬하면 이 새로 등록된 학생이 첫 번째 데이터가 된다. 이해하려면: 새 데이터 삽입으로 인해 원래 첫 번째 페이지의 마지막 데이터 조각이 두 번째 페이지의 첫 번째 데이터 조각 위치로 푸시됩니다. 두 번째 페이지의 데이터는 "반복적으로 " 획득 됩니다 . 데이터의 원래 첫 번째 페이지의 마지막 기록에 대해 이런 일이 발생하면 일반적으로 프런트 엔드에는 서로 옆에 있고 동일한 두 개의 학생 데이터가 표시됩니다.

    같은 방법으로 두 번째 페이지의 데이터를 가져오기 전에 로그아웃으로 인해 첫 번째 페이지의 학생이 데이터베이스에서 삭제되고 모든 데이터의 시작 위치 오프셋이 1만큼 감소하고 첫 번째 데이터가 두 번째 페이지 첫 번째 페이지의 마지막 데이터 조각이 되므로 두 번째 데이터 페이지를 요청할 때 반환되는 결과에는 이 데이터 조각이 "누락" 됩니다.

요약: 데이터베이스 데이터가 동적으로 변경될 때 오프셋에 실시간 동적 수정이 없고 여전히 오프셋 = (페이지 - 1) * pageSize 방법을 사용하여 데이터를 얻는 경우 데이터 중복 또는 누락이 발생합니다.

둘, 해결책

    위의 분석 결과, 우리는 데이터를 요청할 때마다 올바른 오프셋을 얻을 수 있다면 항소 문제가 없을 것이라는 것을 알고 있습니다. 이 오프셋은 요청된 학생 데이터의 첫 번째 페이지의 마지막 학생 기록이어야 합니다 . " 역순으로 정렬할 때 ". 따라서 우리는 마지막 레코드의 ID를 가져와서 " fromId = ID " 매개변수를 통해 백그라운드에서 제공하는 인터페이스에 업로드 하고 계산을 통해 데이터의 다음 페이지를 요청하기 위한 올바른 오프셋을 얻습니다. 데이터베이스 데이터가 추가되거나 삭제되더라도 중복되거나 누락된 사례는 없습니다. 일반적으로 데이터를 요청할 때마다 formIId가 나타내는 레코드의 다음 레코드부터 시작하여 10개의 새로운 레코드를 얻습니다.

    데이터의 첫 번째 페이지 요청(fromId = 0)

https://api.domain.com/class/student/list?fromId=0&pageSize=10

    fromId = 0(데이터의 첫 번째 페이지 요청을 의미)에 동의하므로 오프셋 값은 0입니다. 데이터의 첫 번째 페이지에 있는 마지막 데이터 조각의 Student_id가 1001이라고 가정합니다.

    fromId = 1001; 매개변수를 사용하여 데이터의 두 번째 페이지를 요청합니다.

https://api.domain.com/class/student/list?fromId=1001&pageSize=10

    마지막 레코드(fromId) 이후 다음 레코드의 시작 위치를 얻기 위해 백그라운드에서 실시간 계산:

tb_student에서 count(*)를 선택하세요(여기서 Register_time >=) (student_id = 1001인 tb_student에서 Register_time을 선택하세요);


지침:

1. 문 안에 선택 쿼리가 중첩되어 있고 내부 중첩 쿼리 문은 하나의 레코드만 반환할 수 있으며 여러 레코드가 나타날 수 없습니다. 그렇지 않으면 SQL 실행 후 오류가 발생합니다.

2. 등록 시간을 기준으로 오름차순으로 정렬하는 경우 " >= "를 " <= "로 바꿔야 합니다 .

3. 정렬에 사용되는 Register_time 필드는 동일한 값을 가질 수 없습니다. 그렇지 않으면 쿼리 데이터가 누락될 수 있습니다. (예를 들어 11번째 데이터와 10번째 데이터의 Register_time 값이 동일하며, 위의 SQL 문을 실행하여 얻은 오프셋 값입니다. 두 번째 페이지에서 요청한 데이터에 제11조 데이터가 표시되지 않습니다.

    위의 SQL 쿼리문에서 반환된 값을 오프셋으로 사용하여 학생 데이터의 두 번째 페이지를 요청하며 쿼리문은 다음과 같습니다.

tb_student 순서에서 *를 선택하세요. Register_time 설명 제한 [오프셋,] 10;

추천

출처blog.csdn.net/crazestone0614/article/details/132346462