En corto
MySQL, en el servidor origen:
| |
PostgreSQL, en el servidor origen:
| |
Y en los dos casos:
| |
gcloud sql import sql acepta SQL plano o .gz: el formato custom de pg_dump va por pg_restore (abajo).
Los errores y de dónde salen
En Cloud SQL nadie tiene SUPER (MySQL) ni es superusuario (PostgreSQL); el administrador es root@% o postgres, miembro de cloudsqlsuperuser. Todo lo que un dump normal da por hecho de un servidor propio se rompe justo ahí:
| Error al importar | Motor | Causa | Arreglo |
|---|---|---|---|
ERROR 1227 (42000) at line N: Access denied; you need (at least one of) the SUPER privilege(s) for this operation (línea de un CREATE … VIEW, TRIGGER, PROCEDURE, FUNCTION o EVENT) | MySQL | DEFINER=`user`@`host` de un usuario que no existe en la instancia, o de root@localhost, que en Cloud SQL nunca existe. El dump no trae usuarios (y no debe traerlos) | Crear esos usuarios antes de importar, o quitar los DEFINER= con el sed |
El mismo ERROR 1227 en las primeras líneas, en SET @@GLOBAL.GTID_PURGED=… | MySQL | El origen tiene GTID y mysqldump escribe la posición, que solo SUPER puede fijar | --set-gtid-purged=OFF |
ERROR 1449 (HY000): The user specified as a definer ('app'@'localhost') does not exist al usar la vista, no al importar | MySQL | Dejaste un DEFINER de un usuario que no existe en la instancia | Quitar el DEFINER o crear el usuario con ese host exacto |
ERROR: must be owner of extension plpgsql | PostgreSQL | COMMENT ON EXTENSION plpgsql del dump: en Cloud SQL las extensiones pertenecen a cloudsqladmin | Comentar las líneas EXTENSION con el sed |
ERROR: role "app_owner" does not exist | PostgreSQL | ALTER … OWNER TO y GRANT … TO para roles del servidor viejo | --no-owner --no-acl, o crear los roles antes |
ERROR: permission denied for schema public o must be owner of … a mitad del dump | PostgreSQL | Importaste con un --user que no es el dueño de lo que ya existe en la base | Importa como postgres en una base vacía; reasigna después |
MySQL: qué hacer con los DEFINER
Primero mira cuántos y cuáles hay en el origen:
| |
Tres salidas, de más a menos fiel al original:
- Crear los usuarios en la instancia antes de importar, con el mismo
user@host:gcloud sql users create app --host=% --instance=my-instance --password=…. Es lo que recomienda la documentación, y mantiene las vistas y procedimientos exactamente como estaban.root@localhostes la excepción: no se puede crear en Cloud SQL, así que unDEFINERcon ese valor hay que cambiarlo sí o sí. - Quitar el
DEFINERcon elsedde arriba: los objetos se crean con el usuario que importa como definer. Suficiente cuando los usuarios del origen no van a existir en Cloud SQL. - Pasar a
SQL SECURITY INVOKER(sed -E 's/SQL SECURITY DEFINER/SQL SECURITY INVOKER/g'además del anterior): la vista o el procedimiento corre con los privilegios de quien lo llama y el definer deja de importar. Cambia el modelo de permisos; revisa que los usuarios de la aplicación puedan leer las tablas de debajo.
El sed es deliberadamente amplio porque DEFINER= aparece también dentro de comentarios condicionales (/*!50013 DEFINER=… SQL SECURITY DEFINER */); borrar solo el DEFINER= deja el resto intacto y válido.
MySQL: los flags, uno por uno
| Flag | Por qué |
|---|---|
--hex-blob | Columnas binarias en hexadecimal; sin él, un BLOB con bytes raros se corrompe al pasar por el juego de caracteres |
--single-transaction | Snapshot consistente de InnoDB sin bloquear tablas; imprescindible en producción |
--set-gtid-purged=OFF | No escribir SET @@GLOBAL.GTID_PURGED, que Cloud SQL no deja ejecutar |
--default-character-set=utf8mb4 | Que el dump y el SET NAMES que trae coincidan con lo que hay en las tablas; evita el clásico é |
--databases app | Obligatorio según la documentación, y nunca con la base mysql. Añade CREATE DATABASE IF NOT EXISTS y USE app, así --database en la importación es opcional |
--routines --triggers --events | mysqldump solo incluye triggers por defecto; procedimientos, funciones y eventos hay que pedirlos. Todos llevan DEFINER |
Si el usuario con el que haces el dump no tiene PROCESS, mysqldump 8.0.21+ falla al inicio con “Access denied; you need (at least one of) the PROCESS privilege(s)” al consultar tablespaces: añade --no-tablespaces.
PostgreSQL: plano o custom
--no-owner --no-acl hacen que todo lo importado pertenezca al --user y no haya GRANT a roles fantasma. Si la aplicación se conecta con otro rol, crea el rol antes y usa --user=app, o reasigna después:
| |
Las extensiones que necesite la base (pg_trgm, postgis, uuid-ossp…) créalas antes de importar, como postgres, en la base destino: CREATE EXTENSION IF NOT EXISTS pg_trgm;. Solo funcionan las de la lista de extensiones soportadas de Cloud SQL; plpgsql ya está. Con eso, comentar los CREATE EXTENSION del dump no quita nada.
Si prefieres el formato custom (-Fc), el filtro de extensiones va en la lista de contenidos de pg_restore, tal como lo documenta Google, y restauras a través del Cloud SQL Auth Proxy:
| |
-j 4 restaura en paralelo, cosa que la importación desde el bucket no hace.
Trampas
- El rol del bucket va a la service account de la instancia, no a la tuya: la documentación pide
storage.objectAdmin(para importar bastanstorage.objects.getylist, es decir,objectViewer). Sin él, “The service account does not have the required permissions for the bucket” aunque tú puedas leer el objeto. - Una operación a la vez por instancia: si hay un backup o export en marcha, la importación falla con “operation already in progress”.
gcloud sql operations list --instance=my-instancelo muestra. - Dumps grandes: la importación es en serie y tarda; lanza con
--asyncy vigila congcloud sql operations wait OPERATION_ID --timeout=unlimited, o elgcloudse te muere por el camino. - Versión de
pg_dump: usa la misma versión mayor que el destino o inferior.pg_dump17 escribeSET transaction_timeout = 0;, que un PostgreSQL 16 rechaza con “unrecognized configuration parameter” y aborta la importación. utf8mb4en la instancia:--default-character-set=utf8mb4en el dump no arregla una instancia creada conlatin1; compruebacharacter_set_serveren los flags de la instancia antes de importar.- El
sedde DEFINER también toca datos: si alguna fila contiene literalmenteDEFINER=`x`@`y`(raro, pero un CMS que guarda SQL puede), sáltala con un patrón anclado aCREATE, o revisa el diff del dump.
Ver también
- PostgreSQL: cheat sheet de administración — roles,
pg_dump,REASSIGN OWNEDy compañía. - Import and export using SQL dump files (MySQL), DEFINER clause y pg_dump / pg_restore (PostgreSQL) en la documentación de Cloud SQL.