{ "info": { "author": "Ivan Zhang", "author_email": "sail4dream@gmail.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "# django_db_pooling\nA patch to enable Django database connection pooling with gevent Gunicorn \nworkers.\n\n### Usage Guide\n\n1. `pip install django_db_pooling`\n1. in wsgi.py: \n\n import os\n import pymysql\n from django.core.wsgi import get_wsgi_application\n from django_db_pooling import pooling\n\n pymysql.install_as_MySQLdb()\n\n os.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"xxxxx.settings\")\n\n application = get_wsgi_application()\n\n pooling.set_pool_size(4)\n pooling.apply_patch()\n\n1. set [`conn_max_age`](https://docs.djangoproject.com/en/dev/ref/settings/#conn-max-age) \nto a value larger than 0 and less than MySQL's `wait_timeout`, e.g 60 seconds is usually\na good enough value.\n\n\n### How it works\n\nThe connection pool patches the `__getitem__` method of \n`django.db.utils.ConnectionHandler` in such a way so that the db connection\n can be reused across multiple requests/green-lets until `conn_max_age` is\n reached.\n\nBy default, Django manage the database connection object in a thread local \nattributed `_connections` in `django.db.utils.ConnectionHandler` so that\neach thread has its own database connection object to avoid race condition.\nIt also allows reuse of database connection by specifying a positive value or\nNone on `conn_max_age` setting to avoid initiating and releasing connection \nfor each request. However, it leads to problem when used with the gevent worker\nin Gunicorn where the thread local attribute is patched by a green-let local \nattribute: if a green-let is not reused, the database connection object\nassociated with green-let will not be released or recycled until it is garbage\ncollected or closed by MySQL. Under a medium or heavy load, those idle \nconnections may accumulate and the connection limit of MySQL is finally reached\nso that no more new connection can be established.\n\nTo solve the above issue, this patch adds a non-local attribute \n`connection_pool`. It is a dictionary with keys being the connection alias name \nand values being a list of pooled connection objects. Whenever a new request \nstarts, connection object in the pool will be reused if there is any or else new \nconnection object is created. The connection object will be bound to the \n`_connections` attribute to associate with the current request. Underlying \nconnection is closed and reopened if the `conn_max_age` is reached. When current \nrequest finishes, the connection object will be recycled to the pool if pool still\nhas capacity, which is set by the method `set_pool_size()`(default to 1 if not \nspecified). Otherwise the connection object will be freed and the underlying \nconnection is closed immediately.\n\nUnder extrem heavy load , it might be a good idea to restrict the concurrency per \nworker in Gunicorn \n([--worker_connections](http://docs.gunicorn.org/en/stable/settings.html#worker-connections))\nto ensure the overall concurrent database connections are less than the maximum \npermitted simultaneous connections in MySQL \n([--max_connections](https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_connections)).\nAlternatively, the `set_pool_size()` method accepts an additional argument \n`max_outstanding`(default to `None` which means unlimited) to limit the maximum concurrent connections per worker basis.\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/zhangi/django_db_pooling", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "django-db-pooling", "package_url": "https://pypi.org/project/django-db-pooling/", "platform": "", "project_url": "https://pypi.org/project/django-db-pooling/", "project_urls": { "Homepage": "https://github.com/zhangi/django_db_pooling" }, "release_url": "https://pypi.org/project/django-db-pooling/0.0.3/", "requires_dist": null, "requires_python": "", "summary": "Django Database Connection Pooling with Gevent workers", "version": "0.0.3" }, "last_serial": 4819310, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "181b38b38d85f5e5019fa0f23f1bc9bd", "sha256": "35f9369e428f0da54dae2deddf610e31cfe5f144bc14632373e1c00bab0c3e16" }, "downloads": -1, "filename": "django_db_pooling-0.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "181b38b38d85f5e5019fa0f23f1bc9bd", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 2318, "upload_time": "2018-10-10T04:13:31", "url": "https://files.pythonhosted.org/packages/3b/73/c1fcd2e5abb448b6552509bba3329ce00e5105989638bc6820d287e70e6e/django_db_pooling-0.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a0213dff5bf3e7227da0c47cd3d37076", "sha256": "9eedd8b32a2432ea71a64689eee97783a880058b85a14c6b1c8a58b197a519b5" }, "downloads": -1, "filename": "django_db_pooling-0.0.1.tar.gz", "has_sig": false, "md5_digest": "a0213dff5bf3e7227da0c47cd3d37076", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1714, "upload_time": "2018-10-10T04:13:33", "url": "https://files.pythonhosted.org/packages/dd/5e/951fde5af7a2e06ffcd8811b453702916b2e8328ccb7e432c971ae55c8fc/django_db_pooling-0.0.1.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "f77dd557b97d2b3c6cada342ae1e5818", "sha256": "31044783e0b2dd0657d7e573dca4d82012109536b6fdb57ae3c27c1e62c24b3d" }, "downloads": -1, "filename": "django_db_pooling-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "f77dd557b97d2b3c6cada342ae1e5818", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 3587, "upload_time": "2019-02-08T04:59:57", "url": "https://files.pythonhosted.org/packages/93/c4/3fbb4ffe4355a6046a6ce1d0d862f3b4646ff672dd751e08abe6c990f3cc/django_db_pooling-0.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "40807d3d49187cbb6243ca7fafdcd87a", "sha256": "15e06a6aed5a8dc3a57d1d7a397725293b1e2dd2f39d56d2193099842a7651d1" }, "downloads": -1, "filename": "django_db_pooling-0.0.2.tar.gz", "has_sig": false, "md5_digest": "40807d3d49187cbb6243ca7fafdcd87a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3241, "upload_time": "2019-02-08T04:59:59", "url": "https://files.pythonhosted.org/packages/20/16/89bdea22c773ffea33128d42701eab64401d8f72288f69693f925a36b451/django_db_pooling-0.0.2.tar.gz" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "e912a70b81819cba766d588a7d4a009e", "sha256": "4355fdebffc5fe5408291a9fc57287cb80d7758588dd8695305fb93279490df5" }, "downloads": -1, "filename": "django_db_pooling-0.0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "e912a70b81819cba766d588a7d4a009e", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 4238, "upload_time": "2019-02-14T08:23:02", "url": "https://files.pythonhosted.org/packages/ce/9e/7775c157737aaf14922e7e7598a546c9ff10d07057dd1aa61f051a0f90b4/django_db_pooling-0.0.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "6bef9b07e019b6f07c6b92e4fc6e7309", "sha256": "db910e1883019d1bbde886ec31c837686948a4d32107d19be647fcba7fd8f3b1" }, "downloads": -1, "filename": "django_db_pooling-0.0.3.tar.gz", "has_sig": false, "md5_digest": "6bef9b07e019b6f07c6b92e4fc6e7309", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3843, "upload_time": "2019-02-14T08:23:04", "url": "https://files.pythonhosted.org/packages/41/00/9ab514e2b65768bf49709082934b4746d67f469436b24ee736e6c965d636/django_db_pooling-0.0.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "e912a70b81819cba766d588a7d4a009e", "sha256": "4355fdebffc5fe5408291a9fc57287cb80d7758588dd8695305fb93279490df5" }, "downloads": -1, "filename": "django_db_pooling-0.0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "e912a70b81819cba766d588a7d4a009e", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 4238, "upload_time": "2019-02-14T08:23:02", "url": "https://files.pythonhosted.org/packages/ce/9e/7775c157737aaf14922e7e7598a546c9ff10d07057dd1aa61f051a0f90b4/django_db_pooling-0.0.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "6bef9b07e019b6f07c6b92e4fc6e7309", "sha256": "db910e1883019d1bbde886ec31c837686948a4d32107d19be647fcba7fd8f3b1" }, "downloads": -1, "filename": "django_db_pooling-0.0.3.tar.gz", "has_sig": false, "md5_digest": "6bef9b07e019b6f07c6b92e4fc6e7309", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3843, "upload_time": "2019-02-14T08:23:04", "url": "https://files.pythonhosted.org/packages/41/00/9ab514e2b65768bf49709082934b4746d67f469436b24ee736e6c965d636/django_db_pooling-0.0.3.tar.gz" } ] }