

Django でレコードの悲観ロックを実現しようと with transaction.atomic()
内で、select_for_update()を実行しましたが、レコードがロックされないです。  
コードは以下です

[code]

    @api_view(['GET', 'POST', 'PUT'])
    def Test(request):
    
      with transaction.atomic(using="test"):
        target_user = AdminUser.objects.select_for_update().get(id="test_user")
        target_user.name = "name"
        target_user.save()
    
      return Response({}, status=status.HTTP_200_OK)
    
[/code]

これらが実行されるときは、以下のようなsqlコマンドが実行されると思っていました

[code]

    BEGIN
    SELECT ***** FOR UPDATE
    COMMIT
    
[/code]

しかし実際は、以下のような実行ログとなりました

[code]

    SELECT ***** FOR UPDATE
    COMMIT
    
[/code]

バージョンに関して  
Django 3.2.12  
Python 3.6.15  
Mysql 5.7.41

何かしらの設定が抜けているなどあればご指摘いただきたいです。  
よろしくお願いいたします。

* * *

データベースエンジンにmysqlを利用しているのですが、django.db.backends.mysql には
BEGINを実行するコマンドがなく、django.db.backends.sqlite3 にはありました


CC BY-SA 4.0
2023-08-24T04:53:10.167
96031
2023-08-25T01:12:25.910
2023-08-24T08:13:45.450
59566
59566
question
python mysql django
Django：transaction.atomic によるトランザクション管理でBEGINコマンドが実行されず、select_for_update() でレコードのロックができない


以下のコードでトランザクションのカーソルにアクセスでき、sqlが実行できたのでBEGINしました。

[code]

    from django.db import transaction, connections
    
    with transaction.atomic(using="test"):
        connections["test"].cursor().execute("BEGIN")
    
[/code]

transaction.atomic() がどのようにトランザクションを開始しているかライブラリを読むと
django.db.transaction.get_connection で django.db.connectionsを呼び出しているのを確認。  
connections[using]でデータベースエンジンごとのDatabaseWrapperオブジェクトからcursorを使っているようだったので、自前のViewでもconnections[using]を使うと同じトランザクション内でsqlが実行できた。


CC BY-SA 4.0
2023-08-24T08:06:00.533
96034
2023-08-25T01:12:25.910
2023-08-25T01:12:25.910
3060
59566
96031
answer