33

私の問題は次のとおりです。

私は自動車ディーラー A と という名前の db テーブルを持っていますsold_cars。車が販売されている場合、このテーブルにエントリを作成します。

テーブルには という名前の整数列がありますorder_no。ディーラーが販売する車内で一意である必要があります。

したがって、ディーラー A が車aを販売bした場合c、この列は になります1, 2, 3。数値計算に穴を開けたくないので、主キーではなく、この列を使用する必要があります。ディーラー A と B (後で追加される可能性があります) には、A ではなく、1、2、3 の順序番号が必要です。 : 1, 3, 5, および B: 2, 4, 6. というわけでorder_no、指定されたディーラーの最後の最大値を選択し、1 ずつ増やして保存します。

問題は、2 人の人が同じミリ秒でディーラー A から車を購入し、両方の注文が同じになったことorder_noです。何かアドバイス?このプロセスをトランザクション ブロックで閉じ、トランザクションが完了するまでこのテーブルをロックすることを考えていましたが、その方法に関する情報が見つかりません。

4

5 に答える 5

14

MySQL を使用していると仮定すると、このコード スニペットはニーズを満たしていると思います。そうでない場合は、構文を少し調整する必要があるかもしれませんが、アイデアはまだ機能するはずです。

ソース:テーブルのロック

class LockingManager(models.Manager):
    """ Add lock/unlock functionality to manager.

    Example::

        class Job(models.Model):

            manager = LockingManager()

            counter = models.IntegerField(null=True, default=0)

            @staticmethod
            def do_atomic_update(job_id)
                ''' Updates job integer, keeping it below 5 '''
                try:
                    # Ensure only one HTTP request can do this update at once.
                    Job.objects.lock()

                    job = Job.object.get(id=job_id)
                    # If we don't lock the tables two simultanous
                    # requests might both increase the counter
                    # going over 5
                    if job.counter < 5:
                        job.counter += 1                                        
                        job.save()

                finally:
                    Job.objects.unlock()


    """    

    def lock(self):
        """ Lock table. 

        Locks the object model table so that atomic update is possible.
        Simulatenous database access request pend until the lock is unlock()'ed.

        Note: If you need to lock multiple tables, you need to do lock them
        all in one SQL clause and this function is not enough. To avoid
        dead lock, all tables must be locked in the same order.

        See http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html
        """
        cursor = connection.cursor()
        table = self.model._meta.db_table
        logger.debug("Locking table %s" % table)
        cursor.execute("LOCK TABLES %s WRITE" % table)
        row = cursor.fetchone()
        return row

    def unlock(self):
        """ Unlock the table. """
        cursor = connection.cursor()
        table = self.model._meta.db_table
        cursor.execute("UNLOCK TABLES")
        row = cursor.fetchone()
        return row  
于 2014-02-21T11:10:37.920 に答える