Atualizando um banco de dados MySQL usando scripts numerados em comparação com um campo de versão [closed]

3

Recebi uma tarefa para atualizar um banco de dados MySQL 5.7 usando um diretório de scripts seqüenciados e comparando-os com um campo de versão em um banco de dados.

Você deve consultar o banco de dados, comparar o número da tabela retornada com os scripts no diretório e, se o número for menor que o script mais alto, executar todos os scripts que levam ao mais alto. Pode haver lacunas na numeração dos scripts também

A questão também é descrita aqui; link

No entanto, criei uma solução para o problema - exceto que não consigo fazer com que os scripts sejam executados em sequência. Se houver uma lacuna na numeração, o meu grep puxará outro script que compartilha o mesmo número - como posso evitar isso?

, por exemplo, grep para 6, mas executa 66.update.sql em vez de 6.update.sql

Nota; Também estou ciente de que a instrução if $ CURRENT_DB_VERSION -lt 9 provavelmente é redundante - mas foi minha tentativa de tentar resolver o problema de qualquer script com um único inteiro precedido por 0.

Eu criei uma versão do script onde eu usaria apenas a ordenação -n | head -1 função para executar os scripts em ordem e removê-los uma vez executado - mas não consegui fazer o script começar a executar scripts .sql na versão DB.

#!/bin/bash
####### Usage check 
[[ $# -ne 5 ]] && echo -e "Please provide the SQL scripts directory, username, hostname, database and password \nUSAGE: ./sql_upgrade.sh /directory username hostname dbname password" && exit

####### access / store db information
cd $1
user=$2
host=$3
database=$4
pass=$5

######## DB Version store
mysql -u $user -h $host -p$pass -D $database -e "SELECT version FROM versionTable" > dbvers.out
CURRENT_DB_VERSION='cat dbvers.out | grep -o '[0-9]\+''
highest_upgrade_version='ls $(pwd) | grep -Eo '[0-9]+' | sort -rn | head -n 1 | awk 'NR' |  sed 's/^0*//''

######### create list of scripts and order them
ls $(pwd) | grep .sql | sort -n >> scripts_list.txt

while [[ $CURRENT_DB_VERSION -lt $highest_upgrade_version || $CURRENT_DB_VERSION -eq $highest_upgrade_version ]]
do
    next_script_to_execute='grep -Eo $CURRENT_DB_VERSION scripts_list.txt | sort -n | head -n 1'        
    if [[ $next_script_to_execute -gt $CURRENT_DB_VERSION || -z $next_script_to_execute ]]
            then
        ((CURRENT_DB_VERSION++))
    elif [[ $CURRENT_DB_VERSION -lt 9 ]]
            then
        for i in $(ls $(pwd) | sort -n| grep -E "^[0]" | grep $CURRENT_DB_VERSION| head -1); 
                    do mysql -u $user -h $host -p$pass -D $database < $i
        echo $i "is currently being executed"
        ((CURRENT_DB_VERSION++))
                    done
    else
        for i in $(ls $(pwd) | sed 's/^[1-9]*\+ //' | grep -E $CURRENT_DB_VERSION | sort -n | head -n 1); do mysql -u $user -h $host -p$pass -D $database < $i
        ((CURRENT_DB_VERSION++))
                    echo $i "is currently being executed"
        done
            fi
done

((CURRENT_DB_VERSION--))
echo "Current version of the Database is: "$CURRENT_DB_VERSION
mysql -u $user -h $host -p$pass -D $database -e "UPDATE versionTable SET version = $CURRENT_DB_VERSION"

### cleanup temp files
rm -rf scripts_list.txt
rm -rf dbvers.out
    
por Ross Williams 09.08.2018 / 11:20

2 respostas

2

Acho que você está complicando demais as coisas.

Exemplo mínimo aqui para a lógica que você precisa:

CURRENT_DB_VERSION=5

for FILE in 'ls -1 |sort -n'
do
  FILEVERSION=$(echo $FILE | sed -e 's:^0*::' | sed -e 's/[^0-9]*//g')
  echo "Filename: $FILE Version: $FILEVERSION"
  if (( $FILEVERSION > $CURRENT_DB_VERSION )); then
    echo "File $FILEVERSION is newer version than database $CURRENT_DB_VERSION"
    # execute the file here 
  else
    echo "File $FILEVERSION is older or same version as database version $CURRENT_DB_VERSION"
  fi

done
    
por 09.08.2018 / 13:34
2

Primeiro de tudo: analisar a saída de ls é uma má ideia. Os nomes dos arquivos no Unix podem ter caracteres muito ruins neles e pode reescrever partes de seus nomes de arquivos de maneiras que você não esperava. Eu sugiro sempre usar globbing em vez disso.

Dado que você sabe a versão na qual você inicia como $ current_db_version e a versão na qual deseja parar como $ target_db_version, é possível simplesmente iterar todos os números e usar um glob para determinar os scripts a serem executados para essa versão específica :

for ver in $(seq "${current_db_version}" "${target_db_version}"); do
  echo "Upgrading to ${ver}"
  for script in ./${ver}.*.sql; do
    echo "Executing ${script}"
    test -x "${script}" && "${script}"
  done
done
    
por 09.08.2018 / 14:03