Merging revision from codership-mysql/5.5 (r3928..3968) and

codership-mysql/5.6 (r4021..4065).
- Also contains fixes for some build failures.
This commit is contained in:
Nirbhay Choubey 2014-03-27 16:26:00 -04:00
commit 02ba2bfdb4
57 changed files with 2161 additions and 722 deletions

View File

@ -31,6 +31,9 @@ MACRO (INSTALL_DSYM_DIRECTORIES targets)
GET_TARGET_PROPERTY(type ${target} TYPE) GET_TARGET_PROPERTY(type ${target} TYPE)
# It's a dirty hack, but cmake too stupid and mysql cmake files too buggy */ # It's a dirty hack, but cmake too stupid and mysql cmake files too buggy */
STRING(REPLACE "liblibmysql.dylib" "libmysqlclient.${SHARED_LIB_MAJOR_VERSION}.dylib" location ${location}) STRING(REPLACE "liblibmysql.dylib" "libmysqlclient.${SHARED_LIB_MAJOR_VERSION}.dylib" location ${location})
IF(DEBUG_EXTNAME)
STRING(REGEX REPLACE "/mysqld$" "/mysqld-debug" location ${location})
ENDIF()
IF(type MATCHES "EXECUTABLE" OR type MATCHES "MODULE" OR type MATCHES "SHARED_LIBRARY") IF(type MATCHES "EXECUTABLE" OR type MATCHES "MODULE" OR type MATCHES "SHARED_LIBRARY")
INSTALL(DIRECTORY "${location}.dSYM" DESTINATION ${ARG_DESTINATION} COMPONENT Debuginfo) INSTALL(DIRECTORY "${location}.dSYM" DESTINATION ${ARG_DESTINATION} COMPONENT Debuginfo)
ENDIF() ENDIF()

View File

@ -18,12 +18,12 @@
# so WSREP_VERSION is produced regardless # so WSREP_VERSION is produced regardless
# Set the patch version # Set the patch version
SET(WSREP_PATCH_VERSION "9") SET(WSREP_PATCH_VERSION "10")
# MariaDB addition: Revision number of the last revision merged from # MariaDB addition: Revision number of the last revision merged from
# codership branch visible in @@visible_comment. # codership branch visible in @@visible_comment.
# Branch : codership-mysql/5.5 # Branch : codership-mysql/5.5
SET(WSREP_PATCH_REVNO "3928") # Should be updated on every merge. SET(WSREP_PATCH_REVNO "3968") # Should be updated on every merge.
# MariaDB: Obtain patch revision number: # MariaDB: Obtain patch revision number:
# Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set. # Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set.

View File

@ -22,7 +22,7 @@ extern "C" {
#endif #endif
#ifdef WITH_WSREP #ifdef WITH_WSREP
#include <my_sys.h> #include <my_sys.h>
typedef int (* wsrep_thd_is_brute_force_fun)(void *); typedef my_bool (* wsrep_thd_is_brute_force_fun)(void *, my_bool);
typedef int (* wsrep_abort_thd_fun)(void *, void *, my_bool); typedef int (* wsrep_abort_thd_fun)(void *, void *, my_bool);
typedef int (* wsrep_on_fun)(void *); typedef int (* wsrep_on_fun)(void *);
void wsrep_thr_lock_init( void wsrep_thr_lock_init(

View File

@ -690,7 +690,7 @@ wsrep_break_lock(
{ {
if (wsrep_on(data->owner->mysql_thd) && if (wsrep_on(data->owner->mysql_thd) &&
wsrep_thd_is_brute_force && wsrep_thd_is_brute_force &&
wsrep_thd_is_brute_force(data->owner->mysql_thd)) wsrep_thd_is_brute_force(data->owner->mysql_thd, TRUE))
{ {
THR_LOCK_DATA *holder; THR_LOCK_DATA *holder;
@ -715,7 +715,7 @@ wsrep_break_lock(
holder; holder;
holder=holder->next) holder=holder->next)
{ {
if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd)) if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd, TRUE))
{ {
wsrep_abort_thd(data->owner->mysql_thd, wsrep_abort_thd(data->owner->mysql_thd,
holder->owner->mysql_thd, FALSE); holder->owner->mysql_thd, FALSE);
@ -731,7 +731,7 @@ wsrep_break_lock(
holder; holder;
holder=holder->next) holder=holder->next)
{ {
if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd)) if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd, TRUE))
{ {
wsrep_abort_thd(data->owner->mysql_thd, wsrep_abort_thd(data->owner->mysql_thd,
holder->owner->mysql_thd, FALSE); holder->owner->mysql_thd, FALSE);

View File

@ -321,7 +321,13 @@ IF(WIN32)
ENDFOREACH() ENDFOREACH()
ELSE() ELSE()
IF(WITH_WSREP) IF(WITH_WSREP)
SET(WSREP_BINARIES wsrep_sst_common wsrep_sst_mysqldump wsrep_sst_rsync wsrep_sst_xtrabackup) SET(WSREP_BINARIES
wsrep_sst_common
wsrep_sst_mysqldump
wsrep_sst_rsync
wsrep_sst_xtrabackup
wsrep_sst_xtrabackup-v2
)
ENDIF() ENDIF()
# On Unix, most of the files end up in the bin directory # On Unix, most of the files end up in the bin directory
SET(BIN_SCRIPTS SET(BIN_SCRIPTS

View File

@ -28,7 +28,7 @@ case "$1" in
shift shift
;; ;;
'--auth') '--auth')
readonly WSREP_SST_OPT_AUTH="$2" WSREP_SST_OPT_AUTH="$2"
shift shift
;; ;;
'--bypass') '--bypass')
@ -87,13 +87,21 @@ shift
done done
readonly WSREP_SST_OPT_BYPASS readonly WSREP_SST_OPT_BYPASS
if [ -n "$WSREP_SST_OPT_DATA" ] # For Bug:1200727
if my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then
if [ -z $WSREP_SST_OPT_AUTH -o $WSREP_SST_OPT_AUTH = "(null)" ];then
WSREP_SST_OPT_AUTH=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- "--wsrep_sst_auth" | cut -d= -f2)
fi
fi
if [ -n "${WSREP_SST_OPT_DATA:-}" ]
then then
SST_PROGRESS_FILE="$WSREP_SST_OPT_DATA/sst_in_progress" SST_PROGRESS_FILE="$WSREP_SST_OPT_DATA/sst_in_progress"
else else
SST_PROGRESS_FILE="" SST_PROGRESS_FILE=""
fi fi
wsrep_log() wsrep_log()
{ {
# echo everything to stderr so that it gets into common error log # echo everything to stderr so that it gets into common error log

View File

@ -67,12 +67,22 @@ check_pid_and_port()
MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete" MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete"
rm -rf "$MAGIC_FILE" rm -rf "$MAGIC_FILE"
SCRIPT_DIR=$(cd "$(dirname "$0")"; pwd -P) WSREP_LOG_DIR=${WSREP_LOG_DIR:-""}
WSREP_LOG_DIR=${WSREP_LOG_DIR:-$($SCRIPT_DIR/my_print_defaults --defaults-file "$WSREP_SST_OPT_CONF" mysqld server mysqld-5.5 \
| grep -- '--innodb[-_]log[-_]group[-_]home[-_]dir=' | cut -b 29- )} # if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf
if [ -n "${WSREP_LOG_DIR:-""}" ]; then if [ -z "$WSREP_LOG_DIR" ]; then
SCRIPT_DIR="$(cd $(dirname "$0"); pwd -P)"
WSREP_LOG_DIR=$($SCRIPT_DIR/my_print_defaults --defaults-file \
"$WSREP_SST_OPT_CONF" mysqld server mysqld-5.5 \
| grep -- '--innodb[-_]log[-_]group[-_]home[-_]dir=' \
| cut -b 29- )
fi
if [ -n "$WSREP_LOG_DIR" ]; then
# handle both relative and absolute paths
WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; mkdir -p "$WSREP_LOG_DIR"; cd $WSREP_LOG_DIR; pwd -P) WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; mkdir -p "$WSREP_LOG_DIR"; cd $WSREP_LOG_DIR; pwd -P)
else else
# default to datadir
WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; pwd -P) WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; pwd -P)
fi fi
@ -208,8 +218,6 @@ then
trap "exit 3" INT TERM ABRT trap "exit 3" INT TERM ABRT
trap cleanup_joiner EXIT trap cleanup_joiner EXIT
MYUID=$(id -u)
MYGID=$(id -g)
RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf" RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf"
cat << EOF > "$RSYNC_CONF" cat << EOF > "$RSYNC_CONF"
@ -217,8 +225,6 @@ pid file = $RSYNC_PID
use chroot = no use chroot = no
read only = no read only = no
timeout = 300 timeout = 300
uid = $MYUID
gid = $MYGID
[$MODULE] [$MODULE]
path = $WSREP_SST_OPT_DATA path = $WSREP_SST_OPT_DATA
[$MODULE-log_dir] [$MODULE-log_dir]

View File

@ -0,0 +1,875 @@
#!/bin/bash -ue
# Copyright (C) 2013 Percona Inc
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston
# MA 02110-1301 USA.
# Documentation: http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html
# Make sure to read that before proceeding!
. $(dirname $0)/wsrep_sst_common
ealgo=""
ekey=""
ekeyfile=""
encrypt=0
nproc=1
ecode=0
XTRABACKUP_PID=""
SST_PORT=""
REMOTEIP=""
tcert=""
tpem=""
tkey=""
sockopt=""
progress=""
ttime=0
totime=0
lsn=""
incremental=0
ecmd=""
rlimit=""
# Initially
stagemsg="${WSREP_SST_OPT_ROLE}"
cpat=""
speciald=0
ib_home_dir=""
ib_log_dir=""
sfmt="tar"
strmcmd=""
tfmt=""
tcmd=""
rebuild=0
rebuildcmd=""
payload=0
pvformat="-F '%N => Rate:%r Avg:%a Elapsed:%t %e Bytes: %b %p' "
pvopts="-f -i 10 -N $WSREP_SST_OPT_ROLE "
STATDIR=""
uextra=0
disver=""
scomp=""
sdecomp=""
if which pv &>/dev/null && pv --help | grep -q FORMAT;then
pvopts+=$pvformat
fi
pcmd="pv $pvopts"
declare -a RC
INNOBACKUPEX_BIN=innobackupex
readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ })
DATA="${WSREP_SST_OPT_DATA}"
INFO_FILE="xtrabackup_galera_info"
IST_FILE="xtrabackup_ist"
MAGIC_FILE="${DATA}/${INFO_FILE}"
# Setting the path for ss and ip
export PATH="/usr/sbin:/sbin:$PATH"
timeit(){
local stage=$1
shift
local cmd="$@"
local x1 x2 took extcode
if [[ $ttime -eq 1 ]];then
x1=$(date +%s)
wsrep_log_info "Evaluating $cmd"
eval "$cmd"
extcode=$?
x2=$(date +%s)
took=$(( x2-x1 ))
wsrep_log_info "NOTE: $stage took $took seconds"
totime=$(( totime+took ))
else
wsrep_log_info "Evaluating $cmd"
eval "$cmd"
extcode=$?
fi
return $extcode
}
get_keys()
{
# $encrypt -eq 1 is for internal purposes only
if [[ $encrypt -ge 2 || $encrypt -eq -1 ]];then
return
fi
if [[ $encrypt -eq 0 ]];then
if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then
wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html "
fi
return
fi
if [[ $sfmt == 'tar' ]];then
wsrep_log_info "NOTE: Xtrabackup-based encryption - encrypt=1 - cannot be enabled with tar format"
encrypt=-1
return
fi
wsrep_log_info "Xtrabackup based encryption enabled in my.cnf - Supported only from Xtrabackup 2.1.4"
if [[ -z $ealgo ]];then
wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out"
exit 3
fi
if [[ -z $ekey && ! -r $ekeyfile ]];then
wsrep_log_error "FATAL: Either key or keyfile must be readable"
exit 3
fi
if [[ -z $ekey ]];then
ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile"
else
ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey"
fi
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
ecmd+=" -d"
fi
stagemsg+="-XB-Encrypted"
}
get_transfer()
{
if [[ -z $SST_PORT ]];then
TSST_PORT=4444
else
TSST_PORT=$SST_PORT
fi
if [[ $tfmt == 'nc' ]];then
if [[ ! -x `which nc` ]];then
wsrep_log_error "nc(netcat) not found in path: $PATH"
exit 2
fi
wsrep_log_info "Using netcat as streamer"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
tcmd="nc -dl ${TSST_PORT}"
else
tcmd="nc ${REMOTEIP} ${TSST_PORT}"
fi
else
tfmt='socat'
wsrep_log_info "Using socat as streamer"
if [[ ! -x `which socat` ]];then
wsrep_log_error "socat not found in path: $PATH"
exit 2
fi
if [[ $encrypt -eq 2 || $encrypt -eq 3 ]] && ! socat -V | grep -q WITH_OPENSSL;then
wsrep_log_info "NOTE: socat is not openssl enabled, falling back to plain transfer"
encrypt=-1
fi
if [[ $encrypt -eq 2 ]];then
wsrep_log_info "Using openssl based encryption with socat: with crt and pem"
if [[ -z $tpem || -z $tcert ]];then
wsrep_log_error "Both PEM and CRT files required"
exit 22
fi
stagemsg+="-OpenSSL-Encrypted-2"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
wsrep_log_info "Decrypting with PEM $tpem, CA: $tcert"
tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,cafile=${tcert}${sockopt} stdio"
else
wsrep_log_info "Encrypting with PEM $tpem, CA: $tcert"
tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}"
fi
elif [[ $encrypt -eq 3 ]];then
wsrep_log_info "Using openssl based encryption with socat: with key and crt"
if [[ -z $tpem || -z $tkey ]];then
wsrep_log_error "Both certificate and key files required"
exit 22
fi
stagemsg+="-OpenSSL-Encrypted-3"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
wsrep_log_info "Decrypting with certificate $tpem, key $tkey"
tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,key=${tkey},verify=0${sockopt} stdio"
else
wsrep_log_info "Encrypting with certificate $tpem, key $tkey"
tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,key=${tkey},verify=0${sockopt}"
fi
else
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio"
else
tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}"
fi
fi
fi
}
parse_cnf()
{
local group=$1
local var=$2
reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-)
if [[ -z $reval ]];then
[[ -n $3 ]] && reval=$3
fi
echo $reval
}
get_footprint()
{
pushd $WSREP_SST_OPT_DATA 1>/dev/null
payload=$(du --block-size=1 -c **/*.ibd **/*.MYI **/*.MYI ibdata1 | awk 'END { print $1 }')
if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then
# QuickLZ has around 50% compression ratio
# When compression/compaction used, the progress is only an approximate.
payload=$(( payload*1/2 ))
fi
popd 1>/dev/null
pcmd+=" -s $payload"
adjust_progress
}
adjust_progress()
{
if [[ -n $progress && $progress != '1' ]];then
if [[ -e $progress ]];then
pcmd+=" 2>>$progress"
else
pcmd+=" 2>$progress"
fi
elif [[ -z $progress && -n $rlimit ]];then
# When rlimit is non-zero
pcmd="pv -q"
fi
if [[ -n $rlimit && "$WSREP_SST_OPT_ROLE" == "donor" ]];then
wsrep_log_info "Rate-limiting SST to $rlimit"
pcmd+=" -L \$rlimit"
fi
}
read_cnf()
{
sfmt=$(parse_cnf sst streamfmt "xbstream")
tfmt=$(parse_cnf sst transferfmt "socat")
tcert=$(parse_cnf sst tca "")
tpem=$(parse_cnf sst tcert "")
tkey=$(parse_cnf sst tkey "")
encrypt=$(parse_cnf sst encrypt 0)
sockopt=$(parse_cnf sst sockopt "")
progress=$(parse_cnf sst progress "")
rebuild=$(parse_cnf sst rebuild 0)
ttime=$(parse_cnf sst time 0)
cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$')
incremental=$(parse_cnf sst incremental 0)
ealgo=$(parse_cnf xtrabackup encrypt "")
ekey=$(parse_cnf xtrabackup encrypt-key "")
ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "")
scomp=$(parse_cnf sst compressor "")
sdecomp=$(parse_cnf sst decompressor "")
# Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html
if [[ -z $ealgo ]];then
ealgo=$(parse_cnf sst encrypt-algo "")
ekey=$(parse_cnf sst encrypt-key "")
ekeyfile=$(parse_cnf sst encrypt-key-file "")
fi
rlimit=$(parse_cnf sst rlimit "")
uextra=$(parse_cnf sst use-extra 0)
speciald=$(parse_cnf sst sst-special-dirs 1)
iopts=$(parse_cnf sst inno-backup-opts "")
iapts=$(parse_cnf sst inno-apply-opts "")
impts=$(parse_cnf sst inno-move-opts "")
}
get_stream()
{
if [[ $sfmt == 'xbstream' ]];then
wsrep_log_info "Streaming with xbstream"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
strmcmd="xbstream -x"
else
strmcmd="xbstream -c \${INFO_FILE}"
fi
else
sfmt="tar"
wsrep_log_info "Streaming with tar"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
strmcmd="tar xfi - "
else
strmcmd="tar cf - \${INFO_FILE} "
fi
fi
}
get_proc()
{
set +e
nproc=$(grep -c processor /proc/cpuinfo)
[[ -z $nproc || $nproc -eq 0 ]] && nproc=1
set -e
}
sig_joiner_cleanup()
{
wsrep_log_error "Removing $MAGIC_FILE file due to signal"
rm -f "$MAGIC_FILE"
}
cleanup_joiner()
{
# Since this is invoked just after exit NNN
local estatus=$?
if [[ $estatus -ne 0 ]];then
wsrep_log_error "Cleanup after exit with status:$estatus"
fi
if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then
wsrep_log_info "Removing the sst_in_progress file"
wsrep_cleanup_progress_file
fi
if [[ -n $progress && -p $progress ]];then
wsrep_log_info "Cleaning up fifo file $progress"
rm $progress
fi
if [[ -n ${STATDIR:-} ]];then
[[ -d $STATDIR ]] && rm -rf $STATDIR
fi
}
check_pid()
{
local pid_file="$1"
[ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1
}
cleanup_donor()
{
# Since this is invoked just after exit NNN
local estatus=$?
if [[ $estatus -ne 0 ]];then
wsrep_log_error "Cleanup after exit with status:$estatus"
fi
if [[ -n $XTRABACKUP_PID ]];then
if check_pid $XTRABACKUP_PID
then
wsrep_log_error "xtrabackup process is still running. Killing... "
kill_xtrabackup
fi
rm -f $XTRABACKUP_PID
fi
rm -f ${DATA}/${IST_FILE}
if [[ -n $progress && -p $progress ]];then
wsrep_log_info "Cleaning up fifo file $progress"
rm $progress
fi
}
kill_xtrabackup()
{
local PID=$(cat $XTRABACKUP_PID)
[ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || :
rm -f "$XTRABACKUP_PID"
}
setup_ports()
{
if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }')
REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }')
lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }')
else
SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }')
fi
}
# waits ~10 seconds for nc to open the port and then reports ready
# (regardless of timeout)
wait_for_listen()
{
local PORT=$1
local ADDR=$2
local MODULE=$3
for i in {1..50}
do
ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break
sleep 0.2
done
if [[ $incremental -eq 1 ]];then
echo "ready ${ADDR}/${MODULE}/$lsn"
else
echo "ready ${ADDR}/${MODULE}"
fi
}
check_extra()
{
local use_socket=1
if [[ $uextra -eq 1 ]];then
if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then
local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2)
if [[ -n $eport ]];then
# Xtrabackup works only locally.
# Hence, setting host to 127.0.0.1 unconditionally.
wsrep_log_info "SST through extra_port $eport"
INNOEXTRA+=" --host=127.0.0.1 --port=$eport "
use_socket=0
else
wsrep_log_error "Extra port $eport null, failing"
exit 1
fi
else
wsrep_log_info "Thread pool not set, ignore the option use_extra"
fi
fi
if [[ $use_socket -eq 1 ]] && [[ -n "${WSREP_SST_OPT_SOCKET}" ]];then
INNOEXTRA+=" --socket=${WSREP_SST_OPT_SOCKET}"
fi
}
recv_joiner()
{
local dir=$1
local msg=$2
pushd ${dir} 1>/dev/null
set +e
timeit "$msg" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )"
set -e
popd 1>/dev/null
for ecode in "${RC[@]}";do
if [[ $ecode -ne 0 ]];then
wsrep_log_error "Error while getting data from donor node: " \
"exit codes: ${RC[@]}"
exit 32
fi
done
if [ ! -r "${MAGIC_FILE}" ];then
# this message should cause joiner to abort
wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'"
wsrep_log_info "Contents of datadir"
wsrep_log_info "$(ls -l ${dir}/*)"
exit 32
fi
}
send_donor()
{
local dir=$1
local msg=$2
pushd ${dir} 1>/dev/null
set +e
timeit "$msg" "$strmcmd | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
set -e
popd 1>/dev/null
for ecode in "${RC[@]}";do
if [[ $ecode -ne 0 ]];then
wsrep_log_error "Error while getting data from donor node: " \
"exit codes: ${RC[@]}"
exit 32
fi
done
}
if [[ ! -x `which innobackupex` ]];then
wsrep_log_error "innobackupex not in path: $PATH"
exit 2
fi
rm -f "${MAGIC_FILE}"
if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then
wsrep_log_error "Invalid role ${WSREP_SST_OPT_ROLE}"
exit 22
fi
read_cnf
setup_ports
get_stream
get_transfer
if ${INNOBACKUPEX_BIN} /tmp --help | grep -q -- '--version-check'; then
disver="--no-version-check"
fi
INNOEXTRA=""
INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log"
INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log"
INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $iopts \$INNOEXTRA --galera-info --stream=\$sfmt \${TMPDIR} 2>\${DATA}/innobackup.backup.log"
if [ "$WSREP_SST_OPT_ROLE" = "donor" ]
then
trap cleanup_donor EXIT
if [ $WSREP_SST_OPT_BYPASS -eq 0 ]
then
TMPDIR="${TMPDIR:-/tmp}"
if [ "${AUTH[0]}" != "(null)" ]; then
INNOEXTRA+=" --user=${AUTH[0]}"
fi
if [ ${#AUTH[*]} -eq 2 ]; then
INNOEXTRA+=" --password=${AUTH[1]}"
elif [ "${AUTH[0]}" != "(null)" ]; then
# Empty password, used for testing, debugging etc.
INNOEXTRA+=" --password="
fi
get_keys
if [[ $encrypt -eq 1 ]];then
if [[ -n $ekey ]];then
INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey "
else
INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile "
fi
fi
if [[ -n $lsn ]];then
INNOEXTRA+=" --incremental --incremental-lsn=$lsn "
fi
check_extra
wsrep_log_info "Streaming GTID file before SST"
echo "${WSREP_SST_OPT_GTID}" > "${MAGIC_FILE}"
ttcmd="$tcmd"
if [[ $encrypt -eq 1 ]];then
if [[ -n $scomp ]];then
tcmd=" $ecmd | $scomp | $tcmd "
else
tcmd=" $ecmd | $tcmd "
fi
elif [[ -n $scomp ]];then
tcmd=" $scomp | $tcmd "
fi
send_donor $DATA "${stagemsg}-gtid"
tcmd="$ttcmd"
if [[ -n $progress ]];then
get_footprint
tcmd="$pcmd | $tcmd"
elif [[ -n $rlimit ]];then
adjust_progress
tcmd="$pcmd | $tcmd"
fi
wsrep_log_info "Sleeping before data transfer for SST"
sleep 10
wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT:-4444}"
if [[ -n $scomp ]];then
tcmd="$scomp | $tcmd"
fi
set +e
timeit "${stagemsg}-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
set -e
if [ ${RC[0]} -ne 0 ]; then
wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \
"Check ${DATA}/innobackup.backup.log"
exit 22
elif [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then
wsrep_log_error "$tcmd finished with error: ${RC[1]}"
exit 22
fi
# innobackupex implicitly writes PID to fixed location in ${TMPDIR}
XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid"
else # BYPASS FOR IST
wsrep_log_info "Bypassing the SST for IST"
echo "continue" # now server can resume updating data
echo "${WSREP_SST_OPT_GTID}" > "${MAGIC_FILE}"
echo "1" > "${DATA}/${IST_FILE}"
get_keys
if [[ $encrypt -eq 1 ]];then
if [[ -n $scomp ]];then
tcmd=" $ecmd | $scomp | $tcmd "
else
tcmd=" $ecmd | $tcmd "
fi
elif [[ -n $scomp ]];then
tcmd=" $scomp | $tcmd "
fi
strmcmd+=" \${IST_FILE}"
send_donor $DATA "${stagemsg}-IST"
fi
echo "done ${WSREP_SST_OPT_GTID}"
wsrep_log_info "Total time on donor: $totime seconds"
elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ]
then
[[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE"
[[ -n $SST_PROGRESS_FILE ]] && touch $SST_PROGRESS_FILE
if [[ $speciald -eq 1 ]];then
ib_home_dir=$(parse_cnf mysqld innodb-data-home-dir "")
ib_log_dir=$(parse_cnf mysqld innodb-log-group-home-dir "")
if [[ -z $ib_home_dir && -z $ib_log_dir ]];then
speciald=0
fi
fi
stagemsg="Joiner-Recv"
if [[ ! -e ${DATA}/ibdata1 ]];then
incremental=0
fi
if [[ $incremental -eq 1 ]];then
wsrep_log_info "Incremental SST enabled: NOT SUPPORTED yet"
lsn=$(grep to_lsn xtrabackup_checkpoints | cut -d= -f2 | tr -d ' ')
wsrep_log_info "Recovered LSN: $lsn"
fi
sencrypted=1
nthreads=1
MODULE="xtrabackup_sst"
rm -f "${DATA}/${IST_FILE}"
# May need xtrabackup_checkpoints later on
rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile
ADDR=${WSREP_SST_OPT_ADDR}
if [ -z "${SST_PORT}" ]
then
SST_PORT=4444
ADDR="$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $1 }'):${SST_PORT}"
fi
wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} &
trap sig_joiner_cleanup HUP PIPE INT TERM
trap cleanup_joiner EXIT
if [[ -n $progress ]];then
adjust_progress
tcmd+=" | $pcmd"
fi
if [[ $incremental -eq 1 ]];then
BDATA=$DATA
DATA=$(mktemp -d)
MAGIC_FILE="${DATA}/${INFO_FILE}"
fi
get_keys
if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then
if [[ -n $sdecomp ]];then
strmcmd=" $sdecomp | $ecmd | $strmcmd"
else
strmcmd=" $ecmd | $strmcmd"
fi
elif [[ -n $sdecomp ]];then
strmcmd=" $sdecomp | $strmcmd"
fi
STATDIR=$(mktemp -d)
MAGIC_FILE="${STATDIR}/${INFO_FILE}"
recv_joiner $STATDIR "${stagemsg}-gtid" 1
if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null
then
wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly."
exit 32
fi
if [ ! -r "${STATDIR}/${IST_FILE}" ]
then
wsrep_log_info "Proceeding with SST"
if [[ $speciald -eq 1 && -d ${DATA}/.sst ]];then
wsrep_log_info "WARNING: Stale temporary SST directory: ${DATA}/.sst from previous SST"
fi
if [[ $incremental -ne 1 ]];then
if [[ $speciald -eq 1 ]];then
wsrep_log_info "Cleaning the existing datadir and innodb-data/log directories"
find $ib_home_dir $ib_log_dir $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+
else
wsrep_log_info "Cleaning the existing datadir"
find $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+
fi
tempdir=$(parse_cnf mysqld log-bin "")
if [[ -n ${tempdir:-} ]];then
binlog_dir=$(dirname $tempdir)
binlog_file=$(basename $tempdir)
if [[ -n ${binlog_dir:-} && $binlog_dir != '.' && $binlog_dir != $DATA ]];then
pattern="$binlog_dir/$binlog_file\.[0-9]+$"
wsrep_log_info "Cleaning the binlog directory $binlog_dir as well"
find $binlog_dir -maxdepth 1 -type f -regex $pattern -exec rm -fv {} 1>&2 \+
rm $binlog_dir/*.index || true
fi
fi
else
wsrep_log_info "Removing existing ib_logfile files"
rm -f ${BDATA}/ib_logfile*
fi
if [[ $speciald -eq 1 ]];then
mkdir -p ${DATA}/.sst
TDATA=${DATA}
DATA="${DATA}/.sst"
fi
MAGIC_FILE="${DATA}/${INFO_FILE}"
recv_joiner $DATA "${stagemsg}-SST" 0
get_proc
# Rebuild indexes for compact backups
if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then
wsrep_log_info "Index compaction detected"
rebuild=1
fi
if [[ $rebuild -eq 1 ]];then
nthreads=$(parse_cnf xtrabackup rebuild-threads $nproc)
wsrep_log_info "Rebuilding during prepare with $nthreads threads"
rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads"
fi
if test -n "$(find ${DATA} -maxdepth 1 -type f -name '*.qp' -print -quit)";then
wsrep_log_info "Compressed qpress files found"
if [[ ! -x `which qpress` ]];then
wsrep_log_error "qpress not found in path: $PATH"
exit 22
fi
if [[ -n $progress ]] && pv --help | grep -q 'line-mode';then
count=$(find ${DATA} -type f -name '*.qp' | wc -l)
count=$(( count*2 ))
if pv --help | grep -q FORMAT;then
pvopts="-f -s $count -l -N Decompression -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'"
else
pvopts="-f -s $count -l -N Decompression"
fi
pcmd="pv $pvopts"
adjust_progress
dcmd="$pcmd | xargs -n 2 qpress -T${nproc}d"
else
dcmd="xargs -n 2 qpress -T${nproc}d"
fi
# Decompress the qpress files
wsrep_log_info "Decompression with $nproc threads"
timeit "Joiner-Decompression" "find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd"
extcode=$?
if [[ $extcode -eq 0 ]];then
wsrep_log_info "Removing qpress files after decompression"
find ${DATA} -type f -name '*.qp' -delete
if [[ $? -ne 0 ]];then
wsrep_log_error "Something went wrong with deletion of qpress files. Investigate"
fi
else
wsrep_log_error "Decompression failed. Exit code: $extcode"
exit 22
fi
fi
if [[ $incremental -eq 1 ]];then
# Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues.
INNOAPPLY="${INNOBACKUPEX_BIN} $disver --defaults-file=${WSREP_SST_OPT_CONF} \
--ibbackup=xtrabackup_55 --apply-log $rebuildcmd --redo-only $BDATA --incremental-dir=${DATA} &>>${BDATA}/innobackup.prepare.log"
fi
wsrep_log_info "Preparing the backup at ${DATA}"
timeit "Xtrabackup prepare stage" "$INNOAPPLY"
if [ $? -ne 0 ];
then
wsrep_log_error "${INNOBACKUPEX_BIN} apply finished with errors. Check ${DATA}/innobackup.prepare.log"
exit 22
fi
if [[ $speciald -eq 1 ]];then
MAGIC_FILE="${TDATA}/${INFO_FILE}"
set +e
rm $TDATA/innobackup.prepare.log $TDATA/innobackup.move.log
set -e
wsrep_log_info "Moving the backup to ${TDATA}"
timeit "Xtrabackup move stage" "$INNOMOVE"
if [[ $? -eq 0 ]];then
wsrep_log_info "Move successful, removing ${DATA}"
rm -rf $DATA
DATA=${TDATA}
else
wsrep_log_error "Move failed, keeping ${DATA} for further diagnosis"
wsrep_log_error "Check ${DATA}/innobackup.move.log for details"
fi
fi
if [[ $incremental -eq 1 ]];then
wsrep_log_info "Cleaning up ${DATA} after incremental SST"
[[ -d ${DATA} ]] && rm -rf ${DATA}
DATA=$BDATA
fi
else
wsrep_log_info "${IST_FILE} received from donor: Running IST"
fi
if [[ ! -r ${MAGIC_FILE} ]];then
wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable"
exit 2
fi
cat "${MAGIC_FILE}" # output UUID:seqno
wsrep_log_info "Total time on joiner: $totime seconds"
fi
exit 0

View File

@ -34,6 +34,11 @@
# lp:1193240 requires you to manually cleanup the directory prior to SST # # lp:1193240 requires you to manually cleanup the directory prior to SST #
# # # #
############################################################################################################# #############################################################################################################
# Optional dependencies and options documented here: http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html
# Make sure to read that before proceeding!
. $(dirname $0)/wsrep_sst_common . $(dirname $0)/wsrep_sst_common
@ -44,28 +49,89 @@ encrypt=0
nproc=1 nproc=1
ecode=0 ecode=0
XTRABACKUP_PID="" XTRABACKUP_PID=""
SST_PORT=""
REMOTEIP=""
tcert=""
tpem=""
sockopt=""
progress=""
ttime=0
totime=0
lsn=""
incremental=0
ecmd=""
rlimit=""
sfmt="tar" sfmt="tar"
strmcmd="" strmcmd=""
tfmt=""
tcmd=""
rebuild=0
rebuildcmd=""
payload=0
pvformat="-F '%N => Rate:%r Avg:%a Elapsed:%t %e Bytes: %b %p' "
pvopts="-f -i 10 -N $WSREP_SST_OPT_ROLE "
uextra=0
if which pv &>/dev/null && pv --help | grep -q FORMAT;then
pvopts+=$pvformat
fi
pcmd="pv $pvopts"
declare -a RC declare -a RC
INNOBACKUPEX_BIN=innobackupex
readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ })
DATA="${WSREP_SST_OPT_DATA}"
INFO_FILE="xtrabackup_galera_info"
IST_FILE="xtrabackup_ist"
MAGIC_FILE="${DATA}/${INFO_FILE}"
# Setting the path for ss and ip
export PATH="/usr/sbin:/sbin:$PATH"
timeit(){
local stage=$1
shift
local cmd="$@"
local x1 x2 took extcode
if [[ $ttime -eq 1 ]];then
x1=$(date +%s)
wsrep_log_info "Evaluating $cmd"
eval "$cmd"
extcode=$?
x2=$(date +%s)
took=$(( x2-x1 ))
wsrep_log_info "NOTE: $stage took $took seconds"
totime=$(( totime+took ))
else
wsrep_log_info "Evaluating $cmd"
eval "$cmd"
extcode=$?
fi
return $extcode
}
get_keys() get_keys()
{ {
# There is no metadata in the stream to indicate that it is encrypted if [[ $encrypt -eq 2 ]];then
# So, if the cnf file on joiner contains 'encrypt' under [xtrabackup] section then
# it means encryption is being used
if ! my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt; then
return
fi
if [[ $sfmt == 'tar' ]];then
wsrep_log_info "NOTE: Encryption cannot be enabled with tar format"
return return
fi fi
wsrep_log_info "Encryption enabled in my.cnf - not supported at the moment - Bug in Xtrabackup - lp:1190343" if [[ $encrypt -eq 0 ]];then
ealgo=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt=' | cut -d= -f2) if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then
ekey=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key=' | cut -d= -f2) wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html "
ekeyfile=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key-file=' | cut -d= -f2) fi
return
fi
if [[ $sfmt == 'tar' ]];then
wsrep_log_info "NOTE: Xtrabackup-based encryption - encrypt=1 - cannot be enabled with tar format"
encrypt=0
return
fi
wsrep_log_info "Xtrabackup based encryption enabled in my.cnf - Supported only from Xtrabackup 2.1.4"
if [[ -z $ealgo ]];then if [[ -z $ealgo ]];then
wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out" wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out"
@ -76,35 +142,160 @@ get_keys()
wsrep_log_error "FATAL: Either key or keyfile must be readable" wsrep_log_error "FATAL: Either key or keyfile must be readable"
exit 3 exit 3
fi fi
encrypt=1
if [[ -z $ekey ]];then
ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile"
else
ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey"
fi
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
ecmd+=" -d"
fi
}
get_transfer()
{
if [[ -z $SST_PORT ]];then
TSST_PORT=4444
else
TSST_PORT=$SST_PORT
fi
if [[ $tfmt == 'nc' ]];then
if [[ ! -x `which nc` ]];then
wsrep_log_error "nc(netcat) not found in path: $PATH"
exit 2
fi
wsrep_log_info "Using netcat as streamer"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
tcmd="nc -dl ${TSST_PORT}"
else
tcmd="nc ${REMOTEIP} ${TSST_PORT}"
fi
else
tfmt='socat'
wsrep_log_info "Using socat as streamer"
if [[ ! -x `which socat` ]];then
wsrep_log_error "socat not found in path: $PATH"
exit 2
fi
if [[ $encrypt -eq 2 ]] && ! socat -V | grep -q OPENSSL;then
wsrep_log_info "NOTE: socat is not openssl enabled, falling back to plain transfer"
encrypt=0
fi
if [[ $encrypt -eq 2 ]];then
wsrep_log_info "Using openssl based encryption with socat"
if [[ -z $tpem || -z $tcert ]];then
wsrep_log_error "Both PEM and CRT files required"
exit 22
fi
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
wsrep_log_info "Decrypting with PEM $tpem, CA: $tcert"
tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,cafile=${tcert}${sockopt} stdio"
else
wsrep_log_info "Encrypting with PEM $tpem, CA: $tcert"
tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}"
fi
else
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio"
else
tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}"
fi
fi
fi
}
parse_cnf()
{
local group=$1
local var=$2
reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-)
if [[ -z $reval ]];then
[[ -n $3 ]] && reval=$3
fi
echo $reval
}
get_footprint()
{
pushd $WSREP_SST_OPT_DATA 1>/dev/null
payload=$(du --block-size=1 -c **/*.ibd **/*.MYI **/*.MYI ibdata1 | awk 'END { print $1 }')
if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then
# QuickLZ has around 50% compression ratio
# When compression/compaction used, the progress is only an approximate.
payload=$(( payload*1/2 ))
fi
popd 1>/dev/null
pcmd+=" -s $payload"
adjust_progress
}
adjust_progress()
{
if [[ -n $progress && $progress != '1' ]];then
if [[ -e $progress ]];then
pcmd+=" 2>>$progress"
else
pcmd+=" 2>$progress"
fi
elif [[ -z $progress && -n $rlimit ]];then
# When rlimit is non-zero
pcmd="pv -q"
fi
if [[ -n $rlimit && "$WSREP_SST_OPT_ROLE" == "donor" ]];then
wsrep_log_info "Rate-limiting SST to $rlimit"
pcmd+=" -L \$rlimit"
fi
} }
read_cnf() read_cnf()
{ {
sfmt=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- '--streamfmt' | cut -d= -f2) sfmt=$(parse_cnf sst streamfmt "tar")
tfmt=$(parse_cnf sst transferfmt "socat")
tcert=$(parse_cnf sst tca "")
tpem=$(parse_cnf sst tcert "")
encrypt=$(parse_cnf sst encrypt 0)
sockopt=$(parse_cnf sst sockopt "")
progress=$(parse_cnf sst progress "")
rebuild=$(parse_cnf sst rebuild 0)
ttime=$(parse_cnf sst time 0)
incremental=$(parse_cnf sst incremental 0)
ealgo=$(parse_cnf xtrabackup encrypt "")
ekey=$(parse_cnf xtrabackup encrypt-key "")
ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "")
# Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html
if [[ -z $ealgo ]];then
ealgo=$(parse_cnf sst encrypt-algo "")
ekey=$(parse_cnf sst encrypt-key "")
ekeyfile=$(parse_cnf sst encrypt-key-file "")
fi
rlimit=$(parse_cnf sst rlimit "")
uextra=$(parse_cnf sst use_extra 0)
}
get_stream()
{
if [[ $sfmt == 'xbstream' ]];then if [[ $sfmt == 'xbstream' ]];then
wsrep_log_info "Streaming with xbstream" wsrep_log_info "Streaming with xbstream"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
wsrep_log_info "xbstream requires manual cleanup of data directory before SST - lp:1193240" strmcmd="xbstream -x"
strmcmd="xbstream -x -C ${DATA}"
elif [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
strmcmd="xbstream -c ${INFO_FILE} ${IST_FILE}"
else else
wsrep_log_error "Invalid role: $WSREP_SST_OPT_ROLE" strmcmd="xbstream -c \${INFO_FILE} \${IST_FILE}"
exit 22
fi fi
else else
sfmt="tar" sfmt="tar"
wsrep_log_info "Streaming with tar" wsrep_log_info "Streaming with tar"
wsrep_log_info "Note: Advanced xtrabackup features - encryption,compression etc. not available with tar."
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
wsrep_log_info "However, xbstream requires manual cleanup of data directory before SST - lp:1193240." strmcmd="tar xfi - --recursive-unlink -h"
strmcmd="tar xfi - -C ${DATA}"
elif [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
strmcmd="tar cf - ${INFO_FILE} ${IST_FILE}"
else else
wsrep_log_error "Invalid role: $WSREP_SST_OPT_ROLE" strmcmd="tar cf - \${INFO_FILE} \${IST_FILE}"
exit 22
fi fi
fi fi
@ -118,6 +309,12 @@ get_proc()
set -e set -e
} }
sig_joiner_cleanup()
{
wsrep_log_error "Removing $MAGIC_FILE file due to signal"
rm -f "$MAGIC_FILE"
}
cleanup_joiner() cleanup_joiner()
{ {
# Since this is invoked just after exit NNN # Since this is invoked just after exit NNN
@ -125,18 +322,14 @@ cleanup_joiner()
if [[ $estatus -ne 0 ]];then if [[ $estatus -ne 0 ]];then
wsrep_log_error "Cleanup after exit with status:$estatus" wsrep_log_error "Cleanup after exit with status:$estatus"
fi fi
local PID=$(ps -aef |grep nc| grep $NC_PORT | awk '{ print $2 }')
if [[ $estatus -ne 0 ]];then
wsrep_log_error "Killing nc pid $PID"
else
wsrep_log_info "Killing nc pid $PID"
fi
[ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || :
rm -f "$MAGIC_FILE"
if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then
wsrep_log_info "Removing the sst_in_progress file" wsrep_log_info "Removing the sst_in_progress file"
wsrep_cleanup_progress_file wsrep_cleanup_progress_file
fi fi
if [[ -n $progress && -p $progress ]];then
wsrep_log_info "Cleaning up fifo file $progress"
rm $progress
fi
} }
check_pid() check_pid()
@ -152,119 +345,161 @@ cleanup_donor()
if [[ $estatus -ne 0 ]];then if [[ $estatus -ne 0 ]];then
wsrep_log_error "Cleanup after exit with status:$estatus" wsrep_log_error "Cleanup after exit with status:$estatus"
fi fi
local pid=$XTRABACKUP_PID
if check_pid "$pid" if [[ -n $XTRABACKUP_PID ]];then
if check_pid $XTRABACKUP_PID
then then
wsrep_log_error "xtrabackup process is still running. Killing... " wsrep_log_error "xtrabackup process is still running. Killing... "
kill_xtrabackup kill_xtrabackup
fi fi
rm -f "$pid" rm -f $XTRABACKUP_PID
fi
rm -f ${DATA}/${IST_FILE} rm -f ${DATA}/${IST_FILE}
if [[ -n $progress && -p $progress ]];then
wsrep_log_info "Cleaning up fifo file $progress"
rm $progress
fi
} }
kill_xtrabackup() kill_xtrabackup()
{ {
#set -x
local PID=$(cat $XTRABACKUP_PID) local PID=$(cat $XTRABACKUP_PID)
[ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || :
rm -f "$XTRABACKUP_PID" rm -f "$XTRABACKUP_PID"
#set +x }
setup_ports()
{
if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }')
REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }')
lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }')
else
SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }')
fi
} }
# waits ~10 seconds for nc to open the port and then reports ready # waits ~10 seconds for nc to open the port and then reports ready
# (regardless of timeout) # (regardless of timeout)
wait_for_nc() wait_for_listen()
{ {
local PORT=$1 local PORT=$1
local ADDR=$2 local ADDR=$2
local MODULE=$3 local MODULE=$3
for i in $(seq 1 50) for i in {1..50}
do do
netstat -nptl 2>/dev/null | grep '/nc\s*$' | awk '{ print $4 }' | \ ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break
sed 's/.*://' | grep \^${PORT}\$ >/dev/null && break
sleep 0.2 sleep 0.2
done done
if [[ $incremental -eq 1 ]];then
echo "ready ${ADDR}/${MODULE}/$lsn"
else
echo "ready ${ADDR}/${MODULE}" echo "ready ${ADDR}/${MODULE}"
fi
} }
INNOBACKUPEX_BIN=innobackupex check_extra()
INNOBACKUPEX_ARGS="" {
NC_BIN=nc local use_socket=1
if [[ $uextra -eq 1 ]];then
for TOOL_BIN in INNOBACKUPEX_BIN NC_BIN ; do if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then
if ! which ${!TOOL_BIN} > /dev/null 2>&1 local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2)
then if [[ -n $eport ]];then
echo "Can't find ${!TOOL_BIN} in the path" # Xtrabackup works only locally.
exit 22 # EINVAL # Hence, setting host to 127.0.0.1 unconditionally.
wsrep_log_info "SST through extra_port $eport"
INNOEXTRA+=" --host=127.0.0.1 --port=$eport "
use_socket=0
else
wsrep_log_error "Extra port $eport null, failing"
exit 1
fi fi
done else
wsrep_log_info "Thread pool not set, ignore the option use_extra"
fi
fi
if [[ $use_socket -eq 1 ]] && [[ -n "${WSREP_SST_OPT_SOCKET}" ]];then
INNOEXTRA+=" --socket=${WSREP_SST_OPT_SOCKET}"
fi
}
#ROLE=$1 if [[ ! -x `which innobackupex` ]];then
#ADDR=$2 wsrep_log_error "innobackupex not in path: $PATH"
readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ }) exit 2
readonly DATA="${WSREP_SST_OPT_DATA}" fi
#CONF=$5
INFO_FILE="xtrabackup_galera_info"
IST_FILE="xtrabackup_ist"
MAGIC_FILE="${DATA}/${INFO_FILE}"
rm -f "${MAGIC_FILE}" rm -f "${MAGIC_FILE}"
if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then
wsrep_log_error "Invalid role ${WSREP_SST_OPT_ROLE}"
exit 22
fi
read_cnf read_cnf
setup_ports
get_stream
get_transfer
INNOEXTRA=""
INNOAPPLY="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log"
INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} \$INNOEXTRA --galera-info --stream=\$sfmt \${TMPDIR} 2>\${DATA}/innobackup.backup.log"
if [ "$WSREP_SST_OPT_ROLE" = "donor" ] if [ "$WSREP_SST_OPT_ROLE" = "donor" ]
then then
trap cleanup_donor EXIT trap cleanup_donor EXIT
NC_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }')
REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }')
if [ $WSREP_SST_OPT_BYPASS -eq 0 ] if [ $WSREP_SST_OPT_BYPASS -eq 0 ]
then then
TMPDIR="/tmp" TMPDIR="${TMPDIR:-/tmp}"
INNOBACKUPEX_ARGS="--galera-info --stream=$sfmt
--defaults-file=${WSREP_SST_OPT_CONF}
--socket=${WSREP_SST_OPT_SOCKET}"
if [ "${AUTH[0]}" != "(null)" ]; then if [ "${AUTH[0]}" != "(null)" ]; then
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --user=${AUTH[0]}" INNOEXTRA+=" --user=${AUTH[0]}"
fi fi
if [ ${#AUTH[*]} -eq 2 ]; then if [ ${#AUTH[*]} -eq 2 ]; then
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password=${AUTH[1]}" INNOEXTRA+=" --password=${AUTH[1]}"
else elif [ "${AUTH[0]}" != "(null)" ]; then
# Empty password, used for testing, debugging etc. # Empty password, used for testing, debugging etc.
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password=" INNOEXTRA+=" --password="
fi fi
get_keys get_keys
if [[ $encrypt -eq 1 ]];then if [[ $encrypt -eq 1 ]];then
if [[ -n $ekey ]];then if [[ -n $ekey ]];then
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --encrypt=$ealgo --encrypt-key=$ekey" INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey "
else else
INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --encrypt=$ealgo --encrypt-key-file=$ekeyfile" INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile "
fi fi
fi fi
wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${NC_PORT}" if [[ -n $lsn ]];then
INNOEXTRA+=" --incremental --incremental-lsn=$lsn "
fi
check_extra
wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT}"
if [[ -n $progress ]];then
get_footprint
tcmd="$pcmd | $tcmd"
elif [[ -n $rlimit ]];then
adjust_progress
tcmd="$pcmd | $tcmd"
fi
set +e set +e
${INNOBACKUPEX_BIN} ${INNOBACKUPEX_ARGS} ${TMPDIR} \ timeit "Donor-Transfer" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
2> ${DATA}/innobackup.backup.log | \
${NC_BIN} ${REMOTEIP} ${NC_PORT}
RC=( "${PIPESTATUS[@]}" )
set -e set -e
if [ ${RC[0]} -ne 0 ]; then if [ ${RC[0]} -ne 0 ]; then
wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \ wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \
"Check ${DATA}/innobackup.backup.log" "Check ${DATA}/innobackup.backup.log"
exit 22 exit 22
elif [ ${RC[1]} -ne 0 ]; then elif [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then
wsrep_log_error "${NC_BIN} finished with error: ${RC[1]}" wsrep_log_error "$tcmd finished with error: ${RC[1]}"
exit 22 exit 22
fi fi
@ -272,7 +507,8 @@ then
XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid" XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid"
else # BYPASS else # BYPASS FOR IST
wsrep_log_info "Bypassing the SST for IST" wsrep_log_info "Bypassing the SST for IST"
STATE="${WSREP_SST_OPT_GTID}" STATE="${WSREP_SST_OPT_GTID}"
echo "continue" # now server can resume updating data echo "continue" # now server can resume updating data
@ -282,15 +518,9 @@ then
pushd ${DATA} 1>/dev/null pushd ${DATA} 1>/dev/null
set +e set +e
if [[ $encrypt -eq 1 ]];then if [[ $encrypt -eq 1 ]];then
if [[ -n $ekey ]];then tcmd=" $ecmd | $tcmd"
xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey | ${NC_BIN} ${REMOTEIP} ${NC_PORT}
else
xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | ${NC_BIN} ${REMOTEIP} ${NC_PORT}
fi fi
else timeit "Donor-IST-Unencrypted-transfer" "$strmcmd | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
$strmcmd | ${NC_BIN} ${REMOTEIP} ${NC_PORT}
fi
RC=( "${PIPESTATUS[@]}" )
set -e set -e
popd 1>/dev/null popd 1>/dev/null
@ -301,69 +531,86 @@ then
exit 1 exit 1
fi fi
done done
#rm -f ${DATA}/${IST_FILE}
fi fi
echo "done ${WSREP_SST_OPT_GTID}" echo "done ${WSREP_SST_OPT_GTID}"
wsrep_log_info "Total time on donor: $totime seconds"
elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ] elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ]
then then
[[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE" [[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE"
touch $SST_PROGRESS_FILE touch $SST_PROGRESS_FILE
if [[ ! -e ${DATA}/ibdata1 ]];then
incremental=0
fi
if [[ $incremental -eq 1 ]];then
wsrep_log_info "Incremental SST enabled"
#lsn=$(/pxc/bin/mysqld --defaults-file=$WSREP_SST_OPT_CONF --basedir=/pxc --wsrep-recover 2>&1 | grep -o 'log sequence number .*' | cut -d " " -f 4 | head -1)
lsn=$(grep to_lsn xtrabackup_checkpoints | cut -d= -f2 | tr -d ' ')
wsrep_log_info "Recovered LSN: $lsn"
fi
sencrypted=1 sencrypted=1
nthreads=1 nthreads=1
MODULE="xtrabackup_sst" MODULE="xtrabackup_sst"
rm -f ${DATA}/xtrabackup_* # May need xtrabackup_checkpoints later on
rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile
ADDR=${WSREP_SST_OPT_ADDR} ADDR=${WSREP_SST_OPT_ADDR}
NC_PORT=$(echo ${ADDR} | awk -F ':' '{ print $2 }') if [ -z "${SST_PORT}" ]
if [ -z "${NC_PORT}" ]
then then
NC_PORT=4444 SST_PORT=4444
ADDR="$(echo ${ADDR} | awk -F ':' '{ print $1 }'):${NC_PORT}" ADDR="$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $1 }'):${SST_PORT}"
fi fi
wait_for_nc ${NC_PORT} ${ADDR} ${MODULE} & wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} &
trap "exit 32" HUP PIPE trap sig_joiner_cleanup HUP PIPE INT TERM
trap "exit 3" INT TERM
trap cleanup_joiner EXIT trap cleanup_joiner EXIT
if [[ -n $progress ]];then
adjust_progress
tcmd+=" | $pcmd"
fi
if [[ $incremental -eq 1 ]];then
BDATA=$DATA
DATA=$(mktemp -d)
MAGIC_FILE="${DATA}/${INFO_FILE}"
fi
get_keys get_keys
set +e set +e
if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then
if [[ -n $ekey ]];then strmcmd=" $ecmd | $strmcmd"
${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey | xbstream -x -C ${DATA}
else
${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | xbstream -x -C ${DATA}
fi fi
else
${NC_BIN} -dl ${NC_PORT} | $strmcmd pushd ${DATA} 1>/dev/null
fi timeit "Joiner-Recv-Unencrypted" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )"
RC=( "${PIPESTATUS[@]}" ) popd 1>/dev/null
set -e set -e
if [[ $sfmt == 'xbstream' ]];then if [[ $sfmt == 'xbstream' ]];then
# Special handling till lp:1193240 is fixed" # Special handling till lp:1193240 is fixed"
if [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then if [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then
wsrep_log_error "Xbstream failed" wsrep_log_error "Xbstream failed"
wsrep_log_error "Data directory ${DATA} needs to be empty for SST: lp:1193240" \ wsrep_log_error "Data directory ${DATA} may not be empty: lp:1193240" \
"Manual intervention required in that case" "Manual intervention required in that case"
exit 32 exit 32
fi fi
fi fi
wait %% # join wait_for_nc thread wait %% # join for wait_for_listen thread
for ecode in "${RC[@]}";do for ecode in "${RC[@]}";do
if [[ $ecode -ne 0 ]];then if [[ $ecode -ne 0 ]];then
wsrep_log_error "Error while getting data from donor node: " \ wsrep_log_error "Error while getting data from donor node: " \
"exit codes: ${RC[@]}" "exit codes: ${RC[@]}"
wsrep_log_error "Data directory ${DATA} needs to be empty for SST:" \
"Manual intervention required in that case"
exit 32 exit 32
fi fi
done done
@ -372,43 +619,25 @@ then
then then
# this message should cause joiner to abort # this message should cause joiner to abort
wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'" wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'"
wsrep_log_info "Contents of datadir"
wsrep_log_info "$(ls -l ${DATA}/**/*)"
exit 32 exit 32
fi fi
if ! ps -p ${WSREP_SST_OPT_PARENT} >/dev/null if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null
then then
wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly."
exit 32 exit 32
fi fi
if [ ! -r "${IST_FILE}" ] if [ ! -r "${DATA}/${IST_FILE}" ]
then then
wsrep_log_info "Proceeding with SST" wsrep_log_info "Proceeding with SST"
rebuild=""
wsrep_log_info "Removing existing ib_logfile files" wsrep_log_info "Removing existing ib_logfile files"
if [[ $incremental -ne 1 ]];then
rm -f ${DATA}/ib_logfile* rm -f ${DATA}/ib_logfile*
# Decrypt only if not encrypted in stream.
# NOT USED NOW.
# Till https://blueprints.launchpad.net/percona-xtrabackup/+spec/add-support-for-rsync-url
# is implemented
#get_keys
if [[ $encrypt -eq 1 && $sencrypted -eq 0 ]];then
# Decrypt the files if any
find ${DATA} -type f -name '*.xbcrypt' -printf '%p\n' | while read line;do
input=$line
output=${input%.xbcrypt}
if [[ -n $ekey ]];then
xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey -i $input > $output
else else
xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile -i $input > $output rm -f ${BDATA}/ib_logfile*
fi
done
if [[ $? = 0 ]];then
find ${DATA} -type f -name '*.xbcrypt' -delete
fi
fi fi
get_proc get_proc
@ -416,33 +645,47 @@ then
# Rebuild indexes for compact backups # Rebuild indexes for compact backups
if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then
wsrep_log_info "Index compaction detected" wsrep_log_info "Index compaction detected"
nthreads=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--rebuild-threads' | cut -d= -f2) rebuild=1
[[ -z $nthreads ]] && nthreads=$nproc
wsrep_log_info "Rebuilding with $nthreads threads"
rebuild="--rebuild-indexes --rebuild-threads=$nthreads"
fi fi
if test -n "$(find ${DATA} -maxdepth 1 -name '*.qp' -print -quit)";then if [[ $rebuild -eq 1 ]];then
nthreads=$(parse_cnf xtrabackup rebuild-threads $nproc)
wsrep_log_info "Rebuilding during prepare with $nthreads threads"
rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads"
fi
if test -n "$(find ${DATA} -maxdepth 1 -type f -name '*.qp' -print -quit)";then
wsrep_log_info "Compressed qpress files found" wsrep_log_info "Compressed qpress files found"
if [[ ! -x `which qpress` ]];then if [[ ! -x `which qpress` ]];then
wsrep_log_error "qpress not found in PATH" wsrep_log_error "qpress not found in path: $PATH"
exit 22 exit 22
fi fi
set +e if [[ -n $progress ]] && pv --help | grep -q 'line-mode';then
count=$(find ${DATA} -type f -name '*.qp' | wc -l)
count=$(( count*2 ))
if pv --help | grep -q FORMAT;then
pvopts="-f -s $count -l -N Decompression -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'"
else
pvopts="-f -s $count -l -N Decompression"
fi
pcmd="pv $pvopts"
adjust_progress
dcmd="$pcmd | xargs -n 2 qpress -T${nproc}d"
else
dcmd="xargs -n 2 qpress -T${nproc}d"
fi
wsrep_log_info "Removing existing ibdata1 file" wsrep_log_info "Removing existing ibdata1 file"
rm -f ${DATA}/ibdata1 rm -f ${DATA}/ibdata1
# Decompress the qpress files # Decompress the qpress files
wsrep_log_info "Decompression with $nproc threads" wsrep_log_info "Decompression with $nproc threads"
find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | xargs -P $nproc -n 2 qpress -d timeit "Decompression" "find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd"
extcode=$? extcode=$?
set -e
if [[ $extcode -eq 0 ]];then if [[ $extcode -eq 0 ]];then
wsrep_log_info "Removing qpress files after decompression" wsrep_log_info "Removing qpress files after decompression"
find ${DATA} -type f -name '*.qp' -delete find ${DATA} -type f -name '*.qp' -delete
@ -455,10 +698,21 @@ then
fi fi
fi fi
wsrep_log_info "Preparing the backup at ${DATA}" if [[ $incremental -eq 1 ]];then
# Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues.
INNOAPPLY="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} \
--ibbackup=xtrabackup_55 --apply-log $rebuildcmd --redo-only $BDATA --incremental-dir=${DATA} &>>${BDATA}/innobackup.prepare.log"
fi
wsrep_log_info "Preparing the backup at ${DATA}"
timeit "Xtrabackup prepare stage" "$INNOAPPLY"
if [[ $incremental -eq 1 ]];then
wsrep_log_info "Cleaning up ${DATA} after incremental SST"
[[ -d ${DATA} ]] && rm -rf ${DATA}
DATA=$BDATA
fi
${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log $rebuild \
${DATA} 1>&2 2> ${DATA}/innobackup.prepare.log
if [ $? -ne 0 ]; if [ $? -ne 0 ];
then then
wsrep_log_error "${INNOBACKUPEX_BIN} finished with errors. Check ${DATA}/innobackup.prepare.log" wsrep_log_error "${INNOBACKUPEX_BIN} finished with errors. Check ${DATA}/innobackup.prepare.log"
@ -468,14 +722,13 @@ then
wsrep_log_info "${IST_FILE} received from donor: Running IST" wsrep_log_info "${IST_FILE} received from donor: Running IST"
fi fi
if [[ ! -r ${MAGIC_FILE} ]];then
wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable"
exit 2
fi
cat "${MAGIC_FILE}" # output UUID:seqno cat "${MAGIC_FILE}" # output UUID:seqno
wsrep_log_info "Total time on joiner: $totime seconds"
#Cleanup not required here since EXIT trap should be called
#wsrep_cleanup_progress_file
else
wsrep_log_error "Unrecognized role: ${WSREP_SST_OPT_ROLE}"
exit 22 # EINVAL
fi fi
exit 0 exit 0

View File

@ -385,7 +385,13 @@ const char *ha_partition::table_type() const
// we can do this since we only support a single engine type // we can do this since we only support a single engine type
return m_file[0]->table_type(); return m_file[0]->table_type();
} }
#ifdef WITH_WSREP
int ha_partition::wsrep_db_type() const
{
// we can do this since we only support a single engine type
return ha_legacy_type(m_file[0]->ht);
}
#endif /* WITH_WSREP */
/* /*
Destructor method Destructor method

View File

@ -1265,6 +1265,7 @@ public:
return h; return h;
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
virtual int wsrep_db_type() const;
void wsrep_reset_files() void wsrep_reset_files()
{ {
for (uint i=0; i < m_tot_parts; i++) for (uint i=0; i < m_tot_parts; i++)

View File

@ -1148,10 +1148,27 @@ int ha_prepare(THD *thd)
{ {
if ((err= ht->prepare(ht, thd, all))) if ((err= ht->prepare(ht, thd, all)))
{ {
#ifdef WITH_WSREP
if (WSREP(thd) && ht->db_type== DB_TYPE_WSREP)
{
error= 1;
/* avoid sending error, if we need to replay */
if (thd->wsrep_conflict_state!= MUST_REPLAY)
{
my_error(ER_LOCK_DEADLOCK, MYF(0), err);
}
}
else
{
/* not wsrep hton, bail to native mysql behavior */
#endif
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
ha_rollback_trans(thd, all); ha_rollback_trans(thd, all);
error=1; error=1;
break; break;
#ifdef WITH_WSREP
}
#endif
} }
} }
else else
@ -1407,12 +1424,21 @@ int ha_commit_trans(THD *thd, bool all)
if (WSREP(thd) && ht->db_type== DB_TYPE_WSREP) if (WSREP(thd) && ht->db_type== DB_TYPE_WSREP)
{ {
error= 1; error= 1;
switch (err)
{
case WSREP_TRX_SIZE_EXCEEDED:
/* give user size exeeded erro from wsrep_api.h */
my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_SIZE_EXCEEDED);
break;
case WSREP_TRX_CERT_FAIL:
case WSREP_TRX_ERROR:
/* avoid sending error, if we need to replay */ /* avoid sending error, if we need to replay */
if (thd->wsrep_conflict_state!= MUST_REPLAY) if (thd->wsrep_conflict_state!= MUST_REPLAY)
{ {
my_error(ER_LOCK_DEADLOCK, MYF(0), err); my_error(ER_LOCK_DEADLOCK, MYF(0), err);
} }
} }
}
else else
/* not wsrep hton, bail to native mysql behavior */ /* not wsrep hton, bail to native mysql behavior */
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
@ -5699,7 +5725,9 @@ static bool check_table_binlog_row_based(THD *thd, TABLE *table)
table->s->cached_row_logging_check && table->s->cached_row_logging_check &&
(thd->variables.option_bits & OPTION_BIN_LOG) && (thd->variables.option_bits & OPTION_BIN_LOG) &&
#ifdef WITH_WSREP #ifdef WITH_WSREP
((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open())); /* applier and replayer should not binlog */
((WSREP_EMULATE_BINLOG(thd) && (thd->wsrep_exec_mode != REPL_RECV)) ||
mysql_bin_log.is_open()));
#else #else
mysql_bin_log.is_open()); mysql_bin_log.is_open());
#endif #endif
@ -5802,6 +5830,17 @@ static int binlog_log_row(TABLE* table,
bool error= 0; bool error= 0;
THD *const thd= table->in_use; THD *const thd= table->in_use;
#ifdef WITH_WSREP
/* only InnoDB tables will be replicated through binlog emulation */
if (WSREP_EMULATE_BINLOG(thd) &&
table->file->ht->db_type != DB_TYPE_INNODB &&
!(table->file->ht->db_type == DB_TYPE_PARTITION_DB &&
(((ha_partition*)(table->file))->wsrep_db_type() == DB_TYPE_INNODB)))
// !strcmp(table->file->table_type(), "InnoDB"))
{
return 0;
}
#endif /* WITH_WSREP */
if (check_table_binlog_row_based(thd, table)) if (check_table_binlog_row_based(thd, table))
{ {
MY_BITMAP cols; MY_BITMAP cols;

View File

@ -3096,6 +3096,11 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
{ {
time_t end_time; time_t end_time;
#ifdef WITH_WSREP #ifdef WITH_WSREP
/*
If Query_log_event will contain non trans keyword (not BEGIN, COMMIT,
SAVEPOINT or ROLLBACK) we disable PA for this transaction.
*/
if (!is_trans_keyword())
thd->wsrep_PA_safe= false; thd->wsrep_PA_safe= false;
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
memset(&user, 0, sizeof(user)); memset(&user, 0, sizeof(user));

View File

@ -22,6 +22,7 @@
#include <mysql/plugin.h> #include <mysql/plugin.h>
#include <mysql/service_thd_wait.h> #include <mysql/service_thd_wait.h>
#include <mysql/psi/mysql_stage.h> #include <mysql/psi/mysql_stage.h>
#ifdef WITH_WSREP #ifdef WITH_WSREP
#include "wsrep_mysqld.h" #include "wsrep_mysqld.h"
#include "wsrep_thd.h" #include "wsrep_thd.h"
@ -34,7 +35,6 @@ extern bool
wsrep_grant_mdl_exception(MDL_context *requestor_ctx, wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
MDL_ticket *ticket); MDL_ticket *ticket);
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
#ifdef HAVE_PSI_INTERFACE #ifdef HAVE_PSI_INTERFACE
static PSI_mutex_key key_MDL_map_mutex; static PSI_mutex_key key_MDL_map_mutex;
static PSI_mutex_key key_MDL_wait_LOCK_wait_status; static PSI_mutex_key key_MDL_wait_LOCK_wait_status;
@ -1480,7 +1480,7 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
DBUG_ASSERT(ticket->get_lock()); DBUG_ASSERT(ticket->get_lock());
#ifdef WITH_WSREP #ifdef WITH_WSREP
if ((this == &(ticket->get_lock()->m_waiting)) && if ((this == &(ticket->get_lock()->m_waiting)) &&
wsrep_thd_is_brute_force((void *)(ticket->get_ctx()->wsrep_get_thd()))) wsrep_thd_is_BF((void *)(ticket->get_ctx()->wsrep_get_thd()), false))
{ {
Ticket_iterator itw(ticket->get_lock()->m_waiting); Ticket_iterator itw(ticket->get_lock()->m_waiting);
Ticket_iterator itg(ticket->get_lock()->m_granted); Ticket_iterator itg(ticket->get_lock()->m_granted);
@ -1491,7 +1491,7 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
while ((waiting= itw++) && !added) while ((waiting= itw++) && !added)
{ {
if (!wsrep_thd_is_brute_force((void *)(waiting->get_ctx()->wsrep_get_thd()))) if (!wsrep_thd_is_BF((void *)(waiting->get_ctx()->wsrep_get_thd()), true))
{ {
WSREP_DEBUG("MDL add_ticket inserted before: %lu %s", WSREP_DEBUG("MDL add_ticket inserted before: %lu %s",
wsrep_thd_thread_id(waiting->get_ctx()->wsrep_get_thd()), wsrep_thd_thread_id(waiting->get_ctx()->wsrep_get_thd()),
@ -1892,7 +1892,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
ticket->is_incompatible_when_granted(type_arg)) ticket->is_incompatible_when_granted(type_arg))
#ifdef WITH_WSREP #ifdef WITH_WSREP
{ {
if (wsrep_thd_is_brute_force((void *)(requestor_ctx->wsrep_get_thd())) && if (wsrep_thd_is_BF((void *)(requestor_ctx->wsrep_get_thd()),false) &&
key.mdl_namespace() == MDL_key::GLOBAL) key.mdl_namespace() == MDL_key::GLOBAL)
{ {
WSREP_DEBUG("global lock granted for BF: %lu %s", WSREP_DEBUG("global lock granted for BF: %lu %s",
@ -1933,7 +1933,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
#ifdef WITH_WSREP #ifdef WITH_WSREP
else else
{ {
if (wsrep_thd_is_brute_force((void *)(requestor_ctx->wsrep_get_thd())) && if (wsrep_thd_is_BF((void *)(requestor_ctx->wsrep_get_thd()), false) &&
key.mdl_namespace() == MDL_key::GLOBAL) key.mdl_namespace() == MDL_key::GLOBAL)
{ {
WSREP_DEBUG("global lock granted for BF (waiting queue): %lu %s", WSREP_DEBUG("global lock granted for BF (waiting queue): %lu %s",

View File

@ -76,7 +76,6 @@
#include "wsrep_var.h" #include "wsrep_var.h"
#include "wsrep_thd.h" #include "wsrep_thd.h"
#include "wsrep_sst.h" #include "wsrep_sst.h"
ulong wsrep_running_threads = 0; // # of currently running wsrep threads
#endif #endif
#include "sql_callback.h" #include "sql_callback.h"
#include "threadpool.h" #include "threadpool.h"
@ -2747,11 +2746,7 @@ static void network_init(void)
@note @note
For the connection that is doing shutdown, this is called twice For the connection that is doing shutdown, this is called twice
*/ */
#ifdef WITH_WSREP
void close_connection(THD *thd, uint sql_errno, bool lock)
#else
void close_connection(THD *thd, uint sql_errno) void close_connection(THD *thd, uint sql_errno)
#endif
{ {
DBUG_ENTER("close_connection"); DBUG_ENTER("close_connection");
@ -2984,7 +2979,11 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache)
unlink_thd(thd); unlink_thd(thd);
/* Mark that current_thd is not valid anymore */ /* Mark that current_thd is not valid anymore */
set_current_thd(0); set_current_thd(0);
#ifdef WITH_WSREP
if (put_in_cache && cache_thread() && !thd->wsrep_applier)
#else
if (put_in_cache && cache_thread()) if (put_in_cache && cache_thread())
#endif /* WITH_WSREP */
DBUG_RETURN(0); // Thread is reused DBUG_RETURN(0); // Thread is reused
/* /*
@ -3428,10 +3427,21 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused)))
should not be any other mysql_cond_signal() calls. should not be any other mysql_cond_signal() calls.
*/ */
mysql_mutex_lock(&LOCK_thread_count); mysql_mutex_lock(&LOCK_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
mysql_cond_broadcast(&COND_thread_count); mysql_cond_broadcast(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
/*
Waiting for until mysqld_server_started != 0
to ensure that all server components has been successfully
initialized. This step is mandatory since signal processing
could be done safely only when all server components
has been initialized.
*/
mysql_mutex_lock(&LOCK_server_started);
while (!mysqld_server_started)
mysql_cond_wait(&COND_server_started, &LOCK_server_started);
mysql_mutex_unlock(&LOCK_server_started);
(void) pthread_sigmask(SIG_BLOCK,&set,NULL);
for (;;) for (;;)
{ {
int error; // Used when debugging int error; // Used when debugging
@ -4879,42 +4889,8 @@ will be ignored as the --log-bin option is not defined.");
} }
#endif #endif
#ifdef WITH_WSREP /* WSREP BEFORE SE */
if (!wsrep_recovery)
{
if (opt_bootstrap) // bootsrap option given - disable wsrep functionality
{
wsrep_provider_init(WSREP_NONE);
if (wsrep_init()) unireg_abort(1);
}
else // full wsrep initialization
{
// add basedir/bin to PATH to resolve wsrep script names
char* const tmp_path((char*)alloca(strlen(mysql_home) +
strlen("/bin") + 1));
if (tmp_path)
{
strcpy(tmp_path, mysql_home);
strcat(tmp_path, "/bin");
wsrep_prepend_PATH(tmp_path);
}
else
{
WSREP_ERROR("Could not append %s/bin to PATH", mysql_home);
}
DBUG_ASSERT(!opt_bin_log || opt_bin_logname); DBUG_ASSERT(!opt_bin_log || opt_bin_logname);
if (wsrep_before_SE())
{
#ifndef EMBEDDED_LIBRARY
set_ports(); // this is also called in network_init() later but we need
// to know mysqld_port now - lp:1071882
#endif /* !EMBEDDED_LIBRARY */
wsrep_init_startup(true);
}
}
}
#endif /* WITH_WSREP */
if (opt_bin_log) if (opt_bin_log)
{ {
/* Reports an error and aborts, if the --log-bin's path /* Reports an error and aborts, if the --log-bin's path
@ -4962,10 +4938,67 @@ a file name for --log-bin-index option", opt_binlog_index_name);
{ {
opt_bin_logname= my_once_strdup(buf, MYF(MY_WME)); opt_bin_logname= my_once_strdup(buf, MYF(MY_WME));
} }
#ifdef WITH_WSREP /* WSREP BEFORE SE */
/*
Wsrep initialization must happen at this point, because:
- opt_bin_logname must be known when starting replication
since SST may need it
- SST may modify binlog index file, so it must be opened
after SST has happened
*/
}
if (!wsrep_recovery)
{
if (opt_bootstrap) // bootsrap option given - disable wsrep functionality
{
wsrep_provider_init(WSREP_NONE);
if (wsrep_init()) unireg_abort(1);
}
else // full wsrep initialization
{
// add basedir/bin to PATH to resolve wsrep script names
char* const tmp_path((char*)alloca(strlen(mysql_home) +
strlen("/bin") + 1));
if (tmp_path)
{
strcpy(tmp_path, mysql_home);
strcat(tmp_path, "/bin");
wsrep_prepend_PATH(tmp_path);
}
else
{
WSREP_ERROR("Could not append %s/bin to PATH", mysql_home);
}
if (wsrep_before_SE())
{
set_ports(); // this is also called in network_init() later but we need
// to know mysqld_port now - lp:1071882
wsrep_init_startup(true);
}
}
}
if (opt_bin_log)
{
/*
Variable ln is not defined at this scope. We use opt_bin_logname instead.
It should be the same as ln since
- mysql_bin_log.generate_name() returns first argument if new log name
is not generated
- if new log name is generated, return value is assigned to ln and copied
to opt_bin_logname above
*/
if (mysql_bin_log.open_index_file(opt_binlog_index_name, opt_bin_logname,
TRUE))
{
unireg_abort(1);
}
#else
if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln, TRUE)) if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln, TRUE))
{ {
unireg_abort(1); unireg_abort(1);
} }
#endif /* WITH_WSREP */
} }
/* call ha_init_key_cache() on all key caches to init them */ /* call ha_init_key_cache() on all key caches to init them */
@ -5262,7 +5295,7 @@ pthread_handler_t start_wsrep_THD(void *arg)
thd->thr_create_utime= microsecond_interval_timer(); thd->thr_create_utime= microsecond_interval_timer();
if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0)) if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0))
{ {
close_connection(thd, ER_OUT_OF_RESOURCES, 1); close_connection(thd, ER_OUT_OF_RESOURCES);
statistic_increment(aborted_connects,&LOCK_status); statistic_increment(aborted_connects,&LOCK_status);
MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
@ -5285,7 +5318,7 @@ pthread_handler_t start_wsrep_THD(void *arg)
thd->thread_stack= (char*) &thd; thd->thread_stack= (char*) &thd;
if (thd->store_globals()) if (thd->store_globals())
{ {
close_connection(thd, ER_OUT_OF_RESOURCES, 1); close_connection(thd, ER_OUT_OF_RESOURCES);
statistic_increment(aborted_connects,&LOCK_status); statistic_increment(aborted_connects,&LOCK_status);
MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
delete thd; delete thd;
@ -5307,19 +5340,9 @@ pthread_handler_t start_wsrep_THD(void *arg)
++connection_count; ++connection_count;
mysql_mutex_unlock(&LOCK_connection_count); mysql_mutex_unlock(&LOCK_connection_count);
mysql_mutex_lock(&LOCK_thread_count);
wsrep_running_threads++;
mysql_cond_signal(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
processor(thd); processor(thd);
close_connection(thd, 0, 1); close_connection(thd, 0);
mysql_mutex_lock(&LOCK_thread_count);
wsrep_running_threads--;
mysql_cond_signal(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
// Note: We can't call THD destructor without crashing // Note: We can't call THD destructor without crashing
// if plugins have not been initialized. However, in most of the // if plugins have not been initialized. However, in most of the
@ -5337,6 +5360,7 @@ pthread_handler_t start_wsrep_THD(void *arg)
// at server shutdown // at server shutdown
} }
my_thread_end();
if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION)
{ {
mysql_mutex_lock(&LOCK_thread_count); mysql_mutex_lock(&LOCK_thread_count);
@ -5550,7 +5574,7 @@ void wsrep_close_client_connections(my_bool wait_to_end)
!is_replaying_connection(tmp)) !is_replaying_connection(tmp))
{ {
WSREP_INFO("killing local connection: %ld",tmp->thread_id); WSREP_INFO("killing local connection: %ld",tmp->thread_id);
close_connection(tmp,0,0); close_connection(tmp,0);
} }
#endif #endif
} }
@ -6644,11 +6668,7 @@ void create_thread_to_handle_connection(THD *thd)
my_snprintf(error_message_buff, sizeof(error_message_buff), my_snprintf(error_message_buff, sizeof(error_message_buff),
ER_THD(thd, ER_CANT_CREATE_THREAD), error); ER_THD(thd, ER_CANT_CREATE_THREAD), error);
net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL); net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL);
#ifdef WITH_WSREP
close_connection(thd, ER_OUT_OF_RESOURCES ,0);
#else
close_connection(thd, ER_OUT_OF_RESOURCES); close_connection(thd, ER_OUT_OF_RESOURCES);
#endif /* WITH_WSREP */
mysql_mutex_lock(&LOCK_thread_count); mysql_mutex_lock(&LOCK_thread_count);
thd->unlink(); thd->unlink();
@ -6694,11 +6714,7 @@ static void create_new_thread(THD *thd)
mysql_mutex_unlock(&LOCK_connection_count); mysql_mutex_unlock(&LOCK_connection_count);
DBUG_PRINT("error",("Too many connections")); DBUG_PRINT("error",("Too many connections"));
#ifdef WITH_WSREP
close_connection(thd, ER_CON_COUNT_ERROR, 1);
#else
close_connection(thd, ER_CON_COUNT_ERROR); close_connection(thd, ER_CON_COUNT_ERROR);
#endif /* WITH_WSREP */
statistic_increment(denied_connections, &LOCK_status); statistic_increment(denied_connections, &LOCK_status);
delete thd; delete thd;
statistic_increment(connection_errors_max_connection, &LOCK_status); statistic_increment(connection_errors_max_connection, &LOCK_status);
@ -7109,11 +7125,7 @@ pthread_handler_t handle_connections_namedpipes(void *arg)
if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) || if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) ||
my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC))) my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC)))
{ {
#ifdef WITH_WSREP
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
#else
close_connection(thd, ER_OUT_OF_RESOURCES); close_connection(thd, ER_OUT_OF_RESOURCES);
#endif
delete thd; delete thd;
set_current_thd(0); set_current_thd(0);
continue; continue;
@ -7311,11 +7323,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg)
event_conn_closed)) || event_conn_closed)) ||
my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC))) my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC)))
{ {
#ifdef WITH_WSREP
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
#else
close_connection(thd, ER_OUT_OF_RESOURCES); close_connection(thd, ER_OUT_OF_RESOURCES);
#endif
errmsg= 0; errmsg= 0;
goto errorconn; goto errorconn;
} }

View File

@ -55,11 +55,7 @@ typedef Bitmap<((MAX_INDEXES+7)/8*8)> key_map; /* Used for finding keys */
some places */ some places */
/* Function prototypes */ /* Function prototypes */
void kill_mysql(void); void kill_mysql(void);
#ifdef WITH_WSREP
void close_connection(THD *thd, uint sql_errno= 0, bool lock=1);
#else
void close_connection(THD *thd, uint sql_errno= 0); void close_connection(THD *thd, uint sql_errno= 0);
#endif /* WITH_WSREP */
void handle_connection_in_main_thread(THD *thd); void handle_connection_in_main_thread(THD *thd);
void create_thread_to_handle_connection(THD *thd); void create_thread_to_handle_connection(THD *thd);
void delete_running_thd(THD *thd); void delete_running_thd(THD *thd);

View File

@ -4651,6 +4651,22 @@ err_during_init:
DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5);); DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5););
mysql_mutex_unlock(&rli->run_lock); // tell the world we are done mysql_mutex_unlock(&rli->run_lock); // tell the world we are done
#ifdef WITH_WSREP
/* if slave stopped due to node going non primary, we set global flag to
trigger automatic restart of slave when node joins back to cluster
*/
if (WSREP_ON && !wsrep_ready)
{
WSREP_INFO("Slave thread stopped because node dropped from cluster");
if (wsrep_restart_slave)
{
WSREP_INFO("wsrep_restart_slave was set and therefore slave will be "
"automatically restarted when node joins back to cluster");
wsrep_restart_slave_activated= TRUE;
}
}
#endif /* WITH_WSREP */
DBUG_LEAVE; // Must match DBUG_ENTER() DBUG_LEAVE; // Must match DBUG_ENTER()
my_thread_end(); my_thread_end();
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL

View File

@ -8945,7 +8945,7 @@ bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use,
#ifdef WITH_WSREP #ifdef WITH_WSREP
{ {
signalled|= mysql_lock_abort_for_thread(thd, thd_table); signalled|= mysql_lock_abort_for_thread(thd, thd_table);
if (thd && WSREP(thd) && wsrep_thd_is_brute_force((void *)thd)) if (thd && WSREP(thd) && wsrep_thd_is_BF((void *)thd, true))
{ {
WSREP_DEBUG("remove_table_from_cache: %llu", WSREP_DEBUG("remove_table_from_cache: %llu",
(unsigned long long) thd->real_id); (unsigned long long) thd->real_id);

View File

@ -66,6 +66,7 @@
#include "lock.h" #include "lock.h"
#ifdef WITH_WSREP #ifdef WITH_WSREP
#include "wsrep_mysqld.h" #include "wsrep_mysqld.h"
#include "wsrep_thd.h"
#endif #endif
#include "sql_connect.h" #include "sql_connect.h"
@ -958,6 +959,10 @@ extern "C" void wsrep_thd_awake(THD *thd, my_bool signal)
mysql_mutex_unlock(&LOCK_wsrep_replaying); mysql_mutex_unlock(&LOCK_wsrep_replaying);
} }
} }
extern "C" int wsrep_thd_retry_counter(THD *thd)
{
return(thd->wsrep_retry_counter);
}
extern int extern int
wsrep_trx_order_before(void *thd1, void *thd2) wsrep_trx_order_before(void *thd1, void *thd2)
@ -2129,7 +2134,19 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use,
(e.g. see partitioning code). (e.g. see partitioning code).
*/ */
if (!thd_table->needs_reopen()) if (!thd_table->needs_reopen())
#ifdef WITH_WSREP
{
signalled|= mysql_lock_abort_for_thread(this, thd_table); signalled|= mysql_lock_abort_for_thread(this, thd_table);
if (this && WSREP(this) && wsrep_thd_is_BF((void *)this, FALSE))
{
WSREP_DEBUG("remove_table_from_cache: %llu",
(unsigned long long) this->real_id);
wsrep_abort_thd((void *)this, (void *)in_use, FALSE);
}
}
#else
signalled|= mysql_lock_abort_for_thread(this, thd_table);
#endif
} }
mysql_mutex_unlock(&in_use->LOCK_thd_data); mysql_mutex_unlock(&in_use->LOCK_thd_data);
} }

View File

@ -1102,11 +1102,7 @@ bool setup_connection_thread_globals(THD *thd)
{ {
if (thd->store_globals()) if (thd->store_globals())
{ {
#ifdef WITH_WSREP
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
#else
close_connection(thd, ER_OUT_OF_RESOURCES); close_connection(thd, ER_OUT_OF_RESOURCES);
#endif
statistic_increment(aborted_connects,&LOCK_status); statistic_increment(aborted_connects,&LOCK_status);
MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0)); MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0));
return 1; // Error return 1; // Error
@ -1351,11 +1347,7 @@ void do_handle_one_connection(THD *thd_arg)
if (MYSQL_CALLBACK_ELSE(thd->scheduler, init_new_connection_thread, (), 0)) if (MYSQL_CALLBACK_ELSE(thd->scheduler, init_new_connection_thread, (), 0))
{ {
#ifdef WITH_WSREP
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
#else
close_connection(thd, ER_OUT_OF_RESOURCES); close_connection(thd, ER_OUT_OF_RESOURCES);
#endif
statistic_increment(aborted_connects,&LOCK_status); statistic_increment(aborted_connects,&LOCK_status);
MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0)); MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0));
return; return;
@ -1415,11 +1407,7 @@ void do_handle_one_connection(THD *thd_arg)
} }
#endif #endif
end_thread: end_thread:
#ifdef WITH_WSREP
close_connection(thd, 0, 1);
#else
close_connection(thd); close_connection(thd);
#endif
if (thd->userstat_running) if (thd->userstat_running)
update_global_user_stats(thd, create_user, time(NULL)); update_global_user_stats(thd, create_user, time(NULL));

View File

@ -820,11 +820,7 @@ void do_handle_bootstrap(THD *thd)
if (my_thread_init() || thd->store_globals()) if (my_thread_init() || thd->store_globals())
{ {
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
#ifdef WITH_WSREP
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
#else
close_connection(thd, ER_OUT_OF_RESOURCES); close_connection(thd, ER_OUT_OF_RESOURCES);
#endif /* WITH_WSREP */
#endif #endif
thd->fatal_error(); thd->fatal_error();
goto end; goto end;
@ -2736,7 +2732,9 @@ mysql_execute_command(THD *thd)
if (trans_commit_implicit(thd)) if (trans_commit_implicit(thd))
{ {
thd->mdl_context.release_transactional_locks(); thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("implicit commit failed, MDL released: %lu", thd->thread_id); WSREP_DEBUG("implicit commit failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error; goto error;
} }
/* Release metadata locks acquired in this transaction. */ /* Release metadata locks acquired in this transaction. */
@ -4758,7 +4756,9 @@ end_with_restore_list:
if (trans_begin(thd, lex->start_transaction_opt)) if (trans_begin(thd, lex->start_transaction_opt))
{ {
thd->mdl_context.release_transactional_locks(); thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("BEGIN failed, MDL released: %lu", thd->thread_id); WSREP_DEBUG("BEGIN failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error; goto error;
} }
my_ok(thd); my_ok(thd);
@ -4776,7 +4776,9 @@ end_with_restore_list:
if (trans_commit(thd)) if (trans_commit(thd))
{ {
thd->mdl_context.release_transactional_locks(); thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("COMMIT failed, MDL released: %lu", thd->thread_id); WSREP_DEBUG("COMMIT failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error; goto error;
} }
thd->mdl_context.release_transactional_locks(); thd->mdl_context.release_transactional_locks();
@ -4828,7 +4830,9 @@ end_with_restore_list:
if (trans_rollback(thd)) if (trans_rollback(thd))
{ {
thd->mdl_context.release_transactional_locks(); thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("rollback failed, MDL released: %lu", thd->thread_id); WSREP_DEBUG("rollback failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error; goto error;
} }
thd->mdl_context.release_transactional_locks(); thd->mdl_context.release_transactional_locks();
@ -5375,7 +5379,9 @@ create_sp_error:
if (trans_xa_commit(thd)) if (trans_xa_commit(thd))
{ {
thd->mdl_context.release_transactional_locks(); thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("XA commit failed, MDL released: %lu", thd->thread_id); WSREP_DEBUG("XA commit failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error; goto error;
} }
thd->mdl_context.release_transactional_locks(); thd->mdl_context.release_transactional_locks();
@ -5391,7 +5397,9 @@ create_sp_error:
if (trans_xa_rollback(thd)) if (trans_xa_rollback(thd))
{ {
thd->mdl_context.release_transactional_locks(); thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("XA rollback failed, MDL released: %lu", thd->thread_id); WSREP_DEBUG("XA rollback failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error; goto error;
} }
thd->mdl_context.release_transactional_locks(); thd->mdl_context.release_transactional_locks();
@ -7930,7 +7938,7 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (((thd->security_ctx->master_access & SUPER_ACL) || if (((thd->security_ctx->master_access & SUPER_ACL) ||
thd->security_ctx->user_matches(tmp->security_ctx)) && thd->security_ctx->user_matches(tmp->security_ctx)) &&
!wsrep_thd_is_brute_force((void *)tmp)) !wsrep_thd_is_BF((void *)tmp, true))
#else #else
if ((thd->security_ctx->master_access & SUPER_ACL) || if ((thd->security_ctx->master_access & SUPER_ACL) ||
thd->security_ctx->user_matches(tmp->security_ctx)) thd->security_ctx->user_matches(tmp->security_ctx))

View File

@ -763,6 +763,19 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd)
if (check_one_table_access(thd, DROP_ACL, first_table)) if (check_one_table_access(thd, DROP_ACL, first_table))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
#ifdef WITH_WSREP
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
if ((!thd->is_current_stmt_binlog_format_row() ||
!find_temporary_table(thd, first_table)) &&
wsrep_to_isolation_begin(
thd, first_table->db, first_table->table_name, NULL)
)
{
WSREP_WARN("ALTER TABLE isolation failure");
DBUG_RETURN(TRUE);
}
#endif /* WITH_WSREP */
if (open_tables(thd, &first_table, &table_counter, 0)) if (open_tables(thd, &first_table, &table_counter, 0))
DBUG_RETURN(true); DBUG_RETURN(true);

View File

@ -455,6 +455,12 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
{ {
bool hton_can_recreate; bool hton_can_recreate;
#ifdef WITH_WSREP
if (WSREP(thd) && wsrep_to_isolation_begin(thd,
table_ref->db,
table_ref->table_name, NULL))
DBUG_RETURN(TRUE);
#endif /* WITH_WSREP */
if (lock_table(thd, table_ref, &hton_can_recreate)) if (lock_table(thd, table_ref, &hton_can_recreate))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
@ -531,12 +537,6 @@ bool Sql_cmd_truncate_table::execute(THD *thd)
if (check_one_table_access(thd, DROP_ACL, first_table)) if (check_one_table_access(thd, DROP_ACL, first_table))
DBUG_RETURN(res); DBUG_RETURN(res);
#ifdef WITH_WSREP
if (WSREP(thd) && wsrep_to_isolation_begin(thd,
first_table->db,
first_table->table_name, NULL))
DBUG_RETURN(TRUE);
#endif /* WITH_WSREP */
if (! (res= truncate_table(thd, first_table))) if (! (res= truncate_table(thd, first_table)))
my_ok(thd); my_ok(thd);
DBUG_RETURN(res); DBUG_RETURN(res);

View File

@ -3314,7 +3314,9 @@ static bool fix_autocommit(sys_var *self, THD *thd, enum_var_type type)
{ {
thd->variables.option_bits&= ~OPTION_AUTOCOMMIT; thd->variables.option_bits&= ~OPTION_AUTOCOMMIT;
thd->mdl_context.release_transactional_locks(); thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("autocommit, MDL TRX lock released: %lu", thd->thread_id); WSREP_DEBUG("autocommit, MDL TRX lock released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
return true; return true;
} }
/* /*
@ -4646,6 +4648,10 @@ static Sys_var_mybool Sys_wsrep_load_data_splitting(
"transaction after every 10K rows inserted", "transaction after every 10K rows inserted",
GLOBAL_VAR(wsrep_load_data_splitting), GLOBAL_VAR(wsrep_load_data_splitting),
CMD_LINE(OPT_ARG), DEFAULT(TRUE)); CMD_LINE(OPT_ARG), DEFAULT(TRUE));
static Sys_var_mybool Sys_wsrep_restart_slave(
"wsrep_restart_slave", "Should MySQL slave be restarted automatically, when node joins back to cluster",
GLOBAL_VAR(wsrep_restart_slave), CMD_LINE(OPT_ARG), DEFAULT(FALSE));
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
static bool fix_host_cache_size(sys_var *, THD *, enum_var_type) static bool fix_host_cache_size(sys_var *, THD *, enum_var_type)

View File

@ -55,8 +55,8 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len)
wsrep_max_ws_size, total_length); wsrep_max_ws_size, total_length);
goto error; goto error;
} }
uchar* tmp = (uchar *)my_realloc(*buf, total_length,
MYF(MY_ALLOW_ZERO_PTR)); uchar* tmp = (uchar *)my_realloc(*buf, total_length, MYF(0));
if (!tmp) if (!tmp)
{ {
WSREP_ERROR("could not (re)allocate buffer: %zu + %u", WSREP_ERROR("could not (re)allocate buffer: %zu + %u",
@ -72,7 +72,7 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len)
if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
{ {
WSREP_ERROR("failed to initialize io-cache"); WSREP_WARN("failed to initialize io-cache");
goto cleanup; goto cleanup;
} }
@ -166,19 +166,19 @@ static int wsrep_write_cache_once(wsrep_t* const wsrep,
{ {
WSREP_WARN("transaction size limit (%lu) exceeded: %zu", WSREP_WARN("transaction size limit (%lu) exceeded: %zu",
wsrep_max_ws_size, total_length); wsrep_max_ws_size, total_length);
err = WSREP_TRX_SIZE_EXCEEDED;
goto cleanup; goto cleanup;
} }
if (total_length > allocated) if (total_length > allocated)
{ {
size_t const new_size(heap_size(total_length)); size_t const new_size(heap_size(total_length));
uchar* tmp = (uchar *)my_realloc(heap_buf, new_size, uchar* tmp = (uchar *)my_realloc(heap_buf, new_size, MYF(0));
MYF(MY_ALLOW_ZERO_PTR));
if (!tmp) if (!tmp)
{ {
WSREP_ERROR("could not (re)allocate buffer: %zu + %u", WSREP_ERROR("could not (re)allocate buffer: %zu + %u",
allocated, length); allocated, length);
err = WSREP_SIZE_EXCEEDED; err = WSREP_TRX_SIZE_EXCEEDED;
goto cleanup; goto cleanup;
} }
@ -233,7 +233,7 @@ static int wsrep_write_cache_inc(wsrep_t* const wsrep,
if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0)) if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
{ {
WSREP_ERROR("failed to initialize io-cache"); WSREP_ERROR("failed to initialize io-cache");
return WSREP_TRX_ROLLBACK; return WSREP_TRX_ERROR;
} }
int err(WSREP_OK); int err(WSREP_OK);
@ -254,7 +254,7 @@ static int wsrep_write_cache_inc(wsrep_t* const wsrep,
{ {
WSREP_WARN("transaction size limit (%lu) exceeded: %zu", WSREP_WARN("transaction size limit (%lu) exceeded: %zu",
wsrep_max_ws_size, total_length); wsrep_max_ws_size, total_length);
err = WSREP_SIZE_EXCEEDED; err = WSREP_TRX_SIZE_EXCEEDED;
goto cleanup; goto cleanup;
} }
@ -349,3 +349,59 @@ int wsrep_binlog_savepoint_rollback(THD *thd, void *sv)
int rcode = binlog_hton->savepoint_rollback(binlog_hton, thd, sv); int rcode = binlog_hton->savepoint_rollback(binlog_hton, thd, sv);
return rcode; return rcode;
} }
void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache)
{
char filename[PATH_MAX]= {0};
int len= snprintf(filename, PATH_MAX, "%s/GRA_%ld_%lld.log",
wsrep_data_home_dir, thd->thread_id,
(long long)wsrep_thd_trx_seqno(thd));
size_t bytes_in_cache = 0;
// check path
if (len >= PATH_MAX)
{
WSREP_ERROR("RBR dump path too long: %d, skipping dump.", len);
return ;
}
// init cache
my_off_t const saved_pos(my_b_tell(cache));
if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
{
WSREP_ERROR("failed to initialize io-cache");
return ;
}
// open file
FILE* of = fopen(filename, "wb");
if (!of)
{
WSREP_ERROR("Failed to open file '%s': %d (%s)",
filename, errno, strerror(errno));
goto cleanup;
}
// ready to write
bytes_in_cache= my_b_bytes_in_cache(cache);
if (unlikely(bytes_in_cache == 0)) bytes_in_cache = my_b_fill(cache);
if (likely(bytes_in_cache > 0)) do
{
if (my_fwrite(of, cache->read_pos, bytes_in_cache,
MYF(MY_WME | MY_NABP)) == (size_t) -1)
{
WSREP_ERROR("Failed to write file '%s'", filename);
goto cleanup;
}
cache->read_pos= cache->read_end;
} while ((cache->file >= 0) && (bytes_in_cache= my_b_fill(cache)));
if(cache->error == -1)
{
WSREP_ERROR("RBR inconsistent");
goto cleanup;
}
cleanup:
// init back
if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
{
WSREP_ERROR("failed to reinitialize io-cache");
}
// close file
if (of) fclose(of);
}

View File

@ -50,4 +50,7 @@ int wsrep_binlog_close_connection(THD* thd);
int wsrep_binlog_savepoint_set(THD *thd, void *sv); int wsrep_binlog_savepoint_set(THD *thd, void *sv);
int wsrep_binlog_savepoint_rollback(THD *thd, void *sv); int wsrep_binlog_savepoint_rollback(THD *thd, void *sv);
/* Dump replication buffer to disk without intermediate buffer */
void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache);
#endif /* WSREP_BINLOG_H */ #endif /* WSREP_BINLOG_H */

View File

@ -303,19 +303,6 @@ check_opts (int const argc, const char* const argv[], struct opt opts[])
} }
} }
long long query_cache_size, query_cache_type;
if ((err = get_long_long (opts[QUERY_CACHE_SIZE], &query_cache_size, 10)))
return err;
if ((err = get_long_long (opts[QUERY_CACHE_TYPE], &query_cache_type, 10)))
return err;
if (0 != query_cache_size && 0 != query_cache_type)
{
WSREP_ERROR ("Query cache is not supported (size=%lld type=%lld)",
query_cache_size, query_cache_type);
rcode = EINVAL;
}
bool locked_in_memory; bool locked_in_memory;
err = get_bool (opts[LOCKED_IN_MEMORY], &locked_in_memory); err = get_bool (opts[LOCKED_IN_MEMORY], &locked_in_memory);
if (err) { WSREP_ERROR("get_bool error: %s", strerror(err)); return err; } if (err) { WSREP_ERROR("get_bool error: %s", strerror(err)); return err; }

View File

@ -134,7 +134,7 @@ wsrep_close_connection(handlerton* hton, THD* thd)
- certification test or an equivalent. As a result, - certification test or an equivalent. As a result,
the current transaction just rolls back the current transaction just rolls back
Error codes: Error codes:
WSREP_TRX_ROLLBACK, WSREP_TRX_ERROR WSREP_TRX_CERT_FAIL, WSREP_TRX_SIZE_EXCEEDED, WSREP_TRX_ERROR
- a post-certification failure makes this server unable to - a post-certification failure makes this server unable to
commit its own WS and therefore the server must abort commit its own WS and therefore the server must abort
*/ */
@ -155,14 +155,7 @@ static int wsrep_prepare(handlerton *hton, THD *thd, bool all)
!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
(thd->variables.wsrep_on && !wsrep_trans_cache_is_empty(thd))) (thd->variables.wsrep_on && !wsrep_trans_cache_is_empty(thd)))
{ {
switch (wsrep_run_wsrep_commit(thd, hton, all)) DBUG_RETURN (wsrep_run_wsrep_commit(thd, hton, all));
{
case WSREP_TRX_OK:
break;
case WSREP_TRX_ROLLBACK:
case WSREP_TRX_ERROR:
DBUG_RETURN(1);
}
} }
DBUG_RETURN(0); DBUG_RETURN(0);
} }
@ -330,7 +323,7 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all)
WSREP_INFO("innobase_commit, abort %s", WSREP_INFO("innobase_commit, abort %s",
(thd->query()) ? thd->query() : "void"); (thd->query()) ? thd->query() : "void");
} }
DBUG_RETURN(WSREP_TRX_ROLLBACK); DBUG_RETURN(WSREP_TRX_CERT_FAIL);
} }
mysql_mutex_lock(&LOCK_wsrep_replaying); mysql_mutex_lock(&LOCK_wsrep_replaying);
@ -381,7 +374,7 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all)
mysql_mutex_unlock(&thd->LOCK_wsrep_thd); mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
WSREP_DEBUG("innobase_commit abort after replaying wait %s", WSREP_DEBUG("innobase_commit abort after replaying wait %s",
(thd->query()) ? thd->query() : "void"); (thd->query()) ? thd->query() : "void");
DBUG_RETURN(WSREP_TRX_ROLLBACK); DBUG_RETURN(WSREP_TRX_CERT_FAIL);
} }
thd->wsrep_query_state = QUERY_COMMITTING; thd->wsrep_query_state = QUERY_COMMITTING;
@ -394,7 +387,7 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all)
rcode = wsrep_write_cache(wsrep, thd, cache, &data_len); rcode = wsrep_write_cache(wsrep, thd, cache, &data_len);
if (WSREP_OK != rcode) { if (WSREP_OK != rcode) {
WSREP_ERROR("rbr write fail, data_len: %zu, %d", data_len, rcode); WSREP_ERROR("rbr write fail, data_len: %zu, %d", data_len, rcode);
DBUG_RETURN(WSREP_TRX_ROLLBACK); DBUG_RETURN(WSREP_TRX_SIZE_EXCEEDED);
} }
} }
@ -517,7 +510,7 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all)
} }
mysql_mutex_unlock(&thd->LOCK_wsrep_thd); mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
DBUG_RETURN(WSREP_TRX_ROLLBACK); DBUG_RETURN(WSREP_TRX_CERT_FAIL);
case WSREP_CONN_FAIL: case WSREP_CONN_FAIL:
WSREP_ERROR("connection failure"); WSREP_ERROR("connection failure");

View File

@ -26,6 +26,7 @@
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include "log_event.h" #include "log_event.h"
#include <slave.h>
wsrep_t *wsrep = NULL; wsrep_t *wsrep = NULL;
my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface
@ -63,7 +64,10 @@ ulong wsrep_mysql_replication_bundle = 0;
my_bool wsrep_desync = 0; // desynchronize the node from the my_bool wsrep_desync = 0; // desynchronize the node from the
// cluster // cluster
my_bool wsrep_load_data_splitting = 1; // commit load data every 10K intervals my_bool wsrep_load_data_splitting = 1; // commit load data every 10K intervals
my_bool wsrep_restart_slave = 0; // should mysql slave thread be
// restarted, if node joins back
my_bool wsrep_restart_slave_activated = 0; // node has dropped, and slave
// restart will be needed
/* /*
* End configuration options * End configuration options
*/ */
@ -126,7 +130,7 @@ static void wsrep_log_cb(wsrep_log_level_t level, const char *msg) {
sql_print_error("WSREP: %s", msg); sql_print_error("WSREP: %s", msg);
break; break;
case WSREP_LOG_DEBUG: case WSREP_LOG_DEBUG:
if (wsrep_debug) sql_print_information ("[Debug] WSREP: %s", msg); sql_print_information ("[Debug] WSREP: %s", msg);
default: default:
break; break;
} }
@ -407,14 +411,32 @@ void wsrep_ready_wait ()
static void wsrep_synced_cb(void* app_ctx) static void wsrep_synced_cb(void* app_ctx)
{ {
WSREP_INFO("Synchronized with group, ready for connections"); WSREP_INFO("Synchronized with group, ready for connections");
bool signal_main= false;
if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort(); if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort();
if (!wsrep_ready) if (!wsrep_ready)
{ {
wsrep_ready= TRUE; wsrep_ready= TRUE;
mysql_cond_signal (&COND_wsrep_ready); mysql_cond_signal (&COND_wsrep_ready);
signal_main= true;
} }
local_status.set(WSREP_MEMBER_SYNCED); local_status.set(WSREP_MEMBER_SYNCED);
mysql_mutex_unlock (&LOCK_wsrep_ready); mysql_mutex_unlock (&LOCK_wsrep_ready);
if (signal_main)
{
wsrep_SE_init_grab();
// Signal mysqld init thread to continue
wsrep_sst_complete (&local_uuid, local_seqno, false);
// and wait for SE initialization
wsrep_SE_init_wait();
}
if (wsrep_restart_slave_activated)
{
WSREP_INFO("MySQL slave restart");
wsrep_restart_slave_activated= FALSE;
init_slave();
}
} }
static void wsrep_init_position() static void wsrep_init_position()
@ -495,7 +517,18 @@ int wsrep_init()
wsrep_ready_set(TRUE); wsrep_ready_set(TRUE);
wsrep_inited= 1; wsrep_inited= 1;
global_system_variables.wsrep_on = 0; global_system_variables.wsrep_on = 0;
return 0; wsrep_init_args args;
args.options = (wsrep_provider_options) ?
wsrep_provider_options : "";
rcode = wsrep->init(wsrep, &args);
if (rcode)
{
DBUG_PRINT("wsrep",("wsrep::init() failed: %d", rcode));
WSREP_ERROR("wsrep::init() failed: %d, must shutdown", rcode);
free(wsrep);
wsrep = NULL;
}
return rcode;
} }
else else
{ {
@ -651,7 +684,7 @@ void wsrep_init_startup (bool first)
{ {
if (wsrep_init()) unireg_abort(1); if (wsrep_init()) unireg_abort(1);
wsrep_thr_lock_init(wsrep_thd_is_brute_force, wsrep_abort_thd, wsrep_thr_lock_init(wsrep_thd_is_BF, wsrep_abort_thd,
wsrep_debug, wsrep_convert_LOCK_to_trx, wsrep_on); wsrep_debug, wsrep_convert_LOCK_to_trx, wsrep_on);
/* Skip replication start if no cluster address */ /* Skip replication start if no cluster address */
@ -1358,6 +1391,13 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_,
DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE); DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE);
DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED); DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED);
if (thd->global_read_lock.can_acquire_protection())
{
WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %lu",
thd->query(), thd->thread_id);
return -1;
}
if (wsrep_debug && thd->mdl_context.has_locks()) if (wsrep_debug && thd->mdl_context.has_locks())
{ {
WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu", WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu",

View File

@ -96,6 +96,8 @@ extern my_bool wsrep_replicate_myisam;
extern my_bool wsrep_log_conflicts; extern my_bool wsrep_log_conflicts;
extern ulong wsrep_mysql_replication_bundle; extern ulong wsrep_mysql_replication_bundle;
extern my_bool wsrep_load_data_splitting; extern my_bool wsrep_load_data_splitting;
extern my_bool wsrep_restart_slave;
extern my_bool wsrep_restart_slave_activated;
enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU }; enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU };
@ -158,6 +160,7 @@ extern "C" char * wsrep_thd_query(THD *thd);
extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd);
extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id);
extern "C" void wsrep_thd_awake(THD *thd, my_bool signal); extern "C" void wsrep_thd_awake(THD *thd, my_bool signal);
extern "C" int wsrep_thd_retry_counter(THD *thd);
extern void wsrep_close_client_connections(my_bool wait_to_end); extern void wsrep_close_client_connections(my_bool wait_to_end);
@ -232,8 +235,9 @@ extern void wsrep_ready_wait();
enum wsrep_trx_status { enum wsrep_trx_status {
WSREP_TRX_OK, WSREP_TRX_OK,
WSREP_TRX_ROLLBACK, WSREP_TRX_CERT_FAIL, /* certification failure, must abort */
WSREP_TRX_ERROR, WSREP_TRX_SIZE_EXCEEDED, /* trx size exceeded */
WSREP_TRX_ERROR, /* native mysql error */
}; };
extern enum wsrep_trx_status extern enum wsrep_trx_status
@ -274,6 +278,7 @@ extern rpl_sidno wsrep_sidno;
#endif /* GTID_SUPPORT */ #endif /* GTID_SUPPORT */
extern my_bool wsrep_preordered_opt; extern my_bool wsrep_preordered_opt;
#ifdef HAVE_PSI_INTERFACE
extern PSI_mutex_key key_LOCK_wsrep_ready; extern PSI_mutex_key key_LOCK_wsrep_ready;
extern PSI_mutex_key key_COND_wsrep_ready; extern PSI_mutex_key key_COND_wsrep_ready;
extern PSI_mutex_key key_LOCK_wsrep_sst; extern PSI_mutex_key key_LOCK_wsrep_sst;
@ -288,7 +293,7 @@ extern PSI_mutex_key key_LOCK_wsrep_replaying;
extern PSI_cond_key key_COND_wsrep_replaying; extern PSI_cond_key key_COND_wsrep_replaying;
extern PSI_mutex_key key_LOCK_wsrep_slave_threads; extern PSI_mutex_key key_LOCK_wsrep_slave_threads;
extern PSI_mutex_key key_LOCK_wsrep_desync; extern PSI_mutex_key key_LOCK_wsrep_desync;
#endif /* HAVE_PSI_INTERFACE */
struct TABLE_LIST; struct TABLE_LIST;
int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_,
const TABLE_LIST* table_list); const TABLE_LIST* table_list);

View File

@ -54,6 +54,8 @@ extern const char wsrep_defaults_file[];
#define WSREP_SST_MYSQLDUMP "mysqldump" #define WSREP_SST_MYSQLDUMP "mysqldump"
#define WSREP_SST_RSYNC "rsync" #define WSREP_SST_RSYNC "rsync"
#define WSREP_SST_SKIP "skip" #define WSREP_SST_SKIP "skip"
#define WSREP_SST_XTRABACKUP "xtrabackup"
#define WSREP_SST_XTRABACKUP_V2 "xtrabackup-v2"
#define WSREP_SST_DEFAULT WSREP_SST_RSYNC #define WSREP_SST_DEFAULT WSREP_SST_RSYNC
#define WSREP_SST_ADDRESS_AUTO "AUTO" #define WSREP_SST_ADDRESS_AUTO "AUTO"
#define WSREP_SST_AUTH_MASK "********" #define WSREP_SST_AUTH_MASK "********"
@ -231,7 +233,13 @@ void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid,
} }
else else
{ {
WSREP_WARN("Nobody is waiting for SST."); /* This can happen when called from wsrep_synced_cb().
At the moment there is no way to check there
if main thread is still waiting for signal,
so wsrep_sst_complete() is called from there
each time wsrep_ready changes from FALSE -> TRUE.
*/
WSREP_DEBUG("Nobody is waiting for SST.");
} }
mysql_mutex_unlock (&LOCK_wsrep_sst); mysql_mutex_unlock (&LOCK_wsrep_sst);
} }
@ -315,6 +323,33 @@ static char* my_fgets (char* buf, size_t buf_len, FILE* stream)
return ret; return ret;
} }
/*
Generate opt_binlog_opt_val for sst_donate_other(), sst_prepare_other().
Returns zero on success, negative error code otherwise.
String containing binlog name is stored in param ret if binlog is enabled
and GTID mode is on, otherwise empty string. Returned string should be
freed with my_free().
*/
static int generate_binlog_opt_val(char** ret)
{
DBUG_ASSERT(ret);
*ret= NULL;
if (opt_bin_log)
{
assert(opt_bin_logname);
*ret= strcmp(opt_bin_logname, "0") ?
my_strdup(opt_bin_logname, MYF(0)) : my_strdup("", MYF(0));
}
else
{
*ret= my_strdup("", MYF(0));
}
if (!*ret) return -ENOMEM;
return 0;
}
static void* sst_joiner_thread (void* a) static void* sst_joiner_thread (void* a)
{ {
sst_thread_arg* arg= (sst_thread_arg*) a; sst_thread_arg* arg= (sst_thread_arg*) a;
@ -409,10 +444,20 @@ static ssize_t sst_prepare_other (const char* method,
ssize_t cmd_len= 1024; ssize_t cmd_len= 1024;
char cmd_str[cmd_len]; char cmd_str[cmd_len];
const char* sst_dir= mysql_real_data_home; const char* sst_dir= mysql_real_data_home;
const char* binlog_opt= (opt_bin_logname ? (strcmp(opt_bin_logname, "0") ? WSREP_SST_OPT_BINLOG : "") : ""); const char* binlog_opt= "";
const char* binlog_opt_val= (opt_bin_logname ? (strcmp(opt_bin_logname, "0") ? opt_bin_logname : "") : ""); char* binlog_opt_val= NULL;
int ret= snprintf (cmd_str, cmd_len, int ret;
if ((ret= generate_binlog_opt_val(&binlog_opt_val)))
{
WSREP_ERROR("sst_prepare_other(): generate_binlog_opt_val() failed: %d",
ret);
return ret;
}
if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG;
ret= snprintf (cmd_str, cmd_len,
"wsrep_sst_%s " "wsrep_sst_%s "
WSREP_SST_OPT_ROLE" 'joiner' " WSREP_SST_OPT_ROLE" 'joiner' "
WSREP_SST_OPT_ADDR" '%s' " WSREP_SST_OPT_ADDR" '%s' "
@ -424,6 +469,7 @@ static ssize_t sst_prepare_other (const char* method,
method, addr_in, (sst_auth_real) ? sst_auth_real : "", method, addr_in, (sst_auth_real) ? sst_auth_real : "",
sst_dir, wsrep_defaults_file, (int)getpid(), sst_dir, wsrep_defaults_file, (int)getpid(),
binlog_opt, binlog_opt_val); binlog_opt, binlog_opt_val);
my_free(binlog_opt_val);
if (ret < 0 || ret >= cmd_len) if (ret < 0 || ret >= cmd_len)
{ {
@ -933,8 +979,9 @@ wait_signal:
else else
{ {
WSREP_ERROR("Failed to read from: %s", proc.cmd()); WSREP_ERROR("Failed to read from: %s", proc.cmd());
proc.wait();
} }
if (err && proc.error()) err= proc.error(); if (!err && proc.error()) err= proc.error();
} }
else else
{ {
@ -958,6 +1005,8 @@ wait_signal:
return NULL; return NULL;
} }
static int sst_donate_other (const char* method, static int sst_donate_other (const char* method,
const char* addr, const char* addr,
const char* uuid, const char* uuid,
@ -966,10 +1015,18 @@ static int sst_donate_other (const char* method,
{ {
ssize_t cmd_len = 4096; ssize_t cmd_len = 4096;
char cmd_str[cmd_len]; char cmd_str[cmd_len];
const char* binlog_opt= (opt_bin_logname ? (strcmp(opt_bin_logname, "0") ? WSREP_SST_OPT_BINLOG : "") : ""); const char* binlog_opt= "";
const char* binlog_opt_val= (opt_bin_logname ? (strcmp(opt_bin_logname, "0") ? opt_bin_logname : "") : ""); char* binlog_opt_val= NULL;
int ret= snprintf (cmd_str, cmd_len, int ret;
if ((ret= generate_binlog_opt_val(&binlog_opt_val)))
{
WSREP_ERROR("sst_donate_other(): generate_binlog_opt_val() failed: %d",ret);
return ret;
}
if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG;
ret= snprintf (cmd_str, cmd_len,
"wsrep_sst_%s " "wsrep_sst_%s "
WSREP_SST_OPT_ROLE" 'donor' " WSREP_SST_OPT_ROLE" 'donor' "
WSREP_SST_OPT_ADDR" '%s' " WSREP_SST_OPT_ADDR" '%s' "
@ -985,6 +1042,7 @@ static int sst_donate_other (const char* method,
binlog_opt, binlog_opt_val, binlog_opt, binlog_opt_val,
uuid, (long long) seqno, uuid, (long long) seqno,
bypass ? " "WSREP_SST_OPT_BYPASS : ""); bypass ? " "WSREP_SST_OPT_BYPASS : "");
my_free(binlog_opt_val);
if (ret < 0 || ret >= cmd_len) if (ret < 0 || ret >= cmd_len)
{ {
@ -1049,7 +1107,10 @@ void wsrep_SE_init_grab()
void wsrep_SE_init_wait() void wsrep_SE_init_wait()
{ {
while (SE_initialized == false)
{
mysql_cond_wait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init); mysql_cond_wait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init);
}
mysql_mutex_unlock (&LOCK_wsrep_sst_init); mysql_mutex_unlock (&LOCK_wsrep_sst_init);
} }

View File

@ -472,31 +472,53 @@ void wsrep_create_rollbacker()
} }
} }
extern "C" my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync)
int wsrep_thd_is_brute_force(void *thd_ptr)
{ {
/* my_bool status = FALSE;
Brute force: if (thd_ptr)
Appliers and replaying are running in REPL_RECV mode. TOI statements {
in TOTAL_ORDER mode. Locally committing transaction that has got THD* thd = (THD*)thd_ptr;
past wsrep->pre_commit() without error is running in LOCAL_COMMIT mode. if (sync) mysql_mutex_lock(&thd->LOCK_wsrep_thd);
Everything else is running in LOCAL_STATE and should not be considered status = ((thd->wsrep_exec_mode == REPL_RECV) ||
brute force. (thd->wsrep_exec_mode == TOTAL_ORDER));
*/ if (sync) mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
if (thd_ptr) {
switch (((THD *)thd_ptr)->wsrep_exec_mode) {
case LOCAL_STATE: return 0;
case REPL_RECV: return 1;
case TOTAL_ORDER: return 2;
case LOCAL_COMMIT: return 3;
} }
DBUG_ASSERT(0); return status;
}
return 0;
} }
extern "C" extern "C"
my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync)
{
bool status = FALSE;
if (thd_ptr)
{
THD* thd = (THD*)thd_ptr;
if (sync) mysql_mutex_lock(&thd->LOCK_wsrep_thd);
status = ((thd->wsrep_exec_mode == REPL_RECV) ||
(thd->wsrep_exec_mode == TOTAL_ORDER) ||
(thd->wsrep_exec_mode == LOCAL_COMMIT));
if (sync) mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
return status;
}
extern "C"
my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync)
{
bool status = FALSE;
if (thd_ptr)
{
THD* thd = (THD*)thd_ptr;
if (sync) mysql_mutex_lock(&thd->LOCK_wsrep_thd);
status = (thd->wsrep_exec_mode == LOCAL_STATE);
if (sync) mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
return status;
}
int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal) int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal)
{ {
THD *victim_thd = (THD *) victim_thd_ptr; THD *victim_thd = (THD *) victim_thd_ptr;

View File

@ -24,9 +24,13 @@ void wsrep_replay_transaction(THD *thd);
void wsrep_create_appliers(long threads); void wsrep_create_appliers(long threads);
void wsrep_create_rollbacker(); void wsrep_create_rollbacker();
extern "C" int wsrep_thd_is_brute_force(void *thd_ptr); int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr,
extern "C" int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr,
my_bool signal); my_bool signal);
extern my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
//extern "C" my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
extern "C" my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync);
extern "C" my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync);
extern "C" int wsrep_thd_in_locking_session(void *thd_ptr); extern "C" int wsrep_thd_in_locking_session(void *thd_ptr);
#endif /* WSREP_THD_H */ #endif /* WSREP_THD_H */

View File

@ -321,6 +321,10 @@ thd::~thd ()
/* Returns INADDR_NONE, INADDR_ANY, INADDR_LOOPBACK or something else */ /* Returns INADDR_NONE, INADDR_ANY, INADDR_LOOPBACK or something else */
unsigned int wsrep_check_ip (const char* const addr) unsigned int wsrep_check_ip (const char* const addr)
{ {
#if 0
if (addr && 0 == strcasecmp(addr, MY_BIND_ALL_ADDRESSES)) return INADDR_ANY;
#endif
unsigned int ret = INADDR_NONE; unsigned int ret = INADDR_NONE;
struct addrinfo *res, hints; struct addrinfo *res, hints;
@ -362,7 +366,6 @@ unsigned int wsrep_check_ip (const char* const addr)
} }
extern char* my_bind_addr_str; extern char* my_bind_addr_str;
extern uint mysqld_port;
size_t wsrep_guess_ip (char* buf, size_t buf_len) size_t wsrep_guess_ip (char* buf, size_t buf_len)
{ {

View File

@ -331,7 +331,16 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type)
bool wsrep_on_saved= thd->variables.wsrep_on; bool wsrep_on_saved= thd->variables.wsrep_on;
thd->variables.wsrep_on= false; thd->variables.wsrep_on= false;
/* stop replication is heavy operation, and includes closing all client
connections. Closing clients may need to get LOCK_global_system_variables
at least in MariaDB.
Note: releasing LOCK_global_system_variables may cause race condition, if
there can be several concurrent clients changing wsrep_provider
*/
mysql_mutex_unlock(&LOCK_global_system_variables);
wsrep_stop_replication(thd); wsrep_stop_replication(thd);
mysql_mutex_lock(&LOCK_global_system_variables);
if (wsrep_start_replication()) if (wsrep_start_replication())
{ {

View File

@ -1208,7 +1208,7 @@ innobase_srv_conc_enter_innodb(
{ {
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) && if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) return; wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return;
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
if (srv_thread_concurrency) { if (srv_thread_concurrency) {
if (trx->n_tickets_to_enter_innodb > 0) { if (trx->n_tickets_to_enter_innodb > 0) {
@ -1246,7 +1246,7 @@ innobase_srv_conc_exit_innodb(
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) && if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) return; wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return;
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
/* This is to avoid making an unnecessary function call. */ /* This is to avoid making an unnecessary function call. */
@ -3534,11 +3534,6 @@ innobase_commit_low(
/*================*/ /*================*/
trx_t* trx) /*!< in: transaction handle */ trx_t* trx) /*!< in: transaction handle */
{ {
if (trx_is_started(trx)) {
trx_commit_for_mysql(trx);
}
#ifdef WITH_WSREP #ifdef WITH_WSREP
THD* thd = (THD*)trx->mysql_thd; THD* thd = (THD*)trx->mysql_thd;
const char* tmp = 0; const char* tmp = 0;
@ -3556,7 +3551,10 @@ innobase_commit_low(
#endif /* WSREP_PROC_INFO */ #endif /* WSREP_PROC_INFO */
} }
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
if (trx_is_started(trx)) {
trx_commit_for_mysql(trx);
}
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); } if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); }
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
@ -5608,7 +5606,7 @@ wsrep_innobase_mysql_sort(
tmp_length = charset->coll->strnxfrm(charset, str, str_length, tmp_length = charset->coll->strnxfrm(charset, str, str_length,
str_length, tmp_str, tmp_length, 0); str_length, tmp_str, tmp_length, 0);
/**/ /**/
DBUG_ASSERT(tmp_length == str_length); DBUG_ASSERT(tmp_length <= str_length);
break; break;
} }
@ -7294,7 +7292,9 @@ ha_innobase::write_row(
|| sql_command == SQLCOM_CREATE_INDEX || sql_command == SQLCOM_CREATE_INDEX
#ifdef WITH_WSREP #ifdef WITH_WSREP
|| (wsrep_on(user_thd) && wsrep_load_data_splitting && || (wsrep_on(user_thd) && wsrep_load_data_splitting &&
sql_command == SQLCOM_LOAD) sql_command == SQLCOM_LOAD &&
!thd_test_options(
user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
|| sql_command == SQLCOM_DROP_INDEX) || sql_command == SQLCOM_DROP_INDEX)
&& num_write_row >= 10000) { && num_write_row >= 10000) {
@ -7304,7 +7304,6 @@ ha_innobase::write_row(
wsrep_thd_query(user_thd)); wsrep_thd_query(user_thd));
} }
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
/* ALTER TABLE is COMMITted at every 10000 copied rows. /* ALTER TABLE is COMMITted at every 10000 copied rows.
The IX table lock for the original table has to be re-issued. The IX table lock for the original table has to be re-issued.
As this method will be called on a temporary table where the As this method will be called on a temporary table where the
@ -7343,7 +7342,8 @@ no_commit:
{ {
case WSREP_TRX_OK: case WSREP_TRX_OK:
break; break;
case WSREP_TRX_ROLLBACK: case WSREP_TRX_SIZE_EXCEEDED:
case WSREP_TRX_CERT_FAIL:
case WSREP_TRX_ERROR: case WSREP_TRX_ERROR:
DBUG_RETURN(1); DBUG_RETURN(1);
} }
@ -7367,7 +7367,8 @@ no_commit:
{ {
case WSREP_TRX_OK: case WSREP_TRX_OK:
break; break;
case WSREP_TRX_ROLLBACK: case WSREP_TRX_SIZE_EXCEEDED:
case WSREP_TRX_CERT_FAIL:
case WSREP_TRX_ERROR: case WSREP_TRX_ERROR:
DBUG_RETURN(1); DBUG_RETURN(1);
} }
@ -7493,6 +7494,7 @@ no_commit:
if (wsrep_on(current_thd) && if (wsrep_on(current_thd) &&
auto_inc_inserted && auto_inc_inserted &&
wsrep_drupal_282555_workaround && wsrep_drupal_282555_workaround &&
wsrep_thd_retry_counter(current_thd) == 0 &&
!thd_test_options(current_thd, !thd_test_options(current_thd,
OPTION_NOT_AUTOCOMMIT | OPTION_NOT_AUTOCOMMIT |
OPTION_BEGIN)) { OPTION_BEGIN)) {
@ -9620,6 +9622,13 @@ ha_innobase::wsrep_append_keys(
} else { } else {
ut_a(table->s->keys <= 256); ut_a(table->s->keys <= 256);
uint i; uint i;
bool hasPK= false;
for (i=0; i<table->s->keys && !hasPK; ++i) {
KEY* key_info = table->key_info + i;
if (key_info->flags & HA_NOSAME) hasPK = true;
}
for (i=0; i<table->s->keys; ++i) { for (i=0; i<table->s->keys; ++i) {
uint len; uint len;
char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
@ -9640,14 +9649,11 @@ ha_innobase::wsrep_append_keys(
table->s->table_name.str, table->s->table_name.str,
key_info->name); key_info->name);
} }
if (key_info->flags & HA_NOSAME || if (!hasPK || key_info->flags & HA_NOSAME ||
((tab && ((tab &&
dict_table_get_referenced_constraint(tab, idx)) || dict_table_get_referenced_constraint(tab, idx)) ||
(!tab && referenced_by_foreign_key()))) { (!tab && referenced_by_foreign_key()))) {
if (key_info->flags & HA_NOSAME || shared)
key_appended = true;
len = wsrep_store_key_val_for_row( len = wsrep_store_key_val_for_row(
table, i, key0, key_info->key_length, table, i, key0, key_info->key_length,
record0, &is_null); record0, &is_null);
@ -9656,6 +9662,10 @@ ha_innobase::wsrep_append_keys(
thd, trx, table_share, table, thd, trx, table_share, table,
keyval0, len+1, shared); keyval0, len+1, shared);
if (rcode) DBUG_RETURN(rcode); if (rcode) DBUG_RETURN(rcode);
if (key_info->flags & HA_NOSAME || shared)
key_appended = true;
} }
else else
{ {
@ -16853,6 +16863,7 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno)
} }
/*******************************************************************//** /*******************************************************************//**
This function is used to kill one transaction in BF. */ This function is used to kill one transaction in BF. */
int int
wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
const trx_t * const bf_trx, const trx_t * const bf_trx,

View File

@ -291,7 +291,7 @@ UNIV_INTERN
int int
wsrep_innobase_kill_one_trx(void *thd_ptr, wsrep_innobase_kill_one_trx(void *thd_ptr,
const trx_t *bf_trx, trx_t *victim_trx, ibool signal); const trx_t *bf_trx, trx_t *victim_trx, ibool signal);
extern "C" int wsrep_thd_is_brute_force(void *thd_ptr); my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
int wsrep_trx_order_before(void *thd1, void *thd2); int wsrep_trx_order_before(void *thd1, void *thd2);
void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
unsigned char* str, unsigned int str_length); unsigned char* str, unsigned int str_length);

View File

@ -894,7 +894,6 @@ lock_trx_has_rec_x_lock(
record */ record */
#define LOCK_CONV_BY_OTHER 4096 /*!< this bit is set when the lock is created #define LOCK_CONV_BY_OTHER 4096 /*!< this bit is set when the lock is created
by other transaction */ by other transaction */
#define WSREP_BF 8192
#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_TYPE_MASK #if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_TYPE_MASK
# error # error
#endif #endif

View File

@ -979,47 +979,6 @@ lock_rec_has_to_wait(
&& !lock_mode_compatible(static_cast<enum lock_mode>( && !lock_mode_compatible(static_cast<enum lock_mode>(
LOCK_MODE_MASK & type_mode), LOCK_MODE_MASK & type_mode),
lock_get_mode(lock2))) { lock_get_mode(lock2))) {
#ifdef WITH_WSREP
/* if BF thread is locking and has conflict with another BF
thread, we need to look at trx ordering and lock types */
if (for_locking &&
wsrep_thd_is_brute_force(trx->mysql_thd) &&
wsrep_thd_is_brute_force(lock2->trx->mysql_thd)) {
if (wsrep_debug) {
fprintf(stderr, "\n BF-BF lock conflict \n");
lock_rec_print(stderr, lock2);
}
if (wsrep_trx_order_before(trx->mysql_thd,
lock2->trx->mysql_thd) &&
(type_mode & LOCK_MODE_MASK) == LOCK_X &&
(lock2->type_mode & LOCK_MODE_MASK) == LOCK_X)
{
/* exclusive lock conflicts are not accepted */
fprintf(stderr, "BF-BF X lock conflict\n");
lock_rec_print(stderr, lock2);
abort();
} else {
if (wsrep_debug) {
fprintf(stderr,
"BF conflict, modes: %lu %lu\n",
type_mode,
lock2->type_mode);
#ifdef OUT
fprintf(stderr,
"seqnos %llu %llu\n",
(long long)wsrep_thd_trx_seqno(
trx->mysql_thd),
(long long)wsrep_thd_trx_seqno(
lock2->trx->mysql_thd));
#endif
}
return FALSE;
}
}
#endif /* WITH_WSREP */
/* We have somewhat complex rules when gap type record locks /* We have somewhat complex rules when gap type record locks
cause waits */ cause waits */
@ -1069,6 +1028,44 @@ lock_rec_has_to_wait(
return(FALSE); return(FALSE);
} }
#ifdef WITH_WSREP
/* if BF thread is locking and has conflict with another BF
thread, we need to look at trx ordering and lock types */
if (for_locking &&
wsrep_thd_is_BF(trx->mysql_thd, FALSE) &&
wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) {
if (wsrep_debug) {
fprintf(stderr, "\n BF-BF lock conflict \n");
lock_rec_print(stderr, lock2);
}
if (wsrep_trx_order_before(trx->mysql_thd,
lock2->trx->mysql_thd) &&
(type_mode & LOCK_MODE_MASK) == LOCK_X &&
(lock2->type_mode & LOCK_MODE_MASK) == LOCK_X)
{
/* exclusive lock conflicts are not accepted */
fprintf(stderr, "BF-BF X lock conflict\n");
lock_rec_print(stderr, lock2);
abort();
} else {
/* if lock2->index->n_uniq <=
lock2->index->n_user_defined_cols
operation is on uniq index
*/
if (wsrep_debug) fprintf(stderr,
"BF conflict, modes: %lu %lu, "
"idx: %s-%s n_uniq %u n_user %u\n",
type_mode, lock2->type_mode,
lock2->index->name,
lock2->index->table_name,
lock2->index->n_uniq,
lock2->index->n_user_defined_cols);
return FALSE;
}
}
#endif /* WITH_WSREP */
return(TRUE); return(TRUE);
} }
@ -1626,13 +1623,12 @@ lock_rec_other_has_expl_req(
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
#ifdef WITH_WSREP #ifdef WITH_WSREP
static static void
void
wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) { wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
ut_ad(lock_mutex_own()); ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(lock->trx)); ut_ad(trx_mutex_own(lock->trx));
my_bool bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
my_bool bf_other = wsrep_thd_is_brute_force(lock->trx->mysql_thd); my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE);
if ((bf_this && !bf_other) || if ((bf_this && !bf_other) ||
(bf_this && bf_other && wsrep_trx_order_before( (bf_this && bf_other && wsrep_trx_order_before(
trx->mysql_thd, lock->trx->mysql_thd))) { trx->mysql_thd, lock->trx->mysql_thd))) {
@ -1930,11 +1926,6 @@ lock_rec_create(
lock->trx = trx; lock->trx = trx;
lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC; lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC;
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(trx->mysql_thd)) {
lock->type_mode |= WSREP_BF;
}
#endif /* WITH_WSREP */
lock->index = index; lock->index = index;
lock->un_member.rec_lock.space = space; lock->un_member.rec_lock.space = space;
@ -1954,12 +1945,12 @@ lock_rec_create(
ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted); ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
lock_t *hash = (lock_t *)c_lock->hash; lock_t *hash = (lock_t *)c_lock->hash;
lock_t *prev = NULL; lock_t *prev = NULL;
while (hash && while (hash &&
wsrep_thd_is_brute_force(((lock_t *)hash)->trx->mysql_thd) && wsrep_thd_is_BF(((lock_t *)hash)->trx->mysql_thd, TRUE) &&
wsrep_trx_order_before( wsrep_trx_order_before(
((lock_t *)hash)->trx->mysql_thd, ((lock_t *)hash)->trx->mysql_thd,
trx->mysql_thd)) { trx->mysql_thd)) {
@ -2363,11 +2354,6 @@ lock_rec_lock_fast(
|| (LOCK_MODE_MASK & mode) == LOCK_X); || (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == 0 || mode - (LOCK_MODE_MASK & mode) == 0
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
@ -2386,8 +2372,7 @@ lock_rec_lock_fast(
#else #else
lock = lock_rec_create( lock = lock_rec_create(
mode, block, heap_no, index, trx, FALSE); mode, block, heap_no, index, trx, FALSE);
#endif #endif /* WITH_WSREP */
} }
status = LOCK_REC_SUCCESS_CREATED; status = LOCK_REC_SUCCESS_CREATED;
} else { } else {
@ -2455,11 +2440,6 @@ lock_rec_lock_slow(
|| (LOCK_MODE_MASK & mode) == LOCK_X); || (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == 0 || mode - (LOCK_MODE_MASK & mode) == 0
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
@ -2569,19 +2549,8 @@ lock_rec_lock(
|| (LOCK_MODE_MASK & mode) == LOCK_X); || (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == 0); || mode - (LOCK_MODE_MASK & mode) == 0);
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(thr_get_trx(thr)->mysql_thd)) {
mode |= WSREP_BF;
}
#endif
ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
/* We try a simplified and faster subroutine for the most /* We try a simplified and faster subroutine for the most
@ -4025,15 +3994,17 @@ lock_deadlock_select_victim(
if (trx_weight_ge(ctx->wait_lock->trx, ctx->start)) { if (trx_weight_ge(ctx->wait_lock->trx, ctx->start)) {
/* The joining transaction is 'smaller', /* The joining transaction is 'smaller',
choose it as the victim and roll it back. */ choose it as the victim and roll it back. */
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (!wsrep_thd_is_brute_force(ctx->start->mysql_thd)) { if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
return(ctx->start); return(ctx->wait_lock->trx);
} else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
return(ctx->start); return(ctx->start);
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(ctx->wait_lock->trx->mysql_thd)) if (wsrep_thd_is_BF(ctx->wait_lock->trx->mysql_thd, TRUE))
return(ctx->start); return(ctx->start);
else else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
@ -4167,7 +4138,7 @@ lock_deadlock_search(
ctx->too_deep = TRUE; ctx->too_deep = TRUE;
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(ctx->start->mysql_thd)) if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
return(ctx->wait_lock->trx->id); return(ctx->wait_lock->trx->id);
else else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
@ -4190,7 +4161,7 @@ lock_deadlock_search(
ctx->too_deep = TRUE; ctx->too_deep = TRUE;
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(ctx->start->mysql_thd)) if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
return(lock->trx->id); return(lock->trx->id);
else else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
@ -4313,7 +4284,7 @@ lock_deadlock_check_and_resolve(
ut_a(victim_trx_id == trx->id); ut_a(victim_trx_id == trx->id);
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (!wsrep_thd_is_brute_force(ctx.start->mysql_thd)) if (!wsrep_thd_is_BF(ctx.start->mysql_thd, TRUE))
{ {
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
@ -4409,7 +4380,7 @@ lock_table_create(
UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock); UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock);
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
UT_LIST_INSERT_AFTER( UT_LIST_INSERT_AFTER(
un_member.tab_lock.locks, table->locks, c_lock, lock); un_member.tab_lock.locks, table->locks, c_lock, lock);
} else { } else {
@ -6489,7 +6460,7 @@ lock_rec_convert_impl_to_expl(
if (rec_get_deleted_flag(rec, rec_offs_comp(offsets)) if (rec_get_deleted_flag(rec, rec_offs_comp(offsets))
#ifdef WITH_WSREP #ifdef WITH_WSREP
&& !wsrep_thd_is_brute_force(impl_trx->mysql_thd) && !wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE)
/* BF-BF conflict is possible if advancing into /* BF-BF conflict is possible if advancing into
lock_rec_other_has_conflicting*/ lock_rec_other_has_conflicting*/
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */

View File

@ -184,6 +184,28 @@ lock_wait_table_reserve_slot(
return(NULL); return(NULL);
} }
#ifdef WITH_WSREP
/*********************************************************************//**
check if lock timeout was for priority thread,
as a side effect trigger lock monitor
@return false for regular lock timeout */
static ibool
wsrep_is_BF_lock_timeout(
/*====================*/
trx_t* trx) /* in: trx to check for lock priority */
{
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
fprintf(stderr, "WSREP: BF lock wait long\n");
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;
os_event_set(srv_monitor_event);
return TRUE;
}
return FALSE;
}
#endif /* WITH_WSREP */
/***************************************************************//** /***************************************************************//**
Puts a user OS thread to wait for a lock to be released. If an error Puts a user OS thread to wait for a lock to be released. If an error
occurs during the wait trx->error_state associated with thr is occurs during the wait trx->error_state associated with thr is
@ -375,9 +397,15 @@ lock_wait_suspend_thread(
if (lock_wait_timeout < 100000000 if (lock_wait_timeout < 100000000
&& wait_time > (double) lock_wait_timeout) { && wait_time > (double) lock_wait_timeout) {
#ifdef WITH_WSREP
if (!wsrep_is_BF_lock_timeout(trx)) {
#endif /* WITH_WSREP */
trx->error_state = DB_LOCK_WAIT_TIMEOUT; trx->error_state = DB_LOCK_WAIT_TIMEOUT;
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
MONITOR_INC(MONITOR_TIMEOUT); MONITOR_INC(MONITOR_TIMEOUT);
} }
@ -461,8 +489,13 @@ lock_wait_check_and_cancel(
if (trx->lock.wait_lock) { if (trx->lock.wait_lock) {
ut_a(trx->lock.que_state == TRX_QUE_LOCK_WAIT); ut_a(trx->lock.que_state == TRX_QUE_LOCK_WAIT);
#ifdef WITH_WSREP
if (!wsrep_is_BF_lock_timeout(trx)) {
#endif /* WITH_WSREP */
lock_cancel_waiting_and_release(trx->lock.wait_lock); lock_cancel_waiting_and_release(trx->lock.wait_lock);
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
} }
lock_mutex_exit(); lock_mutex_exit();

View File

@ -1926,9 +1926,6 @@ row_ins_scan_sec_index_for_duplicate(
mem_heap_t* offsets_heap) mem_heap_t* offsets_heap)
/*!< in/out: memory heap that can be emptied */ /*!< in/out: memory heap that can be emptied */
{ {
#ifdef WITH_WSREP
trx_t* trx = thr_get_trx(thr);
#endif
ulint n_unique; ulint n_unique;
int cmp; int cmp;
ulint n_fields_cmp; ulint n_fields_cmp;
@ -1997,16 +1994,8 @@ row_ins_scan_sec_index_for_duplicate(
if (flags & BTR_NO_LOCKING_FLAG) { if (flags & BTR_NO_LOCKING_FLAG) {
/* Set no locks when applying log /* Set no locks when applying log
in online table rebuild. */ in online table rebuild. */
#ifdef WITH_WSREP
/* slave applier must not get duplicate error */
} else if (allow_duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
} else if (allow_duplicates) { } else if (allow_duplicates) {
#endif
/* If the SQL-query will update or replace /* If the SQL-query will update or replace
duplicate key we will take X-lock for duplicate key we will take X-lock for
duplicates ( REPLACE, LOAD DATAFILE REPLACE, duplicates ( REPLACE, LOAD DATAFILE REPLACE,
@ -2016,6 +2005,10 @@ row_ins_scan_sec_index_for_duplicate(
lock_type, block, rec, index, offsets, thr); lock_type, block, rec, index, offsets, thr);
} else { } else {
#ifdef WITH_WSREP
/* appliers don't need dupkey checks */
if (!wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0))
#endif /* WITH_WSREP */
err = row_ins_set_shared_rec_lock( err = row_ins_set_shared_rec_lock(
lock_type, block, rec, index, offsets, thr); lock_type, block, rec, index, offsets, thr);
} }
@ -2211,13 +2204,7 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate sure that in roll-forward we get the same duplicate
errors as in original execution */ errors as in original execution */
#ifdef WITH_WSREP
if (trx->duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
if (trx->duplicates) { if (trx->duplicates) {
#endif
/* If the SQL-query will update or replace /* If the SQL-query will update or replace
duplicate key we will take X-lock for duplicate key we will take X-lock for
@ -2262,13 +2249,7 @@ duplicate:
offsets = rec_get_offsets(rec, cursor->index, offsets, offsets = rec_get_offsets(rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
#ifdef WITH_WSREP
if (trx->duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
if (trx->duplicates) { if (trx->duplicates) {
#endif
/* If the SQL-query will update or replace /* If the SQL-query will update or replace
duplicate key we will take X-lock for duplicate key we will take X-lock for

View File

@ -373,6 +373,8 @@ wsrep_row_upd_check_foreign_constraints(
trx = thr_get_trx(thr); trx = thr_get_trx(thr);
/* TODO: make native slave thread bail out here */
rec = btr_pcur_get_rec(pcur); rec = btr_pcur_get_rec(pcur);
ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_validate(rec, index, offsets));

View File

@ -2409,27 +2409,6 @@ suspend_thread:
OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */ OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
} }
#ifdef WITH_WSREP_TODO
/*********************************************************************//**
check if lock timeout was for priority thread,
as a side effect trigger lock monitor
@return false for regular lock timeout */
static ibool
wsrep_is_BF_lock_timeout(
/*====================*/
srv_slot_t* slot) /* in: lock slot to check for lock priority */
{
if (wsrep_on(thr_get_trx(slot->thr)->mysql_thd) &&
wsrep_thd_is_brute_force((thr_get_trx(slot->thr))->mysql_thd)) {
fprintf(stderr, "WSREP: BF lock wait long\n");
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;
os_event_set(lock_sys->timeout_event);
return TRUE;
}
return FALSE;
}
#endif /* WITH_WSREP_TODO */
/*********************************************************************//** /*********************************************************************//**
Check if purge should stop. Check if purge should stop.
@return true if it should shutdown. */ @return true if it should shutdown. */

View File

@ -178,7 +178,12 @@ trx_sys_flush_max_trx_id(void)
mtr_t mtr; mtr_t mtr;
trx_sysf_t* sys_header; trx_sysf_t* sys_header;
#ifndef WITH_WSREP
/* wsrep_fake_trx_id violates this assert
* Copied from trx_sys_get_new_trx_id
*/
ut_ad(mutex_own(&trx_sys->mutex)); ut_ad(mutex_own(&trx_sys->mutex));
#endif /* WITH_WSREP */
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
mtr_start(&mtr); mtr_start(&mtr);

View File

@ -1438,7 +1438,7 @@ innobase_srv_conc_enter_innodb(
{ {
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) && if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) return; wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return;
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
if (srv_thread_concurrency) { if (srv_thread_concurrency) {
if (trx->n_tickets_to_enter_innodb > 0) { if (trx->n_tickets_to_enter_innodb > 0) {
@ -1476,7 +1476,7 @@ innobase_srv_conc_exit_innodb(
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) && if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) return; wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return;
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
/* This is to avoid making an unnecessary function call. */ /* This is to avoid making an unnecessary function call. */
@ -3967,11 +3967,6 @@ innobase_commit_low(
/*================*/ /*================*/
trx_t* trx) /*!< in: transaction handle */ trx_t* trx) /*!< in: transaction handle */
{ {
if (trx_is_started(trx)) {
trx_commit_for_mysql(trx);
}
#ifdef WITH_WSREP #ifdef WITH_WSREP
THD* thd = (THD*)trx->mysql_thd; THD* thd = (THD*)trx->mysql_thd;
const char* tmp = 0; const char* tmp = 0;
@ -3989,7 +3984,10 @@ innobase_commit_low(
#endif /* WSREP_PROC_INFO */ #endif /* WSREP_PROC_INFO */
} }
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
if (trx_is_started(trx)) {
trx_commit_for_mysql(trx);
}
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); } if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); }
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
@ -6054,7 +6052,7 @@ wsrep_innobase_mysql_sort(
tmp_length = charset->coll->strnxfrm(charset, str, str_length, tmp_length = charset->coll->strnxfrm(charset, str, str_length,
str_length, tmp_str, tmp_length, 0); str_length, tmp_str, tmp_length, 0);
/**/ /**/
DBUG_ASSERT(tmp_length == str_length); DBUG_ASSERT(tmp_length <= str_length);
break; break;
} }
@ -7755,7 +7753,6 @@ ha_innobase::write_row(
wsrep_thd_query(user_thd)); wsrep_thd_query(user_thd));
} }
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
/* ALTER TABLE is COMMITted at every 10000 copied rows. /* ALTER TABLE is COMMITted at every 10000 copied rows.
The IX table lock for the original table has to be re-issued. The IX table lock for the original table has to be re-issued.
As this method will be called on a temporary table where the As this method will be called on a temporary table where the
@ -7794,7 +7791,8 @@ no_commit:
{ {
case WSREP_TRX_OK: case WSREP_TRX_OK:
break; break;
case WSREP_TRX_ROLLBACK: case WSREP_TRX_SIZE_EXCEEDED:
case WSREP_TRX_CERT_FAIL:
case WSREP_TRX_ERROR: case WSREP_TRX_ERROR:
DBUG_RETURN(1); DBUG_RETURN(1);
} }
@ -7818,10 +7816,12 @@ no_commit:
{ {
case WSREP_TRX_OK: case WSREP_TRX_OK:
break; break;
case WSREP_TRX_ROLLBACK: case WSREP_TRX_SIZE_EXCEEDED:
case WSREP_TRX_CERT_FAIL:
case WSREP_TRX_ERROR: case WSREP_TRX_ERROR:
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (binlog_hton->commit(binlog_hton, user_thd, 1)) if (binlog_hton->commit(binlog_hton, user_thd, 1))
DBUG_RETURN(1); DBUG_RETURN(1);
wsrep_post_commit(user_thd, TRUE); wsrep_post_commit(user_thd, TRUE);
@ -7952,6 +7952,7 @@ no_commit:
if (wsrep_on(current_thd) && if (wsrep_on(current_thd) &&
auto_inc_inserted && auto_inc_inserted &&
wsrep_drupal_282555_workaround && wsrep_drupal_282555_workaround &&
wsrep_thd_retry_counter(current_thd) == 0 &&
!thd_test_options(current_thd, !thd_test_options(current_thd,
OPTION_NOT_AUTOCOMMIT | OPTION_NOT_AUTOCOMMIT |
OPTION_BEGIN)) { OPTION_BEGIN)) {
@ -7963,8 +7964,7 @@ no_commit:
error= DB_SUCCESS; error= DB_SUCCESS;
wsrep_thd_set_conflict_state( wsrep_thd_set_conflict_state(
current_thd, MUST_ABORT); current_thd, MUST_ABORT);
innobase_srv_conc_exit_innodb( innobase_srv_conc_exit_innodb(prebuilt->trx);
prebuilt->trx);
/* jump straight to func exit over /* jump straight to func exit over
* later wsrep hooks */ * later wsrep hooks */
goto func_exit; goto func_exit;
@ -10133,6 +10133,13 @@ ha_innobase::wsrep_append_keys(
} else { } else {
ut_a(table->s->keys <= 256); ut_a(table->s->keys <= 256);
uint i; uint i;
bool hasPK= false;
for (i=0; i<table->s->keys && !hasPK; ++i) {
KEY* key_info = table->key_info + i;
if (key_info->flags & HA_NOSAME) hasPK = true;
}
for (i=0; i<table->s->keys; ++i) { for (i=0; i<table->s->keys; ++i) {
uint len; uint len;
char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
@ -10153,14 +10160,11 @@ ha_innobase::wsrep_append_keys(
table->s->table_name.str, table->s->table_name.str,
key_info->name); key_info->name);
} }
if (key_info->flags & HA_NOSAME || if (!hasPK || key_info->flags & HA_NOSAME ||
((tab && ((tab &&
dict_table_get_referenced_constraint(tab, idx)) || dict_table_get_referenced_constraint(tab, idx)) ||
(!tab && referenced_by_foreign_key()))) { (!tab && referenced_by_foreign_key()))) {
if (key_info->flags & HA_NOSAME || shared)
key_appended = true;
len = wsrep_store_key_val_for_row( len = wsrep_store_key_val_for_row(
table, i, key0, key_info->key_length, table, i, key0, key_info->key_length,
record0, &is_null); record0, &is_null);
@ -10169,6 +10173,10 @@ ha_innobase::wsrep_append_keys(
thd, trx, table_share, table, thd, trx, table_share, table,
keyval0, len+1, shared); keyval0, len+1, shared);
if (rcode) DBUG_RETURN(rcode); if (rcode) DBUG_RETURN(rcode);
if (key_info->flags & HA_NOSAME || shared)
key_appended = true;
} }
else else
{ {
@ -17759,6 +17767,7 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno)
} }
/*******************************************************************//** /*******************************************************************//**
This function is used to kill one transaction in BF. */ This function is used to kill one transaction in BF. */
int int
wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
const trx_t * const bf_trx, const trx_t * const bf_trx,

View File

@ -290,7 +290,7 @@ UNIV_INTERN
int int
wsrep_innobase_kill_one_trx(void *thd_ptr, wsrep_innobase_kill_one_trx(void *thd_ptr,
const trx_t *bf_trx, trx_t *victim_trx, ibool signal); const trx_t *bf_trx, trx_t *victim_trx, ibool signal);
extern "C" int wsrep_thd_is_brute_force(void *thd_ptr); my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
int wsrep_trx_order_before(void *thd1, void *thd2); int wsrep_trx_order_before(void *thd1, void *thd2);
void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
unsigned char* str, unsigned int str_length); unsigned char* str, unsigned int str_length);

View File

@ -906,7 +906,6 @@ lock_trx_has_rec_x_lock(
record */ record */
#define LOCK_CONV_BY_OTHER 4096 /*!< this bit is set when the lock is created #define LOCK_CONV_BY_OTHER 4096 /*!< this bit is set when the lock is created
by other transaction */ by other transaction */
#define WSREP_BF 8192
#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_TYPE_MASK #if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_TYPE_MASK
# error # error
#endif #endif

View File

@ -55,7 +55,6 @@ extern my_bool wsrep_debug;
extern my_bool wsrep_log_conflicts; extern my_bool wsrep_log_conflicts;
#include "ha_prototypes.h" #include "ha_prototypes.h"
#endif #endif
/* Restricts the length of search we will do in the waits-for /* Restricts the length of search we will do in the waits-for
graph of transactions */ graph of transactions */
#define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000 #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000
@ -981,47 +980,6 @@ lock_rec_has_to_wait(
&& !lock_mode_compatible(static_cast<enum lock_mode>( && !lock_mode_compatible(static_cast<enum lock_mode>(
LOCK_MODE_MASK & type_mode), LOCK_MODE_MASK & type_mode),
lock_get_mode(lock2))) { lock_get_mode(lock2))) {
#ifdef WITH_WSREP
/* if BF thread is locking and has conflict with another BF
thread, we need to look at trx ordering and lock types */
if (for_locking &&
wsrep_thd_is_brute_force(trx->mysql_thd) &&
wsrep_thd_is_brute_force(lock2->trx->mysql_thd)) {
if (wsrep_debug) {
fprintf(stderr, "\n BF-BF lock conflict \n");
lock_rec_print(stderr, lock2);
}
if (wsrep_trx_order_before(trx->mysql_thd,
lock2->trx->mysql_thd) &&
(type_mode & LOCK_MODE_MASK) == LOCK_X &&
(lock2->type_mode & LOCK_MODE_MASK) == LOCK_X)
{
/* exclusive lock conflicts are not accepted */
fprintf(stderr, "BF-BF X lock conflict\n");
lock_rec_print(stderr, lock2);
abort();
} else {
if (wsrep_debug) {
fprintf(stderr,
"BF conflict, modes: %lu %lu\n",
type_mode,
lock2->type_mode);
#ifdef OUT
fprintf(stderr,
"seqnos %llu %llu\n",
(long long)wsrep_thd_trx_seqno(
trx->mysql_thd),
(long long)wsrep_thd_trx_seqno(
lock2->trx->mysql_thd));
#endif
}
return FALSE;
}
}
#endif /* WITH_WSREP */
/* We have somewhat complex rules when gap type record locks /* We have somewhat complex rules when gap type record locks
cause waits */ cause waits */
@ -1071,6 +1029,44 @@ lock_rec_has_to_wait(
return(FALSE); return(FALSE);
} }
#ifdef WITH_WSREP
/* if BF thread is locking and has conflict with another BF
thread, we need to look at trx ordering and lock types */
if (for_locking &&
wsrep_thd_is_BF(trx->mysql_thd, FALSE) &&
wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) {
if (wsrep_debug) {
fprintf(stderr, "\n BF-BF lock conflict \n");
lock_rec_print(stderr, lock2);
}
if (wsrep_trx_order_before(trx->mysql_thd,
lock2->trx->mysql_thd) &&
(type_mode & LOCK_MODE_MASK) == LOCK_X &&
(lock2->type_mode & LOCK_MODE_MASK) == LOCK_X)
{
/* exclusive lock conflicts are not accepted */
fprintf(stderr, "BF-BF X lock conflict\n");
lock_rec_print(stderr, lock2);
abort();
} else {
/* if lock2->index->n_uniq <=
lock2->index->n_user_defined_cols
operation is on uniq index
*/
if (wsrep_debug) fprintf(stderr,
"BF conflict, modes: %lu %lu, "
"idx: %s-%s n_uniq %u n_user %u\n",
type_mode, lock2->type_mode,
lock2->index->name,
lock2->index->table_name,
lock2->index->n_uniq,
lock2->index->n_user_defined_cols);
return FALSE;
}
}
#endif /* WITH_WSREP */
return(TRUE); return(TRUE);
} }
@ -1578,8 +1574,7 @@ lock_rec_has_expl(
static static
void void
lock_rec_discard(lock_t* in_lock); lock_rec_discard(lock_t* in_lock);
#endif /* WITH_WSREP */ #endif
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/*********************************************************************//** /*********************************************************************//**
Checks if some other transaction has a lock request in the queue. Checks if some other transaction has a lock request in the queue.
@ -1629,13 +1624,12 @@ lock_rec_other_has_expl_req(
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
#ifdef WITH_WSREP #ifdef WITH_WSREP
static static void
void
wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) { wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
ut_ad(lock_mutex_own()); ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(lock->trx)); ut_ad(trx_mutex_own(lock->trx));
my_bool bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
my_bool bf_other = wsrep_thd_is_brute_force(lock->trx->mysql_thd); my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE);
if ((bf_this && !bf_other) || if ((bf_this && !bf_other) ||
(bf_this && bf_other && wsrep_trx_order_before( (bf_this && bf_other && wsrep_trx_order_before(
trx->mysql_thd, lock->trx->mysql_thd))) { trx->mysql_thd, lock->trx->mysql_thd))) {
@ -1933,11 +1927,6 @@ lock_rec_create(
lock->trx = trx; lock->trx = trx;
lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC; lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC;
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(trx->mysql_thd)) {
lock->type_mode |= WSREP_BF;
}
#endif /* WITH_WSREP */
lock->index = index; lock->index = index;
lock->un_member.rec_lock.space = space; lock->un_member.rec_lock.space = space;
@ -1957,12 +1946,12 @@ lock_rec_create(
ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted); ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
lock_t *hash = (lock_t *)c_lock->hash; lock_t *hash = (lock_t *)c_lock->hash;
lock_t *prev = NULL; lock_t *prev = NULL;
while (hash && while (hash &&
wsrep_thd_is_brute_force(((lock_t *)hash)->trx->mysql_thd) && wsrep_thd_is_BF(((lock_t *)hash)->trx->mysql_thd, TRUE) &&
wsrep_trx_order_before( wsrep_trx_order_before(
((lock_t *)hash)->trx->mysql_thd, ((lock_t *)hash)->trx->mysql_thd,
trx->mysql_thd)) { trx->mysql_thd)) {
@ -2376,11 +2365,6 @@ lock_rec_lock_fast(
|| (LOCK_MODE_MASK & mode) == LOCK_X); || (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == 0 || mode - (LOCK_MODE_MASK & mode) == 0
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
@ -2468,11 +2452,6 @@ lock_rec_lock_slow(
|| (LOCK_MODE_MASK & mode) == LOCK_X); || (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == 0 || mode - (LOCK_MODE_MASK & mode) == 0
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
@ -2582,19 +2561,8 @@ lock_rec_lock(
|| (LOCK_MODE_MASK & mode) == LOCK_X); || (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == 0); || mode - (LOCK_MODE_MASK & mode) == 0);
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(thr_get_trx(thr)->mysql_thd)) {
mode |= WSREP_BF;
}
#endif
ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
/* We try a simplified and faster subroutine for the most /* We try a simplified and faster subroutine for the most
@ -4040,15 +4008,17 @@ lock_deadlock_select_victim(
if (trx_weight_ge(ctx->wait_lock->trx, ctx->start)) { if (trx_weight_ge(ctx->wait_lock->trx, ctx->start)) {
/* The joining transaction is 'smaller', /* The joining transaction is 'smaller',
choose it as the victim and roll it back. */ choose it as the victim and roll it back. */
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (!wsrep_thd_is_brute_force(ctx->start->mysql_thd)) if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
return(ctx->start); return(ctx->wait_lock->trx);
else else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
return(ctx->start); return(ctx->start);
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(ctx->wait_lock->trx->mysql_thd)) if (wsrep_thd_is_BF(ctx->wait_lock->trx->mysql_thd, TRUE))
return(ctx->start); return(ctx->start);
else else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
@ -4182,7 +4152,7 @@ lock_deadlock_search(
ctx->too_deep = TRUE; ctx->too_deep = TRUE;
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(ctx->start->mysql_thd)) if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
return(ctx->wait_lock->trx->id); return(ctx->wait_lock->trx->id);
else else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
@ -4205,7 +4175,7 @@ lock_deadlock_search(
ctx->too_deep = TRUE; ctx->too_deep = TRUE;
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(ctx->start->mysql_thd)) if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE))
return(lock->trx->id); return(lock->trx->id);
else else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
@ -4328,7 +4298,7 @@ lock_deadlock_check_and_resolve(
ut_a(victim_trx_id == trx->id); ut_a(victim_trx_id == trx->id);
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (!wsrep_thd_is_brute_force(ctx.start->mysql_thd)) if (!wsrep_thd_is_BF(ctx.start->mysql_thd, TRUE))
{ {
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
@ -4426,7 +4396,7 @@ lock_table_create(
UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock); UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock);
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
UT_LIST_INSERT_AFTER( UT_LIST_INSERT_AFTER(
un_member.tab_lock.locks, table->locks, c_lock, lock); un_member.tab_lock.locks, table->locks, c_lock, lock);
} else { } else {
@ -6531,7 +6501,7 @@ lock_rec_convert_impl_to_expl(
if (rec_get_deleted_flag(rec, rec_offs_comp(offsets)) if (rec_get_deleted_flag(rec, rec_offs_comp(offsets))
#ifdef WITH_WSREP #ifdef WITH_WSREP
&& !wsrep_thd_is_brute_force(impl_trx->mysql_thd) && !wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE)
/* BF-BF conflict is possible if advancing into /* BF-BF conflict is possible if advancing into
lock_rec_other_has_conflicting*/ lock_rec_other_has_conflicting*/
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */

View File

@ -184,6 +184,28 @@ lock_wait_table_reserve_slot(
return(NULL); return(NULL);
} }
#ifdef WITH_WSREP
/*********************************************************************//**
check if lock timeout was for priority thread,
as a side effect trigger lock monitor
@return false for regular lock timeout */
static ibool
wsrep_is_BF_lock_timeout(
/*====================*/
trx_t* trx) /* in: trx to check for lock priority */
{
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
fprintf(stderr, "WSREP: BF lock wait long\n");
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;
os_event_set(srv_monitor_event);
return TRUE;
}
return FALSE;
}
#endif /* WITH_WSREP */
/***************************************************************//** /***************************************************************//**
Puts a user OS thread to wait for a lock to be released. If an error Puts a user OS thread to wait for a lock to be released. If an error
occurs during the wait trx->error_state associated with thr is occurs during the wait trx->error_state associated with thr is
@ -375,9 +397,15 @@ lock_wait_suspend_thread(
if (lock_wait_timeout < 100000000 if (lock_wait_timeout < 100000000
&& wait_time > (double) lock_wait_timeout) { && wait_time > (double) lock_wait_timeout) {
#ifdef WITH_WSREP
if (!wsrep_is_BF_lock_timeout(trx)) {
#endif /* WITH_WSREP */
trx->error_state = DB_LOCK_WAIT_TIMEOUT; trx->error_state = DB_LOCK_WAIT_TIMEOUT;
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
MONITOR_INC(MONITOR_TIMEOUT); MONITOR_INC(MONITOR_TIMEOUT);
} }
@ -461,8 +489,13 @@ lock_wait_check_and_cancel(
if (trx->lock.wait_lock) { if (trx->lock.wait_lock) {
ut_a(trx->lock.que_state == TRX_QUE_LOCK_WAIT); ut_a(trx->lock.que_state == TRX_QUE_LOCK_WAIT);
#ifdef WITH_WSREP
if (!wsrep_is_BF_lock_timeout(trx)) {
#endif /* WITH_WSREP */
lock_cancel_waiting_and_release(trx->lock.wait_lock); lock_cancel_waiting_and_release(trx->lock.wait_lock);
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
} }
lock_mutex_exit(); lock_mutex_exit();

View File

@ -1938,9 +1938,6 @@ row_ins_scan_sec_index_for_duplicate(
mem_heap_t* offsets_heap) mem_heap_t* offsets_heap)
/*!< in/out: memory heap that can be emptied */ /*!< in/out: memory heap that can be emptied */
{ {
#ifdef WITH_WSREP
trx_t* trx = thr_get_trx(thr);
#endif
ulint n_unique; ulint n_unique;
int cmp; int cmp;
ulint n_fields_cmp; ulint n_fields_cmp;
@ -2009,16 +2006,7 @@ row_ins_scan_sec_index_for_duplicate(
if (flags & BTR_NO_LOCKING_FLAG) { if (flags & BTR_NO_LOCKING_FLAG) {
/* Set no locks when applying log /* Set no locks when applying log
in online table rebuild. */ in online table rebuild. */
#ifdef WITH_WSREP
/* slave applier must not get duplicate error */
} else if (allow_duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
} else if (allow_duplicates) { } else if (allow_duplicates) {
#endif
/* If the SQL-query will update or replace /* If the SQL-query will update or replace
duplicate key we will take X-lock for duplicate key we will take X-lock for
@ -2029,6 +2017,10 @@ row_ins_scan_sec_index_for_duplicate(
lock_type, block, rec, index, offsets, thr); lock_type, block, rec, index, offsets, thr);
} else { } else {
#ifdef WITH_WSREP
/* appliers don't need dupkey checks */
if (!wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0))
#endif /* WITH_WSREP */
err = row_ins_set_shared_rec_lock( err = row_ins_set_shared_rec_lock(
lock_type, block, rec, index, offsets, thr); lock_type, block, rec, index, offsets, thr);
} }
@ -2224,13 +2216,7 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate sure that in roll-forward we get the same duplicate
errors as in original execution */ errors as in original execution */
#ifdef WITH_WSREP
if (trx->duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
if (trx->duplicates) { if (trx->duplicates) {
#endif
/* If the SQL-query will update or replace /* If the SQL-query will update or replace
duplicate key we will take X-lock for duplicate key we will take X-lock for
@ -2275,13 +2261,7 @@ duplicate:
offsets = rec_get_offsets(rec, cursor->index, offsets, offsets = rec_get_offsets(rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
#ifdef WITH_WSREP
if (trx->duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
if (trx->duplicates) { if (trx->duplicates) {
#endif
/* If the SQL-query will update or replace /* If the SQL-query will update or replace
duplicate key we will take X-lock for duplicate key we will take X-lock for

View File

@ -375,6 +375,8 @@ wsrep_row_upd_check_foreign_constraints(
trx = thr_get_trx(thr); trx = thr_get_trx(thr);
/* TODO: make native slave thread bail out here */
rec = btr_pcur_get_rec(pcur); rec = btr_pcur_get_rec(pcur);
ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_validate(rec, index, offsets));

View File

@ -2998,27 +2998,6 @@ suspend_thread:
OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */ OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
} }
#ifdef WITH_WSREP_TODO
/*********************************************************************//**
check if lock timeout was for priority thread,
as a side effect trigger lock monitor
@return false for regular lock timeout */
static ibool
wsrep_is_BF_lock_timeout(
/*====================*/
srv_slot_t* slot) /* in: lock slot to check for lock priority */
{
if (wsrep_on(thr_get_trx(slot->thr)->mysql_thd) &&
wsrep_thd_is_brute_force((thr_get_trx(slot->thr))->mysql_thd)) {
fprintf(stderr, "WSREP: BF lock wait long\n");
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;
os_event_set(lock_sys->timeout_event);
return TRUE;
}
return FALSE;
}
#endif /* WITH_WSREP_TODO */
/*********************************************************************//** /*********************************************************************//**
Check if purge should stop. Check if purge should stop.
@return true if it should shutdown. */ @return true if it should shutdown. */

View File

@ -178,7 +178,12 @@ trx_sys_flush_max_trx_id(void)
mtr_t mtr; mtr_t mtr;
trx_sysf_t* sys_header; trx_sysf_t* sys_header;
#ifndef WITH_WSREP
/* wsrep_fake_trx_id violates this assert
* Copied from trx_sys_get_new_trx_id
*/
ut_ad(mutex_own(&trx_sys->mutex)); ut_ad(mutex_own(&trx_sys->mutex));
#endif /* WITH_WSREP */
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
mtr_start(&mtr); mtr_start(&mtr);

View File

@ -1174,6 +1174,7 @@ echo "=====" >> $STATUS_HISTORY
%attr(755, root, root) %{_bindir}/wsrep_sst_rsync %attr(755, root, root) %{_bindir}/wsrep_sst_rsync
%attr(755, root, root) %{_bindir}/wsrep_sst_rsync_wan %attr(755, root, root) %{_bindir}/wsrep_sst_rsync_wan
%attr(755, root, root) %{_bindir}/wsrep_sst_xtrabackup %attr(755, root, root) %{_bindir}/wsrep_sst_xtrabackup
%attr(755, root, root) %{_bindir}/wsrep_sst_xtrabackup-v2
%endif %endif
%attr(755, root, root) %{_sbindir}/mysqld %attr(755, root, root) %{_sbindir}/mysqld

View File

@ -137,7 +137,11 @@ typedef void (*wsrep_log_cb_t)(wsrep_log_level_t, const char *);
typedef uint64_t wsrep_trx_id_t; //!< application transaction ID typedef uint64_t wsrep_trx_id_t; //!< application transaction ID
typedef uint64_t wsrep_conn_id_t; //!< application connection ID typedef uint64_t wsrep_conn_id_t; //!< application connection ID
typedef int64_t wsrep_seqno_t; //!< sequence number of a writeset, etc. typedef int64_t wsrep_seqno_t; //!< sequence number of a writeset, etc.
#ifdef __cplusplus
typedef bool wsrep_bool_t;
#else
typedef _Bool wsrep_bool_t; //!< should be the same as standard (C99) bool typedef _Bool wsrep_bool_t; //!< should be the same as standard (C99) bool
#endif /* __cplusplus */
/*! undefined seqno */ /*! undefined seqno */
#define WSREP_SEQNO_UNDEFINED (-1) #define WSREP_SEQNO_UNDEFINED (-1)

View File

@ -20,11 +20,13 @@
#include <errno.h> #include <errno.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
/*! Dummy backend context. */ /*! Dummy backend context. */
typedef struct wsrep_dummy typedef struct wsrep_dummy
{ {
wsrep_log_cb_t log_fn; wsrep_log_cb_t log_fn;
char* options;
} wsrep_dummy_t; } wsrep_dummy_t;
/* Get pointer to wsrep_dummy context from wsrep_t pointer */ /* Get pointer to wsrep_dummy context from wsrep_t pointer */
@ -42,6 +44,10 @@ typedef struct wsrep_dummy
static void dummy_free(wsrep_t *w) static void dummy_free(wsrep_t *w)
{ {
WSREP_DBUG_ENTER(w); WSREP_DBUG_ENTER(w);
if (WSREP_DUMMY(w)->options)
{
free(WSREP_DUMMY(w)->options);
}
free(w->ctx); free(w->ctx);
w->ctx = NULL; w->ctx = NULL;
} }
@ -49,8 +55,15 @@ static void dummy_free(wsrep_t *w)
static wsrep_status_t dummy_init (wsrep_t* w, static wsrep_status_t dummy_init (wsrep_t* w,
const struct wsrep_init_args* args) const struct wsrep_init_args* args)
{ {
WSREP_DUMMY(w)->log_fn = args->logger_cb;
WSREP_DBUG_ENTER(w); WSREP_DBUG_ENTER(w);
WSREP_DUMMY(w)->log_fn = args->logger_cb;
if (args->options)
{
char* options = malloc(strlen(args->options) + 1);
if (options == NULL) return WSREP_WARNING;
strcpy(options, args->options);
WSREP_DUMMY(w)->options = options;
}
return WSREP_OK; return WSREP_OK;
} }
@ -61,16 +74,41 @@ static uint64_t dummy_capabilities (wsrep_t* w __attribute__((unused)))
static wsrep_status_t dummy_options_set( static wsrep_status_t dummy_options_set(
wsrep_t* w, wsrep_t* w,
const char* conf __attribute__((unused))) const char* conf)
{ {
char* options = NULL;
WSREP_DBUG_ENTER(w); WSREP_DBUG_ENTER(w);
// concatenate config string with ';'
options = WSREP_DUMMY(w)->options;
if (options == NULL)
{
options = malloc(strlen(conf) + 1);
if (options == NULL)
{
return WSREP_WARNING;
}
strcpy(options, conf);
} else {
int opt_len = strlen(options);
char* p = realloc(options,
opt_len + 1 + // ';'
strlen(conf) + 1); // \0
if (p == NULL)
{
return WSREP_WARNING;
}
p[opt_len] = ';';
strcpy(p + opt_len + 1, conf);
options = p;
}
WSREP_DUMMY(w)->options = options;
return WSREP_OK; return WSREP_OK;
} }
static char* dummy_options_get (wsrep_t* w) static char* dummy_options_get (wsrep_t* w)
{ {
WSREP_DBUG_ENTER(w); WSREP_DBUG_ENTER(w);
return NULL; return WSREP_DUMMY(w)->options;
} }
static wsrep_status_t dummy_connect( static wsrep_status_t dummy_connect(
@ -385,6 +423,7 @@ int wsrep_dummy_loader(wsrep_t* w)
// initialize private context // initialize private context
WSREP_DUMMY(w)->log_fn = NULL; WSREP_DUMMY(w)->log_fn = NULL;
WSREP_DUMMY(w)->options = NULL;
return 0; return 0;
} }