간단한 예/아니요 질문 "유효함"을 사용하여 마지막 스냅샷 이후 ZFS 데이터 세트가 변경되었는지 어떻게 확인할 수 있습니까?

간단한 예/아니요 질문 "유효함"을 사용하여 마지막 스냅샷 이후 ZFS 데이터 세트가 변경되었는지 어떻게 확인할 수 있습니까?

tank이름이 지정된 데이터세트로 이름이 지정된 풀이 있다고 가정해 보겠습니다 data. data명명된 스냅샷 도 하나 이상 있습니다 last_snapshot.

tank
tank/data
tank/data@last_snapshot

diff내가 아는 한, 데이터 세트가 변경되었는지 확인하는 "느린" 방법은 다음의 출력을 확인하는 것입니다.

zfs diff tank/data@last_snapshot

마지막 스냅샷 이후 각 개별 파일/폴더에 대한 데이터 세트의 모든 변경 사항이 표시됩니다. 이 명령은 많은 출력을 생성할 수 있으며 변경 사항이 많은 경우 몇 초 또는 몇 분 동안 실행될 수 있습니다.

더 빠르지만 (내가 아는 한) 덜 신뢰할 수 있는 방법은 written데이터세트의 속성을 살펴보는 것입니다.

tank/data written 72K -
tank/data@last_snapshot written 1,83G -

데이터세트(스냅샷 아님) written의 값이 56~128k인 경우 데이터세트는대개마지막/가장 최근 스냅샷 이후 수정되지 않았습니다. 이 방법이 훨씬 빠르지만 숫자가 왜 그렇게 많이 변하는지 이해하지 못한 채 이 방법에 의존하고 싶지 않습니다.

안전하고 신속하게 예/아니오 질문을 하려면 어떻게 해야 합니까? 마지막 스냅샷 이후 데이터세트가 변경/수정되었습니까?


디자인 철학(배경): 나는 몇 주에 한 번씩 "큰" 변경 사항을 드물게 수신하는 상당한 양의 데이터 세트를 가지고 있습니다. 하루에 한 번 스냅샷을 만들고 마지막 스냅샷(예: 7)을 유지하면 마지막 "중요한" 변경 이전의 상태가 빠르게 손실될 수 있습니다. 제가 염두에 둔 것은 다음과 같습니다. "중요한" 변경 사항이 발생할 때만 스냅샷을 찍고 마지막 7개를 유지합니다.

답변1

이것은 좋은 질문이며 지금 제가 할 수 있는 일은 '찬성'에 투표하는 것뿐입니다.

이 문제에 대해 생각할 때 제가 시도한 몇 가지 추측 방법은 다음과 같습니다.

  • 데이터 세트의 스냅샷을 다시 생성하고 createtxg두 스냅샷의 ("생성") 속성을 비교합니다. 한 테스트에서는 운이 좋았고 연속된 값이 있었습니다(snapA 생성과 snapB 생성 사이의 전환 중에 트랜잭션이 발생하지 않았다는 의미). 추가 조사에 따르면 트랜잭션 그룹은 파일 시스템별로 고유한 번호가 아니라 풀 전체에 걸쳐 전역적으로 번호가 지정되므로 이 사실은 나중에 쓸모가 없는 것으로 판명되었습니다.

  • createtxg스냅샷의 값을 파일 시스템의 가장 최근 트랜잭션 그룹과 비교합니다. 확실하지는 않지만 스냅샷이 createtxg파일 시스템의 최신 트랜잭션 그룹과 같거나 그보다 높으면 스냅샷 생성 자체가 해당 파일 시스템에 커밋된 최신 트랜잭션임을 유추할 수 있습니다. 이것이 사실인지는 확실하지 않지만, 스냅샷이 "원본"인지 아닌지를 정확하게 결정하기 위해 스냅샷을 createtxg파일 시스템의 가장 최근 스냅샷과 비교할 수 있다면 txg뜻밖의 일이 될 것입니다 .

이 시점에서 제가 제공할 수 있는 최선의 대답은 written파일 시스템의 속성을 신뢰하는 것입니다. 단, 엄격한 매개변수 내에서만 가능합니다.

1) 보류 중인 모든 트랜잭션이 파일 시스템에 커밋되었는지 확인합니다.

sync; sleep 1; sync  # maybe I'm just being superstitious?

2) 파일 시스템이 비활성(마운트되지 않음)인지 확인하십시오.

zfs umount tank/data

written3) -p다음 플래그를 사용하여 기계가 분석할 수 있는 속성의 정확한 값을 쿼리합니다.zfs list

zfs list -Hpo written tank/data

스냅샷이 원본이라고 추론하려면 이 숫자가 정확히 0이어야 합니다. "작다"라고 넣으면 부족하다zfs매뉴얼 페이지액면 그대로:

다음 기본 속성에는 데이터세트에 대한 읽기 전용 통계 정보가 포함되어 있습니다. 이러한 속성은 설정하거나 상속할 수 없습니다. 별도로 명시하지 않는 한 기본 속성은 모든 데이터세트 유형에 적용됩니다.
...

createtxg

데이터세트가 생성되는 트랜잭션 그룹(txg)입니다. 북마크에는 createtxg원래 바인딩된 스냅샷과 동일한 내용이 있습니다. 이 속성은 증분 전송 및 수신과 같은 스냅샷 목록을 정렬하는 데 적합합니다.
...

written

마지막 스냅샷 이후 이 데이터세트에 기록된 참조 공간의 양입니다.

추가 약속은 다음과 같습니다.

written@snapshot

지정된 스냅샷 이후 이 데이터세트에 기록된 참조 공간의 양입니다. 이는 이 데이터 세트에서 참조되지만 지정된 스냅샷에서는 참조되지 않는 공간입니다.

값이 0임을 확인하고 해당 상태에 대한 조치를 취하기 시작할 때 경쟁 조건이 발생하지 않도록 파일 시스템을 마운트 해제해야 하지만 동시에 다른 프로세스가 파일 시스템에 쓰고 파티가 충돌하려고 할 때 .

가장 최근에 커밋된 트랜잭션 그룹 번호에 대해 파일 시스템을 쿼리하는 방법을 아는 사람이 있다면 그 방법을 알아야 할 의무가 있습니다. 기본적인 인터넷 검색으로는 유용할 것이라고 생각되는 내용이 나오지 않았습니다.

또 다른 흥미로운 속성은 referenced스냅샷과 해당 상위 파일 시스템의 속성입니다.

referenced

이 데이터세트에 액세스할 수 있는 데이터의 양으로, 풀의 다른 데이터세트와 공유되거나 공유되지 않을 수 있습니다. 스냅샷이나 복제본이 생성되면 내용이 동일하기 때문에 처음에는 생성된 파일 시스템이나 스냅샷과 동일한 공간을 참조합니다.

그러나 내 직감은 파일 시스템과 스냅샷이 모두 10G의 데이터를 참조할 수 있지만 디스크의 실제 블록에 있는 10G와 동일하지 않기 때문에 이 속성도 잘못된 희망을 낳는다는 것입니다. 아닙니다"는 의미합니다. 공유됨"이라는 referenced값이 일치한다는 것은 충분조건이라기보다는 필요조건에 더 가까운 것 같습니다.

전체적으로 겸손과 불확실성이 많기 때문에 zfs list스냅샷이 원본이라고 가정하기 전에 이 출력을 고수해야 한다고 생각합니다.

# zfs create -o mountpoint=/root/test w541/test
# zfs snap w541/test@snap1
# zfs list -po written,written@snap1 w541/test
WRITTEN  WRITTEN@SNAP1
      0              0

더러워진 스냅샷은 더 이상 깨끗하지 않습니다.

# touch test/foo
# zfs list -po written,written@snap1 w541/test
WRITTEN  WRITTEN@SNAP1
  57344          57344

롤백하면 다시 깨끗해집니다.

# zfs rollback w541/test@snap1
# zfs list -po written,written@snap1 w541/test
WRITTEN  WRITTEN@SNAP1
      0              0

그러나 최고의 무결성을 위해서는 속성을 쿼리하기 전에 아마도 일정 시간 동안 파일 시스템을 마운트 해제해야 합니다 written.

잘못된 가정, 감독 또는 선의의 사람들이 제공한 추가 통찰력을 수정해 주시면 매우 감사하겠습니다.

답변2

나중에 참고할 수 있도록 다음 논리를 채택했습니다. 집중적인 테스트를 거친 결과 정상적으로 작동하는 것 같습니다.하지만 더 나은 답변과 아이디어는 대단히 감사하겠습니다.참고로 다음도 참조하세요.zfs-discuss 메일링 리스트에 대한 토론.

for dataset in tree:

    # If there is no snapshot for this dataset, make one ...
    if len(dataset['SNAPSHOTS']) == 0:
        make_snapshot(dataset)
        continue

    # If nothing has been written, no snapshot is required.
    if dataset['written'] == 0:
        continue

    # If written is north of 1 MByte, make a snapshot.
    if dataset['written'] > (1024 ** 2):
        make_snapshot(dataset)
        continue

    # If the dataset is not a filesystem and
    # we got this far, make a snapshot.
    if dataset['type'] == 'volume':
        make_snapshot(dataset)
        continue

    # Only filesystems with less than 1 MByte written left.
    # Let's look at the diff of the last snapshot.
    diff_out = run_command([
        'zfs', 'diff',
        dataset['NAME'] + '@' + dataset['SNAPSHOTS'][-1]['NAME']
        ])

    # If the diff is not empty, make a snapshot.
    if len(diff_out.strip(' \t\n')) > 0:
        make_snapshot(dataset)

답변3

bash다음은 원하는 대로 변경할 수 있는 재귀 풀에 대해 이를 처리하는 스크립트 입니다 .

function processChanges() {
        POOL=$1
        ROWS=$(zfs get -Hr written ${POOL} |grep -v @ |awk '{print $1 "|" $3}' |grep -v "${POOL}|")
        for ROW in ${ROWS}; do
                CHANGED=0
                V=${ROW##*|}
                P=${ROW%%|*}
                echo -n "Checking ${P}... "
                if [ "${V: -1}" = "K" ]; then
                        BYTES_CHANGED=$(echo "${V:0:-1} * 1024" |bc )
                elif [ "${V: -1}" = "M" ]; then
                        BYTES_CHANGED=$(echo "${V:0:-1} * 1024 * 1024" |bc )
                elif [ "${V: -1}" = "G" ]; then
                        BYTES_CHANGED=$(echo "${V:0:-1} * 1024 * 1024 * 1024" |bc )
                else
                        BYTES_CHANGED=${V}
                fi
                BYTES_CHANGED=${BYTES_CHANGED%%.*}
                MEG=$(( 1 * 1024 * 1024 ))
                if [ ${BYTES_CHANGED} -gt ${MEG} ]; then
                        CHANGED=1;
                elif [ ${BYTES_CHANGED} -ne 0 ]; then
                        LASTSNAP=$(zfs list -t snap ${P} |grep ${P} |sort |tail -n1)
                        LASTSNAP=$(echo ${LASTSNAP##*@}); LASTSNAP=$(echo ${LASTSNAP%% *});
                        DIFF=$(zfs diff ${P}@${LASTSNAP})
                        if [ "${DIFF}" != "" ]; then
                                CHANGED=2;
                        fi
                fi
                if [ ${CHANGED} -gt 0 ]; then
                        echo "Changed"
                else
                        echo "No changes"
                fi
        done
}

processChanges s/storage

관련 정보