Назад | Перейти на главную страницу

Обновление базы данных MySQL с использованием пронумерованных сценариев по сравнению с полем версии

Мне дали задание обновить БД MySQL 5.7, используя каталог упорядоченных скриптов и сравнив их с полем версии в БД.

Вы должны запросить БД, затем сравнить возвращенный номер таблицы со сценариями в каталоге, и, если номер ниже, чем самый высокий сценарий, выполнить все сценарии, ведущие к самому высокому. Также могут быть пробелы в нумерации скриптов.

Вопрос также изложен здесь; https://dba.stackexchange.com/questions/214087/how-to-upgrade-a-mysql-database-using-numbered-scripts-based-on-a-version-field

Однако я создал решение проблемы - за исключением того, что я не могу заставить сценарии выполняться последовательно. Если в нумерации есть пробел, моя команда grep вместо этого вытащит другой скрипт с тем же номером - как я могу этого избежать?

то есть grep для 6, но он выполняет 66.update.sql вместо 6.update.sql

Заметка; Я также знаю, что оператор if $ CURRENT_DB_VERSION -lt 9, вероятно, избыточен, но это была моя попытка решить проблему любого скрипта, имеющего одно целое число, которому предшествует 0.

Я создал версию сценария, в которой я просто использовал бы sort -n | Функция head -1 для выполнения сценариев по порядку и удаления их после выполнения, но я не мог заставить сценарий начать выполнение сценариев .sql в версии БД.

#!/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

Прежде всего: анализ вывода ls - плохая идея. Имена файлов в Unix могут содержать действительно плохие символы, и ls может переписать части ваших имен файлов неожиданным образом. Я предлагаю всегда использовать вместо этого глобус.

Учитывая, что вы знаете версию, с которой вы начинаете как $ current_db_version, и версию, на которой вы хотите остановиться как $ target_db_version, вы можете просто перебрать все числа и использовать глобус для определения сценариев, которые будут запускаться для этой конкретной версии:

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

Я думаю, вы слишком усложняете.

Минимальный пример необходимой логики:

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