【问题标题】:Docker Compose: MySQL Syntax Error "DELIMITER" On Line 1Docker Compose:第 1 行的 MySQL 语法错误“DELIMITER”
【发布时间】:2026-02-06 03:45:02
【问题描述】:

我有一个问题,我希望 Docker Compose 在设置 MySQL 后直接导入我的 Database.sql 文件。但它总是给我抛出错误:

您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以获取在“DELIMITER |”附近使用的正确语法在第 1 行

但不知何故,当我通过浏览器中的 phpMyAdmin 导入它时,它工作得非常好。

这是我的docker-compose.yml

version: "3.2"
services:
  php:
    build: './php/'
    networks:
      - backend
    volumes:
      - ./www/:/var/www/html/
  apache:
    build: './apache/'
    depends_on:
      - php
      - mysql
    networks:
      - frontend
      - backend
    ports:
      - "8081:80"
    volumes:
      - ./www/:/var/www/html/
  mysql:
    image: mysql:5.7
    volumes:
      - ./mysql:/tmp/database
    command: mysqld --max_allowed_packet=32505856 --user=root --init-file="/tmp/database/schema.sql"
    networks:
      - backend
    environment:
      - MYSQL_ROOT_PASSWORD=root
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    links:
        - mysql
    ports:
      - '8082:80'
    environment:
      MYSQL_USERNAME: root
      MYSQL_ROOT_PASSWORD: root
      PMA_HOST: mysql
    networks:
      - backend
networks:
  frontend:
  backend:

这是我执行的 .sql 文件的示例片段:

-- phpMyAdmin SQL Dump
-- version 4.8.2
-- https://www.phpmyadmin.net/
--
-- Host: mysql
-- Generation Time: Aug 20, 2018 at 08:30 AM
-- Server version: 5.7.23
-- PHP Version: 7.2.6
DELIMITER $$

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";

--
-- Database: `database`
--
CREATE DATABASE IF NOT EXISTS `databasetest` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
USE `databasetest`;

--
-- Procedures
--
DROP PROCEDURE IF EXISTS `sp_filestatus_get`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_filestatus_get` (IN `filename_name` VARCHAR(500), IN `kampagne_name` VARCHAR(100), IN `outlet_name` VARCHAR(100))  NO SQL

... Some more stuff

END;

我是否遗漏了配置中的某些内容?或者为什么它不能与 compose 一起工作,但直接在 phpMyAdmin 中工作?

【问题讨论】:

  • 请记住 DELIMITER 不是 MySQL 命令。这是您的 MySQL 客户端需要支持的命令。所以可能 docker(或你的 docker 版本)不知何故不支持它。
  • 啊,谢谢您的回复,我不知道。这就是它直接在 phpMyAdmin 中工作的原因。有没有可能找出哪个 Docker 版本支持 DELIMITER?
  • 我不知道,不幸的是,我从未使用过 Docker。刚刚遇到其他客户的这个问题。

标签: mysql docker phpmyadmin


【解决方案1】:

我想我可能通过使用/docker-entrypoint-initdb.d/ 而不是init-file=... 标志偶然发现了一个不那么老套的解决方案:

docker-compose.yml
  db:
    image: "mysql:5.7.33"
    container_name: "mydb"
    command: "--default-authentication-plugin=mysql_native_password"
    volumes: # Scripts will apparently be executed by ascending order. See https://github.com/docker-library/mysql/issues/395#issuecomment-375409393
    - db-datavolume:/var/lib/mysql
    - ./db/init.sql:/docker-entrypoint-initdb.d/init1.sql
    - ./db/triggers.sql:/docker-entrypoint-initdb.d/init2.sql
    - ./db/seed.sql:/docker-entrypoint-initdb.d/init3.sql
  ...

volumes:
  db-datavolume

之后,在主机的./db/triggers.sql(挂载到/docker-entrypoint-initdb.d/init2.sql)中,DELIMETER 工作正常。

【讨论】:

    【解决方案2】:

    如果你真的需要你的DELIMITER 语句,你可以将你的mysql命令更改为

    bash -c "service mysql start && echo 'xxxxxxxxxxxxxxxxx' && mysql --max_allowed_packet=32505856 -u root -proot < /tmp/database/schema.sql && while true; do sleep 1; done"

    那么它应该可以在没有任何其他更改的情况下工作。

    所以你的 mysql-section 应该是这样的:

      mysql:
        image: mysql:5.7
        volumes:
          - ./mysql:/tmp/database
        command: bash -c "service mysql start && echo 'xxxxxxxxxxxxxxxxx' && mysql --max_allowed_packet=32505856 -u root -proot < /tmp/database/schema.sql && while true; do sleep 1; done"
        networks:
          - backend
        environment:
          - MYSQL_ROOT_PASSWORD=root
    

    解释它为什么起作用:

    之前,您使用mysqld 命令启动mysql-server 并指定init-script。现在它作为服务启动。这带来了一个优点和一个缺点。

    • 优势:您现在可以使用mysql 命令连接到您的mysql-server。
    • 缺点:指定mysql命令后,容器会被docker停止。

    为了解决这个缺点,我添加了while true; do sleep 1; done 作为最后一个命令。这会导致容器运行直到它停止。 echo 只是为了让您看到命令被执行。

    【讨论】:

    • 不起作用。它甚至不尝试执行我的 sql 文件。
    • 抱歉 - 已解决问题!
    • 该死的。请解释它为什么起作用,这样这可能是有回报的答案。这比之前的答案更短更容易!它只是满足我的要求。对不起那个投反对票的人
    • PS: Grüße aus Österreich :D
    • @reiner.luke 好吧,它来自推理,你在 sql 中有语法错误,并以你携带该脚本的方式修复它,这是明确的......另外,你必须在这里小心,因为我猜您在执行 mysql 命令期间可能有静默异常,该命令未引发,并且容器继续运行,因为您添加了 while 循环。您可以为此仔细检查 sql 服务启动日志,并确保在交互式会话中运行脚本不会引发异常。关于安全:解决方法!= 不安全...
    【解决方案3】:

    sql API 不直接支持DELIMETER,因为该语句的支持是由它在 phpmyadmin 中工作的客户端定义的,因为它支持该语句。默认的mysql 客户端使用delimeter 语句,按照Stored programs defining 中的建议步骤并相应地更新sql 文件(CREATE PROCEDURE 应替换为您的sql 语句)。

    mysql> delimiter //
    
    mysql> CREATE PROCEDURE dorepeat(p1 INT)
        -> BEGIN
        ->   SET @x = 0;
        ->   REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
        -> END
        -> //
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> delimiter ;
    

    根据您使用的脚本,您必须以不同于现在的方式处理分隔符:

    替换

    DROP PROCEDURE IF EXISTS `sp_filestatus_get`$$
    

    DROP PROCEDURE IF EXISTS `sp_filestatus_get`;
    

    另外,请将END; 替换为END $$ 并在文件末尾添加DELIMITER ;

    这里有一些链接,您可以在 init sql 脚本中找到需要调整的内容:

    【讨论】:

    • 所以实际上我必须用命令行设置分隔符?类似的东西:command: mysqld delimiter $$ --max_allowed_packet=32505856 --user=root --init-file="/tmp/database/winwin_pms_schema.sql"。 $$ 因为我所有的语句都使用DELIMITER $$。这只是一个想法,因为此命令不起作用
    • 不,它应该定义在winwin_pms_schema.sql的顶部,并且在定义sql过程的END之后设置回之前的值(;
    • @reiner.luke 另外,我敢打赌这是 sql 相关的问题,而不是 docker-compose
    • 编辑了我的问题。如您所见,我在所有语句的顶部定义分隔符并将其重置为END;。但仍然是同样的错误。
    • @reiner.luke 欢迎您,祝您好运! :) 谢谢你的奖励!