texto:   A-   A+
eliax

Pregunta a eliax: ¿Qué es un Connection Pool en bases de datos?
eliax id: 9163 josé elías en ene 17, 2012 a las 12:08 AM (00:08 horas)
eliax - para mentes curiosasHoy quiero escribir un breve artículo para aquellos que se inician en el mundo de la informática (o incluso para aquellos ya con algunos años de experiencia pero que quizás no sabían del tema), pues es algo que toma mucha importancia a la hora de confeccionarse aplicaciones web para que escalen a miles o millones de usuarios.

El tema es qué es un Connection Pool en relación a bases de datos.

Antes de iniciar debo decir que la técnica de Connection Pools es algo que antes de la Era Web por lo general era conocido solo por unos cuantos expertos en bases de datos que desarrollaban aplicaciones que debían escalar con miles de transacciones por segundo (como por ejemplo, sistemas para manejar Bolsas de Valores, Reservaciones Aéreas, etc).

Recordemos que antes de la web la mayoría de los sistemas eran del tipo Cliente-Servidor (y algunos cuantos multi-tier), y por lo general para una cantidad limitada de usuarios en una LAN en donde se tenía un buen control sobre el acceso a dichas aplicaciones, y el tema de demasiadas conexiones a bases de datos no era muy problemático.

Sin embargo, con la llegada de la web, cualquier página en Internet está expuesta potencialmente a decenas o cientos de miles de pedidos de usuarios simultáneos, por lo que el tema de Connection Pools toma mucha relevancia.

Pero, ¿qué es Connection Pooling y cuál es el problema que resuelve, y cómo lo resuelve? Pues veamos primero el problema...

Imaginen que tienen una base de datos a la cual han conectado una página web de ventas de productos, y que de repente la página se vuelve popular y los usuarios empiezan a hacer pedidos en masa.

Al inicio todo estará color de rosa, pero eventualmente, conforme aumenta la demanda en la base de datos, llegaremos a un punto bastante conocido por aquellos que programan sistemas web sin conocer este tema: El famoso error de "demasiadas conexiones a la base de datos".

El problema es que las bases de datos tiene un gran Talón de Aquiles del cual asombrosamente una gran cantidad de desarrolladores parece desconocer: Crear una conexión es un proceso extremadamente caro (en términos de recursos de hardware) en comparación a hacer simples queries.

Ese problema no se hace evidente en la etapa de desarrollo de un sistema ya que por lo general el sistema lo desarrollan un puñado de personas, por lo que el impacto en la base de datos es mínimo.

Sin embargo, en el momento que le pedimos a una base de datos (cualquier base de datos) que abra y cierre 1000 conexiones por segundo (o incluso por minuto), nos metemos en graves problemas...

Pero existe una solución bastante conocida entre expertos, y es bastante simple y sumamente efectiva, y como podrán adivinar es el tema de Connection Pools, que no es ni una tecnología ni un producto, sino que más bien una técnica, que se implementa en casi cualquier entorno de programación.

La idea es la siguiente: En vez de crear y destruir una conexión cada vez que un usuario la solicite, hagamos algo diferente. Vamos a mantener un grupo (o "pool") de conexiones (de ahí el nombre "Connection Pool"), con un número fijo de conexiones siempre abiertas y conectadas a la base de datos. Esas conexiones jamás se cerrarán.

Eso de inicio resuelve el problema de uno tener que abrir y cerrar conexiones constantemente y aumenta el rendimiento de la base de datos tremendamente.

Pero, ¿y qué pasa si se conectan más personas a la base de datos que el número de conexiones que poseemos?

Pues acá entra la segunda parte de la solución que ofrece esta técnica... A simple vista aparentaría que la solución es crear más conexiones, pero eso no resuelve el problema, y al contrario, nos regresa eventualmente al mismo problema de antes, e incluso al largo plazo lo empeoraría ya que utilizaríamos tantos recursos fijos que el CPU, la memoria y el bus del servidor estarían constantemente bajo tensión hasta que la máquina se arrodille y pida piedad.

Entonces, lo que se hace en realidad es que ese grupo de conexiones (que por lo general es bajo, pero depende del hardware y software de la aplicación, pero asumamos que son 20 conexiones) se recicla constantemente.

Y ese reciclaje es el gran truco de esta técnica, y funciona de esta manera: Cada vez que un usuario entra en sesión con la aplicación, y desea hacer una operación que requiera de un query a la base de datos, lo que ocurre es que un Database Connection Manager (en esencia, un intermediario entre tu código y la base de datos) te presta una conexión.

Cuando obtienes tu conexión prestada (en esencia, obtienes una referencia a la conexión), puedes hacer todos los queries que deseas para ese pedido en particular del cliente, pero (y esta es una parte muy importante) en el momento que termines de hacer los queries tu devuelves la conexión al Manager.

El Manager en ese momento etiqueta la conexión que le devolviste como "disponible para ser prestada a alguien más", y repite el proceso. En esencia, el Manager vive en un loop infinito prestando conexiones y recibiendo conexiones devueltas, pero (y no olviden esta parte) el Manager nunca cierra esas conexiones o abre nuevas (salvo la excepción de que por diseño del Manager se creen nuevas conexiones dinámicamente para ponerlas en el pool, pero ese ya es otro tema concerniente al diseño de este tipo de objetos).

Pero, ¿y por qué funciona esto de tener solo 20 conexiones recicladas mejor que el tener por ejemplo 200 conexiones constantemente abriendo y cerrando? Pues por la sencilla razón de que como les mencioné anteriormente, el abrir y cerrar conexiones es un proceso muy costoso, por lo que en la práctica es mejor reciclar 20 conexiones que abrir y cerrar 200.

Sin embargo, esa no es la única razón por la cual este tipo de soluciones se utiliza mucho para escalar. Otra gran ventaja de esta técnica es que no hace que la aplicación se caiga (o que se haga mucho más difícil que caiga). Me explico a continuación...

En el modelo tradicional de abrir y cerrar conexiones, en el momento que no existen más conexiones lo que sucede es que si se llega a un límite, la aplicación se tranca ya que no puede seguir más, y vemos los famosos errores de límites de conexiones, pero en el modelo de Connection Pooling, los pedidos se ponen en una cola (en esencia, un Queue tipo FIFO - el primero que entra, sale), lo que significa que si las 20 conexiones están prestadas actualmente que un nuevo pedido de un usuario por la web no causará un error, sino que simplemente una pequeña espera de unos cuantos milisegundos (o quizás algunos segundos) mientras el Manager espera que alguien más le devuelva una conexión para prestártela a ti.

Esa espera se puede medir en promedio, y es a propósito una manera para en sistemas en producción uno poder afinar el valor de la cantidad de conexiones en el pool.

Algo que es importante también que sepan es que hoy día la mayoría de los entornos modernos de programación (como Java Enterprise Edition, Adobe ColdFusion, el Microsoft .Net, etc) ya hacen esto tras bastidores por ti (hasta cierto punto, siendo ColdFusion quizás el mejor ejemplo en donde uno literalmente no hace nada y todo ocurre transparentemente para el programador), y es esta transparencia la razón por la cual quizás muchos desconozcan el tema, pero es bueno saber siempre lo que ocurre "tras bastidores" pues armados con este conocimiento de hoy ustedes podrán posiblemente diagnosticar en un futuro que el problema de escalabilidad sea tan sencillo como implementar un Connection Pool, o si existe uno el de disminuir o incrementar la cantidad de conexiones fijas.

En nota relacionada, este artículo lo escribí debido a mi decepción de que aun con todos estos años, PHP no soporta todavía esta técnica, razón por la cual no es factible utilizarlo "de caja" para aplicaciones que necesiten escalar masivamente.

Pero antes de que comenten y digan lo contrario sobre PHP, noten que la modalidad de conexión por pconnection en realidad no es lo mismo que esto, ya que no soporta transacciones ACID debido a una limitación de PHP mismo, por lo que en la práctica solo es útil para hacer lecturas a bases de datos y no escrituras.

Así mismo Oracle tiene una manera de implementar Connection Pools con su base de datos, pero es propietaria y requiere modificar el código estándar de PHP para que funcione. Y si preguntan de empresas como Facebook, Google, Yahoo y Amazon que utilizan PHP de alguna forma u otra, estas empresas también debieron romper con la estandarización de PHP para crear sus propias soluciones de Connection Pools y poder hacer escalar a PHP.

En cuanto a soluciones NoSQL, lamentablemente aun no existe estandarización, por lo que por ese lado también estamos en el aire con PHP. Mientras tanto sin embargo, prácticamente toda otra plataforma moderna de programación web soporta esta metodología, por lo que no olviden leer al respecto en sus plataformas de programación favoritas y de cómo tomar ventaja de ellas...

Actualización: Quiero agregar que esta técnica de reutilizar una conexión en realidad es un patrón de programación más generalizado que el ejemplo de Connection Pools. En términos generales, un Connection Pool sería un sub-conjunto de un "Object Pool".

En un Object Pool, uno pre-instancia un grupo de objetos y después con un Object Manager (por lo general, siguiendo el patrón del Singleton) uno toma prestado y devuelve objetos al pool.

Esto es tan útil en cualquier dominio como lo es con bases de datos, ya que el instanciar objetos en cualquier lenguaje de programación es también un proceso costoso en términos de recursos de la máquina, mientras que tomar prestado un objeto no es más que pasar un objeto por referencia, que ocurre prácticamente de forma instantánea.

Esto es de especial utilidad para desarrolladores de video-juegos, que por lo general tiene código muy compacto y optimizado, y requieren del mayor rendimiento posible.

autor: josé elías

Comentarios

  • Gracias Eliax tu explicación fue muy fácil de entender, ahora me siento que se un poco más que ayer! Enhorabuena por el blog.

  • Jose, creo que con node.js se puede llegar a solucionar esto (en el caso del sesarrollo web).

    A propósito algún día hablanos sobre esta nueva tecnología, que sin duda será una de las mas utilizadas en el futuro de la web super dinámica.

    Saludos!

  • Hola

    Para PHP se puede utilizar los famosos aceleradores de PHP los cuales hay varios. La ventaja es que la página php se convierte en una aplicacion que reside en memoria siempre conectada a la BD.

    De esta forma no solo te ahorras las conexiones de bases de datos sino también la interpretación del código por cada visitante a tu sitio.

    Saludos

    • Mario,

      Recuerda que bajo este esquema de aceleradores (de los cuales a propósito Facebook proveyó uno a la comunidad no hace mucho), el problema es que el cuello de botella continúa siendo de tipo I/O (es decir, la base de datos), por lo que el problema continúa siendo el mismo.

      • Para eso esta Apache Cassandra

  • Los frameworks de aplicaciones web te permiten utilizar connection pools de forma transparente al programador. CakePHP para PHP o Ruby on Rails para Ruby, por dar un par de ejemplos...

    • Las conexiones múltiples en CakePHP si no me equivoco utiliza pconnections, que no permiten transacciones en el pool, por lo que no pueden ser utilizadas en entornos de producción que requieran transacciones ACID y Connections Pools a la misma vez (y eso se debe a que CakePHP está escrito en PHP mismo).

  • mmm, esto me va servir en algun tiempo,
    se agradece :)

  • Monten un iis y microsoft sql server y ya :P jajajajja

  • Es muy interesante artículo. Me gustaría comentarte que esto también se suele hacer con sesiones de usuarios, yo por ejemplo, lo he hecho con EMC Documentum, y la filosofía es idéntica a lo que comentas. Gracias

    • Y no solo sesiones: Todo sistema operativo y miles de programas utilizan el patrón de "Object Pools" para lograr lo mismo con objetos, con el fin de no tener que instanciar objetos y solo reutilizarlos que es más eficiente en muchos casos.

  • ... preciso nuevamente...
    Pronto llegaré los utilizaré ;)

  • La verdad que me sorprendió mucho el artículo, no por el contenido en si, sino porque desconocía que hubiera tanta gente que se dedica a programar sin este conocimiento tan básico.

    Me alegra que aportes esta información para aquellos que programan y la desconocían. Pero repito, estoy muy sorprendido, ya que todo programador cuando aprende a acceder a una base de datos aprende dos cosas: lo primero que se aprende es a realizar una conexión y desconexión básica con la base de datos y la segunda es a manejar un Connection Pool, si hay gente que se dedica a programar sin saber qué es un Connection Pool, pufff... que mal vamos...

    • La programación es un campo extremadamente amplio. Y lo que tratamos es no reinventar la rueda, me explico, claro que todos saben que esa entidad llamada Conection Manager me da sesiones contra bbdd, pero no necesitamos saber exactamente por qué existe, o más importante aún, cómo funciona.

      Eso sí, si conoces su funcionamiento interno te da la posibilidad de dar soluciones parecidas a problemas aparentemente distintos.

      • Y no solo eso, muchas personas son simplemente autodidactas, que aprendieron a programar base de datos por pura experimentación, y que al pasar los años requirieron a manuales de SQL sin saber que quizás había más que aprender que solo SQL.

        Yo personalmente he conocido a verdaderos expertos en SQL que desconocían de este tema de los pools, la razón siendo que en el ambiente en donde trabajaban nunca les era necesario saber al respecto.

      • En este caso difiero bastante en algunos puntos.

        Defiendo totalmente la idea de que la gente se sienta atraída por ciertos conocimientos y sea autodidacta para aprenderlos. Esas personas son gente curiosa y requiere un grado de esfuerzo mayor para aprender ciertas cosas con unos medios inferiores de los que tienen otras personas. Pero hay que ser realista y llamar las cosas por su nombre.

        Estoy de acuerdo que la programación es un campo extremadamente amplio, lo podemos equiparar a la medicina, campos que siempre van agrandándose cada vez más en el tiempo y nunca tendrán un fin. Estamos de acuerdo que un médico nunca va a tener unos conocimientos sólidos en todas las materias, es decir, un cirujano del corazón seguramente no sabría operar un riñón, porque invierte todo su tiempo en especializarse en su pequeño campo de la medicina que es el corazón. Pero ese cirujano del corazón y todos los médicos tienen algo en común, y es la medicina general, que tienen que tener absoluto conocimiento de ella.

        En informática ocurre lo mismo, hay cientos de ramas de las cuales es imposible especializarse en todas, se tienen conocimientos generales de muchas de ellas y te especializas en unas pocas. Pero al igual que el médico, todo informático tiene que tener unos conocimientos básicos que tiene que saber si o si.

        ¿Por qué digo esto?, simplemente para que la gente no se lleve a engaño. Yo animo a todo el mundo que sea autodidacta y aprenda de todo en la vida. Pero al igual que todos sabríamos curarnos una herida y no nos ponemos el sobrenombre de médicos. Una persona por el mero hecho de tirar líneas de código para crear aplicaciones, no se puede considerar informático o programador.

        Me agrada que Eliax haya expuesto en su página un artículo dedicado a las conexiones con las bases de datos, siempre es bueno que gente autodidacta aprenda cosas nuevas. Ahora... llamemos las cosas por su nombre. No digamos que existen programadores que desconocían qué era un Connection

        • Difiero en lo último, quien alguna vez en su vida llevo una base de datos (aunque sea en Access), sabe lo que es una conexión. Pero personalmente, en la escuela jamás tuvimos la necesidad (y eso creo que se debe también a la poca preparación de los maestros) de usar un Pool, me entere tiempo después que existía pero no tenía ni idea de en que "casos se usaba" o por que era "bueno usarlo".
          Si comparas un médico con un programador escolarizado, por supuesto, el médico sabe como curar una herida, y quizá pueda dar algún tipo de diagnostico del corazón, pero mediante su experiencia puede aprender más cosas e incluso comprender que tipo de medicamento funciona mejor que otros, o la combinación de ambos.
          Hay cosas que se aprenden en el campo de acción, en la experiencia.|

  • En la actualidad desarrollo en java y postgresql utilizando un connection spool no lo he probado a gran escala pero las prueba que he realizado demuestran que sin connection spool es mucho mas lento y el postgresql se satura mas...

    • Exacto. Una buena prueba es ver el contador del CPU cuando se abren unas cuantas conexiones, versus cuando simplemente se toman prestadas las conexiones. Es una diferencia del cielo a la tierra.

  • Eliax, excelente artículo.

    Tengo aquí el patrón del Singleton que lo he utilizado para crear conexiones a Bases de Datos.

    Al final para cada solicitud del usuario solo tomo la instancia del objeto de conexión.

    ¿Así que mi pregunta es, que tan eficiente es que todos los usuarios estén conectados con el mismo objeto de conexión, o porque tienen que poner (20) conexiones? ¿Afecta el rendimiento tener una conexión para todos los usuarios?

    • Creo que usando un singleton para ese proposito puedes tener problemas con los datos.

      Date cuenta que es la misma instancia para todo el mundo. Deberías comprobar (suponiendo que no lo has hecho ya) con dos máquinas accediendo exactamente al mismo tiempo solicitando datos distintos usando el mismo singleton.

      Perdona que me entrometa en el comentario, pero tuve problemas con esa técnica hace un tiempo y lo pasé mal. Saludos

      • Tienes razón en lo que dices,

        Hay que saber como implementar los patrones, el patrón del Singleton a mi me ha funcionado muy bien, en las aplicaciones que he construido.

        No se puede implementar el Singleton para todo, pero para un objeto que van a usar todos, como una conexión. Todos van a usarla, mientras sea la misma aplicación.

        Por eso una caracteríztica es garantizar que una clase sólo tenga una instancia y proporcionar un punto de acceso global a ella.

        A esto me refiero.
        Mas no se que tan practico sea con millones.

      • En realidad, para crear un Connection Manager es precisamente un Singleton que generalmente se utiliza.

        Notemos que el Singleton es accedido muy brevemente y que siempre reside en memoria, por lo que es bastante eficiente.

        Notemos además que nada evita tener más de un Connection Manager (en esencia, varios Singletons numerados) si la situación lo amerita, en donde cada uno de ellos maneja un rango de conexiones, aunque esta es la excepción más que la regla.

        • Pienso que lo único que al acceder miles de peticiones al mismo objeto de conexión, se tiene que hacer una cola de atención en el server.

          Aunque realmente si es muy eficiente, y me imagino cuando las Computadoras Quanticas ya sean comunes en servidores, será algo excepcional que todos puedan acceder al mismo objeto al "mismo" tiempo, eso estará mas que genial.

          Tal como nos lo has enseñado en tus muy excelentes artículos que has publicado, y me he aprendido mucho de ellos (Y).

    • Efectivamente, como dice Eliax, en los pool de conexiones se utiliza el patron singleton.

      Otra cosa es que si tu te programas tu pool de conexiones, implementes de forma menos eficiente dicho patrón. Por ello, y como he leido en otro mensaje, no vamos a reinventar la rueda, los servidores de aplicaciones ya tienen implementados sus pool de conexiones para que los utilicemos sin necesidad de implementarlos de nuevo.

      Si realmente te interesa aprender, te animo a que implementes tu propio pool de conexiones únicamente con fines didacticos, ya que como he dicho antes, existen implementaciones de terceros muy eficientes.

  • Muy buen artículo, muy digerible, fácil de entender. Ahora podré explicar en palabras simples todo un asunto, que me parecía más complejo xD

  • gracias, el tema es genial ya que habla del rendimiento. Pero me preguntaba, si llegara a crear una apliacion con Connection Pool, Existen tecnicas o herramientas con las que la puedan poner a prueba??

  • Hola, fascinado con este articulo, ya que estoy estudiando el implementar una tiendecita online y estoy comenzando a estudiar prgramación php básica para hacer una web dinamica. Sé que hay varias webs que venden plantillas ya preparadas, pero como tu indicas a mi personalmente tambien me interesa saber que ocurre tras bastidores.
    Sería interesante que pudieses sacar de tu ajustado tiempo una sección dedicada a truquillos de programación.
    Un Saludo.

  • Yo también conozco algún experto de SQL que desconoce los pools. Pero no siempre va ligado el SQL a la programación. Existe mucha gente que simplemente se sienta delante de una aplicación cliente a lanzar sus sentencias SQL para interactuar con la base de datos. Para ellos es transparente lo que dicha aplicación hace para comunicarse con la base de datos, su labor no es crear esas conexiones, simplemente introducir o extraer información de la base de datos a través del SQL, no es necesario que tenga dicho conocimiento, su conocimiento tiene que basarse en crear sentencias SQL óptimas para que el rendimiento de la base de datos no se vea mermado.

    Ahora... si una persona se dedica a programar accesos a la base de datos y desconoce los pools de conexiones, esa persona nunca se le puede considerar experto.

  • No creo tener respuesta a tu pregunta, pero abro un poco el tema a ver si la gente se anima y aprendo yo también :)
    que el pooling en php de mysql suele ser el primer cuello de botella de rendimiento!

    Debido a cómo trabaja Apache, un pool de conexiones con php no parece tener mucho sentido, debido a la arquitectura, salvo que quieras hacer un pool en el mismo hilo y sus subhilos. En este caso singletons u otra cosa por el estilo.

    Por lo poco que sé, se suele desplazar este problema al servidor como hace Oracle con su DRCP o utilizar algo intermedio tipo memcached o algún msyql proxy. También se puede cambiar a fastCGI con php ya que mantiene el proceso en memoria.


    Un par de links interesantes sobre rendimiento asociado a LAMP:
    http://www.mysqlperformanceblog.com/2006/11/12/are-php-persistent-connections-evil/
    http://andigutmans.blogspot.com/2006/10/php-and-database-connection-pooling.html
    http://highscalability.com/bunch-great-strategies-using-memcached-and-mysql-better-together
    Solución de oracle:
    http://blogs.oracle.com/opal/entry/highly_scalable_connection_poo

  • hola, gracias por el articulo, tengo la siguiente duda, si un pool de conexiones se detiene, mediante codigo, o se muere por alguna razon, que sucede con las transacciones en el? se eliminan, se preservan hasta que vuelva a estar disponible? se realiza un rollback cuando esto pasa? gracias de antemano

    • Dentro del Pool Manager no hay transacciones, las transacciones las crea y destruye quien toma prestado la conexión.

      Si por alguna razón el objeto Pool Manager muere, lo único que pasaría es que no podrías tomar prestadas o devolver conexiones, pero tendrías tiempo de hacer Commit o Rollback, pero obviamente debes diseñar tu aplicación de modo que detecte la inexistencia del Pool Manager...

  • Simplemente Gracias, Mi líder de proyecto me mando este enlace con el asunto:

    Bonita definición sobre un Pool Connection.

    Gracias!

  • Añadir Comentario

    tu nombre
    tu email
    (opcional)
    web personal
    (opcional)
    en respuesta a...
    comentario de caracteres máximo
    3 + 6 = requerido (control anti-SPAM)
     

    "Interesante en extremo..!

    Sería fascinante poder compartir tu consciencia de esa forma con otra persona..
    "

    por "Nestor Sanchez" en dic 21, 2010


    en camino a la singularidad...

    ©2005-2014 josé c. elías
    todos los derechos reservados
    como compartir los artículos de eliax