MySQL

93 阅读9分钟

日期查询

按天统计

select DATE_FORMAT(start_time,'%Y%m%d') days,count(product_no) count from test group by days;

按周统计

select DATE_FORMAT(start_time,'%Y%u') weeks,count(product_no) count from test group by weeks;

按月统计

select DATE_FORMAT(start_time,'%Y%m') months,count(product_no) count from test group by months;

当前时间或日期

SELECT CURDATE();  # 2018-12-20
SELECT NOW();  # 2018-12-20 15:04:54

第几天

SELECT to_days("2018-12-07");   # 737400
SELECT to_days("2018-12-07 10:17:12");  # 737400

第几秒

SELECT to_seconds("2018-12-07 10:17:12");; # 63711397032

年份

SELECT year("2018-01-07 10:17:00"); # 2018
SELECT year("2018-01-07");  # 2018

月份

SELECT month("2018-01-07 10:17:00");  # 1
SELECT month("2018-01-07");  # 1

获取第几周

---使用week函数
---第一个参数是date或datetime格式
---第二个参数表示从1开始,或者从0开始。

SELECT week("2018-01-01 10:17:00", 1); # 1
SELECT week("2018-01-01", 1); # 1
SELECT week("2018-01-01 10:17:00", 0); # 0
SELECT week("2018-01-01", 0); # 0

某年第几周

---同时获取到年份和周数

SELECT yearweek("2018-01-01", 1);  # 201801
SELECT yearweek("2018-12-20 14:24:01", 1);  # 201851

年月日

SELECT date("2018-01-07 10:17:00");  # 2018-01-07
SELECT date("2018-01-07");  # 2018-01-07

小时

SELECT hour("2018-01-07 10:17:00"); # 10

分钟

SELECT minute("2018-01-07 10:17:00"); # 17

秒钟

SELECT second("2018-01-07 10:17:12"); # 12

季度

SELECT quarter("2018-01-07 10:17:12");  # 1
SELECT quarter("2018-12-07");  # 4

now()和sysdate()的区别

  • now()取的是语句开始执行的时间,取的是内置的“timestamp”变量,这个变量在语句开始执行时就已设定好,因此在整个语句中的执行过程中都不会发生变化。
  • sysdate()取的是动态的实时时间 例句:SELECT NOW(),SYSDATE(),SLEEP(3),NOW(),SYSDATE();

基于Linux安装mysql 8.0.29

首先查看机器的版本

getconf LONG_BIT

根据上述命令的输出结果自行选择需要安装的版本(32位或64位)

安装包下载

# 32位安装包
wget https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.29-linux-glibc2.12-i686.tar.xz
# 64位安装包
wget https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.29-linux-glibc2.12-x86_64.tar.xz

注:如果服务器没有外网,可以自己在本地电脑下载好之后上传到服务器即可。

解压&重命名

由于我的服务器根目录空间较小,运维外挂的一块磁盘在/app目录下,所以我最终将mysql安装在了/app/usr/local/mysql中。

创建文件夹:mkdir -p /app/usr/local

解压缩到上述新建的文件夹:tar -xvf mysql-8.0.29-linux-glibc2.12-x86_64.tar.xz -C /app/usr/local

进入/app/usr/local文件夹:cd /app/usr/local

重命名:mv mysql-8.0.29-linux-glibc2.12-x86_64 mysql

创建mysql用户组

groupadd mysql

useradd -r -g mysql mysql

创建之后可以使用命令:cat /etc/group | grep mysql来查看是否创建成功

对mysql用户组进行授权

chown -R mysql /app/usr/local/mysql/

chgrp -R mysql /app/usr/local/mysql/

创建数据存储目录

在mysql中创建data文件夹用来存储数据:

cd /app/usr/local/mysql
mkdir data

对data数据存储目录授权:chown mysql:mysql -R data

对组和用户授权

chown -R mysql.mysql /app/usr/local/mysql

chown -R mysql.mysql /app/usr/local/mysql/data

chgrp -R mysql /app/usr/local/mysql

配置文件

cd /app/usr/local/mysql/support-files/

cp mysql.server /etc/init.d/mysqld
# 创建my.cnf文件
vi /etc/my.cnf

添加如下内容(部分目录根据自身服务器情况可略微调整):

[mysqldump]
# 用户名和密码
user=root
password=123456

[client]
port = 3306
socket = /app/usr/local/mysql/tmp/mysql.sock

[mysqld]
bind-address=0.0.0.0
port = 3306
user=root
basedir=/app/usr/local/mysql
datadir=/app/usr/local/mysql/data
socket=/app/usr/local/mysql/tmp/mysql.sock
log-error=/app/usr/local/mysql/mysql.log
pid-file=/app/usr/local/mysql/mysql.pid
symbolic-links=0
explicit_defaults_for_timestamp=true
# 编码
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
# 数据库表不区分大小写
lower_case_table_names = 1
sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO'
default-time_zone = '+8:00'

修改mysqld文件内容:vi /etc/init.d/mysqld 完整的内容如下:

#!/bin/sh
# Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
# This file is public domain and comes with NO WARRANTY of any kind

# MySQL daemon start/stop script.

# Usually this is put in /etc/init.d (at least on machines SYSV R4 based
# systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/K01mysql.
# When this is done the mysql server will be started when the machine is
# started and shut down when the systems goes down.

# Comments to support chkconfig on RedHat Linux
# chkconfig: 2345 64 36
# description: A very fast and reliable SQL database engine.

# Comments to support LSB init script conventions
### BEGIN INIT INFO
# Provides: mysql
# Required-Start: $local_fs $network $remote_fs
# Should-Start: ypbind nscd ldap ntpd xntpd
# Required-Stop: $local_fs $network $remote_fs
# Default-Start:  2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop MySQL
# Description: MySQL is a very fast and reliable SQL database engine.
### END INIT INFO

# If you install MySQL on some other places than /usr/local/mysql, then you
# have to do one of the following things for this script to work:
#
# - Run this script from within the MySQL installation directory
# - Create a /etc/my.cnf file with the following information:
#   [mysqld]
#   basedir=<path-to-mysql-installation-directory>
# - Add the above to any other configuration file (for example ~/.my.ini)
#   and copy my_print_defaults to /usr/bin
# - Add the path to the mysql-installation-directory to the basedir variable
#   below.
#
# If you want to affect other MySQL variables, you should make your changes
# in the /etc/my.cnf, ~/.my.cnf or other MySQL configuration files.

# If you change base dir, you must also change datadir. These may get
# overwritten by settings in the MySQL configuration files.

# 添加或修改内容 begin
basedir=/app/usr/local/mysql
datadir=/app/usr/local/mysql/data
# 添加或修改内容 end

# Default value, in seconds, afterwhich the script should timeout waiting
# for server start.
# Value here is overriden by value in my.cnf.
# 0 means don't wait at all
# Negative numbers mean to wait indefinitely
service_startup_timeout=900

# Lock directory for RedHat / SuSE.

# 添加或修改内容 begin
lockdir='/app/usr/local/mysql/lock/subsys'
# 添加或修改内容 end

lock_file_path="$lockdir/mysql"

# The following variables are only set for letting mysql.server find things.

# Set some defaults
mysqld_pid_file_path=
if test -z "$basedir"
then
# 添加或修改内容 begin
  basedir=/app/usr/local/mysql
  bindir=/app/usr/local/mysql/bin
  if test -z "$datadir"
  then
    datadir=/app/usr/local/mysql/data
  fi
  sbindir=/app/usr/local/mysql/bin
  libexecdir=/app/usr/local/mysql/bin
else
  bindir="$basedir/bin"
  if test -z "$datadir"
  then
    datadir="$basedir/data"
  fi
  sbindir="$basedir/sbin"
  libexecdir="$basedir/libexec"
fi
# 添加或修改内容 end

# datadir_set is used to determine if datadir was set (and so should be
# *not* set inside of the --basedir= handler.)
datadir_set=

#
# Use LSB init script functions for printing messages, if possible
#
lsb_functions="/lib/lsb/init-functions"
if test -f $lsb_functions ; then
  . $lsb_functions
else
  log_success_msg()
  {
    echo " SUCCESS! $@"
  }
  log_failure_msg()
  {
    echo " ERROR! $@"
  }
fi

PATH="/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin"
export PATH

mode=$1    # start or stop

[ $# -ge 1 ] && shift


other_args="$*"   # uncommon, but needed when called from an RPM upgrade action
           # Expected: "--skip-networking --skip-grant-tables"
           # They are not checked here, intentionally, as it is the resposibility
           # of the "spec" file author to give correct arguments only.

case `echo "testing\c"`,`echo -n testing` in
    *c*,-n*) echo_n=   echo_c=     ;;
    *c*,*)   echo_n=-n echo_c=     ;;
    *)       echo_n=   echo_c='\c' ;;
esac

parse_server_arguments() {
  for arg do
    case "$arg" in
      --basedir=*)  basedir=`echo "$arg" | sed -e 's/^[^=]*=//'`
                    bindir="$basedir/bin"
                    if test -z "$datadir_set"; then
                      datadir="$basedir/data"
                    fi
                    sbindir="$basedir/sbin"
                    libexecdir="$basedir/libexec"
        ;;
      --datadir=*)  datadir=`echo "$arg" | sed -e 's/^[^=]*=//'`
                    datadir_set=1
        ;;
      --pid-file=*) mysqld_pid_file_path=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
      --service-startup-timeout=*) service_startup_timeout=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
    esac
  done
}

wait_for_pid () {
  verb="$1"           # created | removed
  pid="$2"            # process ID of the program operating on the pid-file
  pid_file_path="$3" # path to the PID file.

  i=0
  avoid_race_condition="by checking again"

  while test $i -ne $service_startup_timeout ; do

    case "$verb" in
      'created')
        # wait for a PID-file to pop into existence.
        test -s "$pid_file_path" && i='' && break
        ;;
      'removed')
        # wait for this PID-file to disappear
        test ! -s "$pid_file_path" && i='' && break
        ;;
      *)
        echo "wait_for_pid () usage: wait_for_pid created|removed pid pid_file_path"
        exit 1
        ;;
    esac

    # if server isn't running, then pid-file will never be updated
    if test -n "$pid"; then
      if kill -0 "$pid" 2>/dev/null; then
        :  # the server still runs
      else
        # The server may have exited between the last pid-file check and now.
        if test -n "$avoid_race_condition"; then
          avoid_race_condition=""
          continue  # Check again.
        fi

        # there's nothing that will affect the file.
        log_failure_msg "The server quit without updating PID file ($pid_file_path)."
        return 1  # not waiting any more.
      fi
    fi

    echo $echo_n ".$echo_c"
    i=`expr $i + 1`
    sleep 1

  done

  if test -z "$i" ; then
    log_success_msg
    return 0
  else
    log_failure_msg
    return 1
  fi
}

# Get arguments from the my.cnf file,
# the only group, which is read from now on is [mysqld]
if test -x "$bindir/my_print_defaults";  then
  print_defaults="$bindir/my_print_defaults"
else
  # Try to find basedir in /etc/my.cnf
  conf=/etc/my.cnf
  print_defaults=
  if test -r $conf
  then
    subpat='^[^=]*basedir[^=]*=\(.*\)$'
    dirs=`sed -e "/$subpat/!d" -e 's//\1/' $conf`
    for d in $dirs
    do
      d=`echo $d | sed -e 's/[  ]//g'`
      if test -x "$d/bin/my_print_defaults"
      then
        print_defaults="$d/bin/my_print_defaults"
        break
      fi
    done
  fi

  # Hope it's in the PATH ... but I doubt it
  test -z "$print_defaults" && print_defaults="my_print_defaults"
fi

#
# Read defaults file from 'basedir'.   If there is no defaults file there
# check if it's in the old (depricated) place (datadir) and read it from there
#

extra_args=""
if test -r "$basedir/my.cnf"
then
  extra_args="-e $basedir/my.cnf"
fi

parse_server_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server`

#
# Set pid file if not given
#
if test -z "$mysqld_pid_file_path"
then
  mysqld_pid_file_path=$datadir/`hostname`.pid
else
  case "$mysqld_pid_file_path" in
    /* ) ;;
    * )  mysqld_pid_file_path="$datadir/$mysqld_pid_file_path" ;;
  esac
fi

case "$mode" in
  'start')
    # Start daemon

    # Safeguard (relative paths, core dumps..)
    cd $basedir

    echo $echo_n "Starting MySQL"
    if test -x $bindir/mysqld_safe
    then
      # Give extra arguments to mysqld with the my.cnf file. This script
      # may be overwritten at next upgrade.
      $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null &
      wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$?

      # Make lock for RedHat / SuSE
      if test -w "$lockdir"
      then
        touch "$lock_file_path"
      fi

      exit $return_value
    else
      log_failure_msg "Couldn't find MySQL server ($bindir/mysqld_safe)"
    fi
    ;;

  'stop')
    # Stop daemon. We use a signal here to avoid having to know the
    # root password.

    if test -s "$mysqld_pid_file_path"
    then
      # signal mysqld_safe that it needs to stop
      touch "$mysqld_pid_file_path.shutdown"

      mysqld_pid=`cat "$mysqld_pid_file_path"`

      if (kill -0 $mysqld_pid 2>/dev/null)
      then
        echo $echo_n "Shutting down MySQL"
        kill $mysqld_pid
        # mysqld should remove the pid file when it exits, so wait for it.
        wait_for_pid removed "$mysqld_pid" "$mysqld_pid_file_path"; return_value=$?
      else
        log_failure_msg "MySQL server process #$mysqld_pid is not running!"
        rm "$mysqld_pid_file_path"
      fi

      # Delete lock for RedHat / SuSE
      if test -f "$lock_file_path"
      then
        rm -f "$lock_file_path"
      fi
      exit $return_value
    else
      log_failure_msg "MySQL server PID file could not be found!"
    fi
    ;;

  'restart')
    # Stop the service and regardless of whether it was
    # running or not, start it again.
    if $0 stop  $other_args; then
      $0 start $other_args
    else
      log_failure_msg "Failed to stop running server, so refusing to try to start."
      exit 1
    fi
    ;;

  'reload'|'force-reload')
    if test -s "$mysqld_pid_file_path" ; then
      read mysqld_pid <  "$mysqld_pid_file_path"
      kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL"
      touch "$mysqld_pid_file_path"
    else
      log_failure_msg "MySQL PID file could not be found!"
      exit 1
    fi
    ;;
  'status')
    # First, check to see if pid file exists
    if test -s "$mysqld_pid_file_path" ; then
      read mysqld_pid < "$mysqld_pid_file_path"
      if kill -0 $mysqld_pid 2>/dev/null ; then
        log_success_msg "MySQL running ($mysqld_pid)"
        exit 0
      else
        log_failure_msg "MySQL is not running, but PID file exists"
        exit 1
      fi
    else
      # Try to find appropriate mysqld process
      mysqld_pid=`pidof $libexecdir/mysqld`

      # test if multiple pids exist
      pid_count=`echo $mysqld_pid | wc -w`
      if test $pid_count -gt 1 ; then
        log_failure_msg "Multiple MySQL running but PID file could not be found ($mysqld_pid)"
        exit 5
      elif test -z $mysqld_pid ; then
        if test -f "$lock_file_path" ; then
          log_failure_msg "MySQL is not running, but lock file ($lock_file_path) exists"
          exit 2
        fi
        log_failure_msg "MySQL is not running"
        exit 3
      else
        log_failure_msg "MySQL is running but PID file could not be found"
        exit 4
      fi
    fi
    ;;
    *)
      # usage
      basename=`basename "$0"`
      echo "Usage: $basename  {start|stop|restart|reload|force-reload|status}  [ MySQL server options ]"
      exit 1
    ;;
esac

exit 0

创建目录:

cd /app/usr/local/mysql
mkdir -p lock/subsys
mkdir tmp

添加环境变量:

vi /etc/profile

# 文件末尾添加如下内容
# Set MYSQL
export MYSQL=/app/usr/local/mysql
export PATH=$PATH:$MYSQL/bin

保存退出,使用命令:source /etc/profile生效

初始化数据库

进入/app/usr/local/mysql/bin目录,执行命令:./mysqld --initialize --basedir=/app/usr/local/mysql --user=mysql --datadir=/app/usr/local/mysql/data

basedir为安装目录,datadir为数据文件存储目录

启停数据库

# 启动数据库
service mysqld start
# 输出如下内容表示启动成功:
Starting MySQL. SUCCESS!

# 关闭数据库
service mysqld stop
# 输出如下内容表示关闭成功:
Shutting down MySQL. SUCCESS!

查看初始临时密码

cat /app/usr/local/mysql/mysql.log

# 从log中找到temporary password,我的log中涉及到的内容如下。其中yy2omuDK.ntw就是随机生成的密码
A temporary password is generated for root@localhost: yy2omuDK.ntw

登陆数据库

在mysql的bin目录中执行命令:mysql -u root -p回车输入上面查到的临时密码

修改root用户的密码:alter user 'root'@'localhost' identified by '123456';

查看访问权限

使用命令:select user,host from user;输出如下:

mysql> select user,host from user;

+------------------+-----------+

| user | host |

+------------------+-----------+

| mysql.infoschema | localhost |

| mysql.session | localhost |

| mysql.sys | localhost |

| root | localhost |

+------------------+-----------+

4 rows in set (0.00 sec)

可以看到默认情况下只允许本地访问,远程客户端是无法访问的。执行命令:update user set host='%' where user='root';然后重启数据库:service mysqld restart即可解决。

添加开机自启动

chkconfig mysqld on

备份数据库命令

当需要做数据库备份时可以使用mysqldump相关的命令及参数

# root是用户名 123456是密码(该密码要和)1.8中my.cnf配置的password保持一致
mysqldump -uroot -p123456 mysql > mysql.dump

报错&踩坑

如果在linux服务器执行mysql或者mysqldump指令时报如下错误

-bash: mysql: command not found

-bash: mysqldump: command not found

这是由于系统默认会查找/usr/bin下的命令。如果这个命令不在这个目录下,会找不到命令。

我们可以映射一个链接到/usr/bin目录下,相当于建立一个链接文件。

解决办法:

  • 查看mysql的安装路径
[root@monitor ~]# whereis mysql
# /app/usr/local/mysql/bin/mysql就是mysql的安装路径
mysql: /usr/lib64/mysql /usr/share/mysql /app/usr/local/mysql/bin/mysql
  • 设置软链接(mysql的安装路径可能有所不同,需要修改,主要查找的是mysqldump、mysql所在的路径)
ln -fs /app/usr/local/mysql/bin/mysqldump /usr/bin

ln -fs /app/usr/local/mysql/bin/mysql /usr/bin