Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > MySQL
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 09-06-2016
Avatar de darkerbyte
darkerbyte darkerbyte is offline
Miembro
 
Registrado: feb 2005
Posts: 196
Poder: 20
darkerbyte Va por buen camino
Unhappy Que tan confiable es MySQL

Saludos estimados colegas.

Estoy muy agradecido con todos los compañeros que hacen posible este foro, la verdad he aprendido muchísimo de ustedes.

Pues estoy atorado en un problema. Tengo un sistema de Punto de Venta, en el cual mi cliente ha tenido serios problemas ya que tenemos diferencias de existencias en sus inventarios.
Ya me volví loco haciendo cientos de pruebas de escritorio, sin embargo no he logrado que el programa me genere un solo error y al cliente en cambio, le generan múltiples errores.

Ya he revisado mi código, trazado los procesos una y otra vez, revisado las consultas que se mandan al servidor, etc.

Y me estaba preguntando si mi problema será quizá que no estoy usando la versión oficial de MySQL sino la que viene modificada en WAMP (http://www.wampserver.com/en/)
O quizá los controles del Delphi. Aquí pongo lo que estoy usando

WAMP 2.0 (MySQL 5.1.33, Motor InnoDB)
Delphi XE5
Zeos 7.1.4-stable

Disculpen si mi pregunta es hasta cierto punto ingenua, solo quisiera con la experiencia de ustedes descartar cualquier posibilidad.


El código que envío para registrar una venta es así, tengo una tabla de productos con un campo llamado 'Existencia', el sistema
conforme vende tiene que ir descontando. Pero hay veces en las que no hace el descuento de las piezas vendidas.

Código SQL [-]
START TRANSACTION;
INSERT INTO ventas(idVenta, fecha, hora, cliente, vendedor, turno, descuento)
                 VALUES (16, '2016-06-08', '22:19:12', 1, 2, 1, 0.00);
INSERT INTO ventas_partidas(idVenta, idProd, cantidad, precio_compra, precio_venta)
                  VALUES(16, 'PDE', 3.00, 29.00, 35.00);
UPDATE productos SET almacen=almacen-3.00 WHERE clave='PDE';   -- Esta instrucción es donde esta mi duda

Esto lo hago en un try, si se ejecuta correctamente envío una consulta con un "commit", de lo contrario envío "rollback"
Responder Con Cita
  #2  
Antiguo 09-06-2016
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is online now
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.021
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Efectivamente, si el cliente tiene problemas es por algún error en tu software, no lo dudes.
Debes ir físicamente al negocio de tu cliente, ver cómo trabajan, si hacen algo diferente a como lo haces tú en tus pruebas. Probar con su base de datos, etc.
Responder Con Cita
  #3  
Antiguo 09-06-2016
Avatar de newtron
[newtron] newtron is offline
Membrillo Premium
 
Registrado: abr 2007
Ubicación: Motril, Granada
Posts: 3.457
Poder: 20
newtron Va camino a la fama
¿Solamente haces ese proceso de inserción? ¿No hay modificaciones ni anulaciones?

Por otro lado, y por experiencia, te puedo decir que lo más sano es que los procesos para actualizar distintos campos a partir de inserciones, modificaciones o anulaciones en tablas de movimientos estén en triggers de la base de datos. De esa manera tendrás bastantes menos problemas.

Saludos
__________________
Be water my friend.
Responder Con Cita
  #4  
Antiguo 09-06-2016
Avatar de fjcg02
[fjcg02] fjcg02 is offline
Miembro Premium
 
Registrado: dic 2003
Ubicación: Zamudio
Posts: 1.408
Poder: 22
fjcg02 Va camino a la fama
Cita:
Empezado por newtron Ver Mensaje
Por otro lado, y por experiencia, te puedo decir que lo más sano es que los procesos para actualizar distintos campos a partir de inserciones, modificaciones o anulaciones en tablas de movimientos estén en triggers de la base de datos. De esa manera tendrás bastantes menos problemas.


Saludos
__________________
Cuando los grillos cantan, es que es de noche - viejo proverbio chino -
Responder Con Cita
  #5  
Antiguo 09-06-2016
bitbow bitbow is offline
Miembro
 
Registrado: jul 2006
Posts: 366
Poder: 18
bitbow Va camino a la fama
Solo por molestar un poco, de casualidad tu cliente maneja multiples puntos de venta (varios equipos con su soft atacando la misma base de datos), como gestionas esto?

Veo que en tus inserts no manejas un identificador para el punto de venta o terminal.

Saludos.
__________________
¡Ni como ayudarte Niño!!
bitbow
Responder Con Cita
  #6  
Antiguo 09-06-2016
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Otra buena practica es usar logs. En cada paso importante pones algo como

Cita:
Log.debug("Inv.Add", "id=16, date='2016-06-08', date='22:19:12', total=1"),
Y luego asi puedes evaluar posteriormente el flujo del proceso.

AUN mas confiable si haces el LOG *dentro* de la BD. Creas una tabla LOG y haces similar.

Si haces un Log *correcto*, deberias poder reconstruir con 100% de fidelidad los datos derivando SOLO del log.
__________________
El malabarista.
Responder Con Cita
  #7  
Antiguo 09-06-2016
Avatar de darkerbyte
darkerbyte darkerbyte is offline
Miembro
 
Registrado: feb 2005
Posts: 196
Poder: 20
darkerbyte Va por buen camino
Gracias Casimiro, si efectivamente estoy haciendo las pruebas que me comentas. Solo quería descartar cualquier otra posibilidad. Gracias por tu respuesta
Responder Con Cita
  #8  
Antiguo 09-06-2016
Avatar de darkerbyte
darkerbyte darkerbyte is offline
Miembro
 
Registrado: feb 2005
Posts: 196
Poder: 20
darkerbyte Va por buen camino
Question Triggers

Cita:
Empezado por newtron Ver Mensaje
¿Solamente haces ese proceso de inserción? ¿No hay modificaciones ni anulaciones?

Por otro lado, y por experiencia, te puedo decir que lo más sano es que los procesos para actualizar distintos campos a partir de inserciones, modificaciones o anulaciones en tablas de movimientos estén en triggers de la base de datos. De esa manera tendrás bastantes menos problemas.

Saludos
Hola Newtron.

Aprecio mucho tu tiempo para responder y por tu consejo.

Basicamente son 3 tablas. Una con el inventario de productos, una para registro de ventas y otra con el detalle de la venta. La situación es que solo hago inserts cuando se hace una venta.
Cuando se hace una devolución de algun producto o la cancelación de la venta solo marco el ID de la cancelación el que guardo en una tabla de cancelaciones y reintegro el producto al inventario.
No se si para estos casos es posible programar un trigger ya que se haría una modificación solo en una columna de la tabla. No soy muy experto en el tema de los triggers.
Responder Con Cita
  #9  
Antiguo 09-06-2016
Avatar de darkerbyte
darkerbyte darkerbyte is offline
Miembro
 
Registrado: feb 2005
Posts: 196
Poder: 20
darkerbyte Va por buen camino
Cita:
Empezado por bitbow Ver Mensaje
Solo por molestar un poco, de casualidad tu cliente maneja multiples puntos de venta (varios equipos con su soft atacando la misma base de datos), como gestionas esto?

Veo que en tus inserts no manejas un identificador para el punto de venta o terminal.

Saludos.
Si maneja multiples terminales, incluso manejamos sucursales vía internet.

No puse todos los campos de la tabla en la consulta que escribí arriba a fin simplificar mi ejemplo. La tabla de Ventas tiene como llave primaria (idSucursal, idVenta) ambas de tipo entero con la que identifico en que sucursal se realizó la venta. Claro, esta misma llave esta en la tabla ventas_det la cual tiene como llave primaria (idSucursal, idVenta, idProducto) siendo el ultimo de tipo string que es una llave foranea a la tabla de productos. La tabla de Ventas también tiene una columna llamada "idVendedor" con la que identifico que vendedor hizo la venta. No llevo un control por máquina ya que los vendedores pueden abrir multiples instancias del programa en diferentes computadoras usando su mismo id de usuario y estas ventas al hacerse el corte se filtran en base al vendedor que las realizó.

Para registrar la venta lo que hago es obtener el primero el siguiente folio y después genero la consulta (como la que puse arriba, mas menos productos).
Si ocurre un error (que se intentaran registrar dos ventas en el mismo instante y por ende el folio de la venta que llegó posterior está repetido) el sistema manda un rollback de la transaccion que fue rechazada, actualizamos el folio e intentamos registrarla nuevamente.

Estoy haciendo algo mal? quiza me pueden sugerir una mejor manera de hacer las cosas.

De verdad muchas gracias por sus comentarios
Responder Con Cita
  #10  
Antiguo 09-06-2016
Avatar de darkerbyte
darkerbyte darkerbyte is offline
Miembro
 
Registrado: feb 2005
Posts: 196
Poder: 20
darkerbyte Va por buen camino
Gracias mamcx

Tienes razón, voy a programar el log porque es un dolor de cabeza esto.
Responder Con Cita
  #11  
Antiguo 10-06-2016
bitbow bitbow is offline
Miembro
 
Registrado: jul 2006
Posts: 366
Poder: 18
bitbow Va camino a la fama
Ya que nos ampliaste la info sobre le problema lo único que queda son los logs y como indican los compañeros en sus comentarios, si el fallo lo tiene el cliente y tu no puedes replicarlo vuela al lugar del cliente (después de añadir logs por donde se te ocurra) y espera a ver el error.

Saludos.
__________________
¡Ni como ayudarte Niño!!
bitbow
Responder Con Cita
  #12  
Antiguo 10-06-2016
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Cita:
Empezado por darkerbyte Ver Mensaje
[...]tengo una tabla de productos con un campo llamado 'Existencia'
Código SQL [-]
START TRANSACTION;
INSERT INTO ventas(idVenta, fecha, hora, cliente, vendedor, turno, descuento)
                 VALUES (16, '2016-06-08', '22:19:12', 1, 2, 1, 0.00);
INSERT INTO ventas_partidas(idVenta, idProd, cantidad, precio_compra, precio_venta)
                  VALUES(16, 'PDE', 3.00, 29.00, 35.00);
UPDATE productos SET almacen=almacen-3.00 WHERE clave='PDE';   -- Esta instrucción es donde esta mi duda
1. ¿El campo se llama realmente Existencia o almacen?

2. Te recomiendo prescindir de valores literales en sentencias SQL de aplicaciones que no son de uso interno o de pruebas. Es mejor y más seguro usar parámetros ("...Values (..., :Cantidad..."). Quizá en la computadora del cliente 3.00 no sea lo que tú crees que es (configuración regional).

3. ¿Existe la remota posibilidad de que tengas dos productos con la misma clave?

4. ¿Tendrás algún disparador (trigger) involucrado con esas tablas y que no estés observando?

5. ¿Las diferencias inesperadas que se presentan son consistentes o varían sin sentido? ¿El error se presenta bajo un patrón común respecto a las cantidades que debería haber y las que hay?

Saludos misteriosos.
Responder Con Cita
  #13  
Antiguo 10-06-2016
Avatar de darkerbyte
darkerbyte darkerbyte is offline
Miembro
 
Registrado: feb 2005
Posts: 196
Poder: 20
darkerbyte Va por buen camino
Red face En revisión

Gracias Al González.

Siempre es bueno repasar lo básico, no es la primera vez que me pasa estar haciendo algo mal. Respecto a lo que me comentas

1. ¿El campo se llama realmente Existencia o almacen?
El campo se llama almancén, y lo uso para llevar la existencia. Me equivoqué al formular la pregunta.

2. Te recomiendo prescindir de valores literales en sentencias SQL de aplicaciones que no son de uso interno o de pruebas. Es mejor y más seguro usar parámetros ("...Values (..., :Cantidad..."). Quizá en la computadora del cliente 3.00 no sea lo que tú crees que es (configuración regional).
Aprecio el consejo voy a hacer los cambios para que sea por parámetros

3. ¿Existe la remota posibilidad de que tengas dos productos con la misma clave?
No, en la tabla de Productos la clave es llave primaria y el sistema hace una revisión antes de modificar o insertar nuevo producto.

4. ¿Tendrás algún disparador (trigger) involucrado con esas tablas y que no estés observando?
Gracias ya revisé. No tengo de momento triggers en esta parte.

5. ¿Las diferencias inesperadas que se presentan son consistentes o varían sin sentido? ¿El error se presenta bajo un patrón común respecto a las cantidades que debería haber y las que hay?
Varían sin sentido.


Por eso mi pregunta sobre la confiabilidad de MySQL. De hecho otro cliente tenía un problema parecido. A este cliente cuando hacía sus ventas en sus tickets (Impresión en RAW) y notas (hechas con QuickReport) los precios salían distintos a los que tenemos guardados en el sistema. Me volví loco haciendo pruebas, depurando una y otra vez las rutinas del programa. Ya desesperados le dimos formato a sus computadoras y problema solucionado. Aun sigo sin poder explicarme que fue lo que estaba pasando.

De momento estoy haciendo lo del Log que me han sugerido, estoy también haciendo revisión en las rutinas. Por último mi tirada es hacer pruebas para cambiar el servidor del 5.1 a 5.7.
Bueno, les mantendré informados que pasa. Gracias a todos por su tiempo y sus sugerencias
Responder Con Cita
  #14  
Antiguo 10-06-2016
bitbow bitbow is offline
Miembro
 
Registrado: jul 2006
Posts: 366
Poder: 18
bitbow Va camino a la fama
La realidad es que en mi experiencia personal MySql aunque recomendable para sistemas web, en sistemas de escritorio corre lento por lo que he optado por firebird y firebird llegando a usarlo solo cuando el cliente así lo requiere, además de que me he topado con que hay errores que no gestiona adecuadamente como que este mal la sintaxis y aún así compile los procedimientos (igual y es la versión), es verdad que es una base robusta con muchas funcionalidades en cuanto a seguridad, librerías, tipos de datos, etc pero prefiero firebird.
__________________
¡Ni como ayudarte Niño!!
bitbow
Responder Con Cita
  #15  
Antiguo 10-06-2016
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Cita:
Empezado por darkerbyte Ver Mensaje
Varían sin sentido.
Podrias dar un ejemplo de como varian? Como era antes (bueno) como es despues(malo) y como deberia haber sido?
__________________
El malabarista.
Responder Con Cita
  #16  
Antiguo 10-06-2016
Avatar de darkerbyte
darkerbyte darkerbyte is offline
Miembro
 
Registrado: feb 2005
Posts: 196
Poder: 20
darkerbyte Va por buen camino
Mamcx

El cliente me reporta que hacen una venta y los productos que ha vendido los cuales deberían haber sido descontados siguen apareciendo en existencia.
Por eso comenté que tenía mi duda al respecto con esta instrucción:

UPDATE productos SET almacen=almacen-3.00 WHERE clave='PDE'; --En este caso se vendieron 3 pzas del producto 'PDE'

Para cada producto que se vende se inserta la partida en la tabla de "ventas_det" y se hace el desconteo respectivo en la tabla de productos. Después de revisar el kardex veo que efectivamente tengo existencia de más del producto.
Esto es muy extraño porque el algoritmo genera las dos consultas, tanto para insertar como para descontar y lo hace dentro de una transacción y he probado cientos de veces, sin exagerar quizá miles de veces el procedimiento, tranzando paso a paso.
Igual al cliente no se lo hace en todas las ventas, ni en todos los productos.
He cuidado que las claves de los productos de los clientes no tengan símbolos especiales (comillas, asteriscos, etc). Para que no pudieran dar alguna falla en la consulta por el propio lenguaje de MySQL

Creo que es cosa del Chamuco, como decimos por acá.
Responder Con Cita
  #17  
Antiguo 10-06-2016
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is online now
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.021
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cita:
Empezado por darkerbyte Ver Mensaje
UPDATE productos SET almacen=almacen-3.00 WHERE clave='PDE'; --En este caso se vendieron 3 pzas del producto 'PDE'
Eso no son 3 piezas, sino 3.00
Responder Con Cita
  #18  
Antiguo 10-06-2016
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Conceptualmente es el problema que resuelve la contabilidad doble: Si no se conserva la historia y flujo de las transacciones se pueden generar errores (o fraudes).

El problema de fondo es que el manejo del estado de los datos normales en forma CRUD es *destructivo* y no hay manera de saber como se llego al resultado actual. Para un inventario, al igual que un libro contable - de hecho, un inventario es una forma especial de contabilidad- es mas solido usar un diseño inmutable (donde no se sobreescribe sino que se agregan los resultados).

Osea, un log.

Es mejor que el inventario sea asi:

Cita:
Feb1 - Ref:ABC BUY = Qty:1, Value:$10
Feb2 - Ref:ABC SELL = Qty:1, Value:$15
Feb3 - Ref:ABC BUY = Qty:10, Value:$20
Feb3 - Ref:ABC TRANSFER = Qty:10, Value:$20 TO Store: 2
Nota: Se registra luego de hacer las validaciones. Por eso, si no se permiten vender por debajo del stock, no saldran lineas con inventarios negativos. Osea, se registra solo un hecho real y concreto (en el pasado) y no lo que se va a hacer y que *puede* ser rechazado por la logica del negocio.


Y usar la tabla de inventarios como "cache" con el valor actual del stock (Asi que obvio tienes un campo Stock actual). Asi, teniendo la historia en forma de log, puedes tener claro como se movio el flujo del inventario.

Entonces, si hay un problema con un producto, puedes consultar tu log y ver en que momento se genero el problema.
__________________
El malabarista.
Responder Con Cita
  #19  
Antiguo 17-06-2016
Avatar de darkerbyte
darkerbyte darkerbyte is offline
Miembro
 
Registrado: feb 2005
Posts: 196
Poder: 20
darkerbyte Va por buen camino
Avance

Ya hice la complementación para generar un archivo log. Para cada procedimiento el programa guarda lo que el usuario tiene en pantalla y las consultas que el sistema envía al servidor. Ahora a dar un poco de tiempo para empezar a rastrear los archivos
Responder Con Cita
  #20  
Antiguo 08-10-2016
Avatar de darkerbyte
darkerbyte darkerbyte is offline
Miembro
 
Registrado: feb 2005
Posts: 196
Poder: 20
darkerbyte Va por buen camino
Exclamation Conclusión

Usando la idea de Mamcx agregué a cada procedimiento que "mete mano" a la base de datos un log de la información que tengo en pantalla junto con la consulta que está enviando a MySQL para serciorarme que no fuese un error de programación mío.

También implementé en el sistema un método para capturar el estado del inventario (screenshot) que almacena para cada producto
la existencia en cada sucursal junto con el costo del producto. Por supuesto se guarda también la fecha y hora de captura.

Mis clientes volvieron a tener problemas con las existencias de su inventario.
El día 4 estuve haciendo unas pruebas, hice una captura de inventario, el día 5 se registró un movimiento para dos productos
fue una única venta, en el archivo log esto es lo que tenía en pantalla:



Cantidad Clave Descripción Precio Unitario, importe

0.50 ; 520100106; ULTRAFONDO TRANSP. CATALIZABLE GRANEL; Menudeo; 85.50; 42.75 ;
0.50 ; 521101806; CATALIZADOR AL 100% P/ULTRAFONDO GRANEL; Menudeo; 84.50; 42.25 ;


Y aquí lo que se mandó al servidor
Código SQL [-]
START TRANSACTION;
INSERT INTO ventas VALUES (1,8126, '2016-10-05', '17:42:48', 1, 3,282,'',0, 0, 0, 0);
INSERT INTO pedidos VALUES(1,8126,'520100106',0,0.50,1,65.96,85.50);
INSERT INTO pedidos VALUES(1,8126,'521101806',1,0.50,1,65.01,84.50);
UPDATE productos set suc1=suc1-0.50 WHERE clave='520100106';
UPDATE productos set suc1=suc1-0.50 WHERE clave='521101806';
Commit;

El punto es este, pueden ver que en las dos ultimas lineas se resta de la existencia en la sucursal 1 [suc1(decimal(8,2)] la cantidad vendida 0.5
En el screenshot que hice de mi inventario tenía 9.70 piezas y después de esta venta tengo una existencia de 6.20 en el producto "520100106, ULTRAFONDO TRANSP. CATALIZABLE GRANEL"

Escribo el resultado de mis pruebas por si alguien más a futuro pasa por una situación similar. Versión de MySQL la 5.1.33


Voy a probar con otra versión de MySQL porque ya me volví loco haciendo debugs y probando cientos de veces el codigo fuente
o quizá me cambie a Firebird
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Alguién conoce una solución simple y confiable para la WebCam en Delphi ? rolandoj Gráficos 8 27-05-2013 10:53:56
Sincronizar BD MySQL Hosting con BD MySQL servidor local ivantech MySQL 3 09-03-2010 20:01:07
Componente confiable para pasar voz a texto!! JuanErasmo C++ Builder 1 06-05-2006 02:20:13
como conectarme remotamente mysql a mysql sakuragi MySQL 14 11-11-2004 16:04:46


La franja horaria es GMT +2. Ahora son las 11:13:46.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi