A thread running a select_for_update that accesses rows being touched by a similar operation on another connection blocks correctly.
(self)
| 566 | @skipUnlessDBFeature("has_select_for_update") |
| 567 | @skipUnlessDBFeature("supports_transactions") |
| 568 | def test_block(self): |
| 569 | """ |
| 570 | A thread running a select_for_update that accesses rows being touched |
| 571 | by a similar operation on another connection blocks correctly. |
| 572 | """ |
| 573 | # First, let's start the transaction in our thread. |
| 574 | self.start_blocking_transaction() |
| 575 | |
| 576 | # Now, try it again using the ORM's select_for_update |
| 577 | # facility. Do this in a separate thread. |
| 578 | status = [] |
| 579 | thread = threading.Thread(target=self.run_select_for_update, args=(status,)) |
| 580 | |
| 581 | # The thread should immediately block, but we'll sleep |
| 582 | # for a bit to make sure. |
| 583 | thread.start() |
| 584 | sanity_count = 0 |
| 585 | while len(status) != 1 and sanity_count < 10: |
| 586 | sanity_count += 1 |
| 587 | time.sleep(1) |
| 588 | if sanity_count >= 10: |
| 589 | raise ValueError("Thread did not run and block") |
| 590 | |
| 591 | # Check the person hasn't been updated. Since this isn't |
| 592 | # using FOR UPDATE, it won't block. |
| 593 | p = Person.objects.get(pk=self.person.pk) |
| 594 | self.assertEqual("Reinhardt", p.name) |
| 595 | |
| 596 | # When we end our blocking transaction, our thread should |
| 597 | # be able to continue. |
| 598 | self.end_blocking_transaction() |
| 599 | thread.join(5.0) |
| 600 | |
| 601 | # Check the thread has finished. Assuming it has, we should |
| 602 | # find that it has updated the person's name. |
| 603 | self.assertFalse(thread.is_alive()) |
| 604 | |
| 605 | # We must commit the transaction to ensure that MySQL gets a fresh |
| 606 | # read, since by default it runs in REPEATABLE READ mode |
| 607 | transaction.commit() |
| 608 | |
| 609 | p = Person.objects.get(pk=self.person.pk) |
| 610 | self.assertEqual("Fred", p.name) |
| 611 | |
| 612 | @skipUnlessDBFeature("has_select_for_update", "supports_transactions") |
| 613 | def test_raw_lock_not_available(self): |
nothing calls this directly
no test coverage detected