La función SYSDATE() devuelve la fecha y hora del sistema operativo en el momento exacto en que se ejecuta, no cuando comienza la sentencia SQL. Esta diferencia sutil con NOW() tiene implicaciones importantes en procedimientos almacenados, funciones y especialmente en entornos de replicación.
Mientras NOW() captura la fecha y hora al inicio de la sentencia y mantiene ese valor constante durante toda su ejecución, SYSDATE() consulta el reloj del sistema cada vez que se invoca. Esto significa que dos llamadas a SYSDATE() dentro de la misma sentencia pueden devolver valores diferentes si hay suficiente tiempo entre ambas evaluaciones.
Sintaxis
SYSDATE([fsp])El parámetro opcional fsp (fractional seconds precision) acepta valores de 0 a 6 para incluir dígitos de precisión fraccional. Sin parámetro, devuelve la hora con precisión de segundos.
Comportamiento básico
Para entender la diferencia clave entre SYSDATE() y NOW(), observa qué ocurre cuando introduces un retraso entre las evaluaciones.
SELECT SYSDATE() AS inicio_sysdate,
NOW() AS inicio_now,
SLEEP(3) AS pausa,
SYSDATE() AS fin_sysdate,
NOW() AS fin_now;| inicio_sysdate | inicio_now | pausa | fin_sysdate | fin_now |
|---|---|---|---|---|
| 2025-07-15 14:32:08 | 2025-07-15 14:32:08 | 0 | 2025-07-15 14:32:11 | 2025-07-15 14:32:08 |
Las columnas de NOW() muestran exactamente la misma hora en ambas apariciones. En cambio, las columnas de SYSDATE() difieren en tres segundos, porque la segunda llamada consulta el reloj del sistema después de que SLEEP(3) haya introducido la pausa.
Este comportamiento se debe a que MySQL determina el valor de NOW() una vez al comenzar a ejecutar la sentencia y lo reutiliza en cada referencia. SYSDATE(), por el contrario, realiza una llamada al sistema operativo cada vez que se evalúa.
Con precisión fraccionaria, la diferencia puede ser aún más evidente.
SELECT SYSDATE(6) AS primera, SYSDATE(6) AS segunda;| primera | segunda |
|---|---|
| 2025-07-15 14:32:08.451293 | 2025-07-15 14:32:08.451307 |
Incluso sin un SLEEP explícito, los microsegundos pueden diferir porque cada evaluación ocurre en un instante ligeramente distinto.
Caso práctico: auditoría precisa en procedimientos almacenados
En procedimientos almacenados que ejecutan múltiples operaciones, SYSDATE() puede registrar el momento real de cada paso, mientras que NOW() mostraría la misma hora para todo el procedimiento.
CREATE TABLE log_auditoria (
id INT AUTO_INCREMENT PRIMARY KEY,
operacion VARCHAR(100) NOT NULL,
momento_now DATETIME(3) NOT NULL,
momento_sysdate DATETIME(3) NOT NULL
);
DELIMITER //
CREATE PROCEDURE procesar_lote()
BEGIN
INSERT INTO log_auditoria (operacion, momento_now, momento_sysdate)
VALUES ('Inicio del proceso', NOW(3), SYSDATE(3));
-- Simular procesamiento pesado
DO SLEEP(2);
INSERT INTO log_auditoria (operacion, momento_now, momento_sysdate)
VALUES ('Actualización de inventario', NOW(3), SYSDATE(3));
DO SLEEP(1);
INSERT INTO log_auditoria (operacion, momento_now, momento_sysdate)
VALUES ('Fin del proceso', NOW(3), SYSDATE(3));
END //
DELIMITER ;
CALL procesar_lote();
SELECT * FROM log_auditoria ORDER BY id;| id | operacion | momento_now | momento_sysdate |
|---|---|---|---|
| 1 | Inicio del proceso | 2025-07-15 14:32:08.451 | 2025-07-15 14:32:08.451 |
| 2 | Actualización de inventario | 2025-07-15 14:32:08.451 | 2025-07-15 14:32:10.453 |
| 3 | Fin del proceso | 2025-07-15 14:32:08.451 | 2025-07-15 14:32:11.455 |
La columna momento_now tiene el mismo valor en las tres filas porque NOW() se fijó al iniciar el CALL. En cambio, momento_sysdate refleja el momento real de cada inserción, mostrando los dos y tres segundos de retraso acumulados por los SLEEP.
Caso práctico: medir duración de operaciones
SYSDATE() es útil para medir cuánto tarda una operación dentro de una misma sentencia, algo imposible con NOW().
SELECT SYSDATE(6) AS antes,
(SELECT COUNT(*) FROM pedidos WHERE total > 100) AS conteo,
SYSDATE(6) AS despues,
TIMESTAMPDIFF(MICROSECOND, @t1 := SYSDATE(6), SYSDATE(6)) AS diferencia_us;Sin embargo, para mediciones de rendimiento formales, es más apropiado usar las herramientas de performance schema de MySQL. SYSDATE() ofrece una alternativa rápida e informal.
Implicaciones en replicación
Este es el aspecto más crítico de SYSDATE(). En un entorno de replicación basada en sentencias (statement-based replication), el servidor réplica ejecuta las mismas sentencias que el principal. Cuando una sentencia contiene NOW(), MySQL registra el timestamp en el log binario y la réplica usa ese mismo valor, garantizando consistencia.
Con SYSDATE(), la réplica evalúa la función en su propio momento de ejecución, que puede ser segundos o minutos después. Esto produce datos inconsistentes entre el servidor principal y las réplicas.
-- Esta sentencia es SEGURA para replicación
INSERT INTO pedidos (cliente_id, total, fecha_pedido)
VALUES (1050, 340.00, NOW());
-- Esta sentencia es PROBLEMÁTICA en replicación basada en sentencias
INSERT INTO pedidos (cliente_id, total, fecha_pedido)
VALUES (1050, 340.00, SYSDATE());MySQL marca las sentencias que contienen SYSDATE() como inseguras para replicación basada en sentencias y emitirá advertencias en el log.
La opción --sysdate-is-now
Para evitar los problemas de replicación y el comportamiento impredecible de SYSDATE(), MySQL ofrece la opción de inicio del servidor --sysdate-is-now. Cuando se activa, SYSDATE() se comporta exactamente como NOW(), evaluándose una sola vez al inicio de la sentencia.
# En el archivo de configuración my.cnf
[mysqld]
sysdate-is-now=1Con esta opción habilitada, el ejemplo del SLEEP produciría valores idénticos para ambas funciones.
Muchos administradores de bases de datos habilitan esta opción por defecto en servidores de producción, especialmente cuando se usa replicación, para eliminar una fuente potencial de inconsistencias.
Manejo de NULL
Al igual que NOW(), SYSDATE() nunca devuelve NULL. Siempre produce un valor de fecha y hora válido. Las precauciones con valores NULL aplican cuando se combina con columnas que pueden ser nulas.
SELECT p.id, p.cliente_id,
TIMESTAMPDIFF(SECOND, p.fecha_pedido, SYSDATE()) AS segundos_transcurridos
FROM pedidos p
WHERE p.fecha_pedido IS NOT NULL
ORDER BY segundos_transcurridos ASC
LIMIT 5;| id | cliente_id | segundos_transcurridos |
|---|---|---|
| 87 | 1043 | 145 |
| 86 | 1042 | 148 |
| 85 | 998 | 105496 |
| 84 | 1010 | 278833 |
El filtro WHERE p.fecha_pedido IS NOT NULL previene resultados NULL en TIMESTAMPDIFF.
Combinación con otras funciones
SYSDATE() se puede combinar con las mismas funciones de extracción y formato que NOW().
SELECT SYSDATE() AS ahora,
DATE(SYSDATE()) AS fecha,
TIME(SYSDATE()) AS hora,
DATE_FORMAT(SYSDATE(), '%d/%m/%Y %H:%i:%s') AS formato_es;| ahora | fecha | hora | formato_es |
|---|---|---|---|
| 2025-07-15 14:32:11 | 2025-07-15 | 14:32:11 | 15/07/2025 14:32:11 |
Como regla general, a menos que necesites específicamente el comportamiento de evaluación en tiempo real de SYSDATE(), es preferible usar NOW(). Es más predecible, más eficiente (no requiere llamadas adicionales al sistema operativo) y segura para replicación. Reserva SYSDATE() para los casos puntuales donde la diferencia de comportamiento sea un requisito, como la auditoría de tiempos reales dentro de procedimientos.
En el siguiente artículo veremos DATE para extraer la parte de fecha de un datetime.
Escrito por Eduardo Lázaro
