sql >> Database >  >> RDS >> PostgreSQL

Lopen cursors in Django binnen de open transactie?

Ik geloof dat je een aparte db-verbinding nodig hebt om een ​​afzonderlijke, gelijktijdige transactie te krijgen. Ik ben er ook vrij zeker van dat django slechts één verbinding per database beheert. Maar je zou er nog een kunnen maken. Er kan een goede reden zijn om dit niet te doen. Complexiteit komt voor de geest.

Ik denk dat zoiets als dit zou werken:

from django.conf import settings
from django.db.utils import ConnectionHandler

def my_view(request):
    """Flirt with complexity by using two connections to db"""
    private_connections = ConnectionHandler(settings.DATABASES)
    db = router.db_for_write(model)
    new_conn = private_connections[db]
    new_conn.enter_transaction_management()
    new_conn.managed(True)
    new_cur = new_conn.cursor()
    new_cur.execute("INSERT INTO ...")
    new_conn.commit()
    new_conn.close()

Merk op dat u django.db.transaction . niet kunt gebruiken omdat het werkt op de globale verbindingsinstanties in django.db.connections , maar in ieder geval is dat slechts een dunne wikkel rond de transactiebeheermethoden op het verbindingsobject.

Ik denk dat de echte vraag is waarom wil je dit doen?! En wat is er mis met het antwoord van Lakshman Prasad? U kunt vastleggen/terugdraaien wanneer u maar wilt, dus niets verhindert u om verschillende taken in verschillende transacties binnen één weergave uit te voeren. Het feit dat de transacties parallel moeten zijn en niet opeenvolgend, duidt op een logisch verband ertussen, wat naar mijn mening erop zou wijzen dat ze echt in dezelfde transactie zouden moeten zijn.

Als u daarentegen gewoon een soort offline verwerking probeert te emuleren, waarvan het succes of falen helemaal niet relevant is voor de weergave, overweeg dan om een ​​berichtenwachtrij op te zetten en deze invoegingen in een aparte werkwijze. Selderij is een populair pakket om precies dat te doen. Als responstijd echter geen groot probleem is, denk ik nog steeds dat opeenvolgende transacties voldoende moeten zijn.

Bijwerken:

Als u wilt dat uw door de database ondersteunde cache in autocommit-modus werkt terwijl uw bedrijfslogica nog steeds in een enkele (afzonderlijke) transactie wordt uitgevoerd, is er een django-manier. Het enige dat u hoeft te doen, is ervoor zorgen dat de caching buiten plaatsvindt de commit_on_success :

  • Als u alleen de caching-middleware gebruikt, zorg er dan voor dat deze zich buiten de TransactionMiddleware bevindt .

  • Als je caching view-decorators gebruikt, zou ik durven raden dat je TransactionMiddleware zou kunnen uitschakelen (of plaats de probleemweergave in een autocommit decorateur) en gebruik de commit_on_success binnenhuisarchitect binnen de cache-decorateur. Het ziet er grappig uit, maar ik weet niet waarom het niet zou werken:

    @transaction.autocommit
    @cache_page(500)
    @transaction.commit_on_success
    def my_view(request):
        "..."
    
  • Als u sjablooncaching gebruikt of meer betrokken handmatige caching doet, kunt u TransactionMiddleware ook uitschakelen (of plaats de probleemweergave in een autocommit decorateur) en gebruik commit_on_success als contextmanager om alleen de code die u nodig hebt in een beheerde transactie te plaatsen, terwijl de rest van de weergave in autocommit blijft.

    @transaction.autocommit
    def my_view(request):
        data = cache.get(some_key)
        with transaction.commit_on_success():
            context = do_some_processing(data)
        cache.set(some_key, context['data'])
        return render('template/with/cache/blocks.html', context=context)
    


  1. Django bulk_create met negeerrijen die IntegrityError veroorzaken?

  2. Kan ik met MySQL Connector/J meerdere query's uitvoeren, gescheiden door puntkomma's?

  3. Verbinding instellenZwembad crasht Slick 3.0

  4. Voorwaardelijke WHERE-clausule in SQL Server