查询语言.forUpdate

Testing Is Documentation

tests/Database/Query/ForUpdateTest.php查询语言.forUpdate - 图1

对数据库悲观锁的支持,排它锁和共享锁。

Uses

  1. <?php
  2. use Tests\Database\DatabaseTestCase as TestCase;

forUpdate 排它锁 FOR UPDATE 查询

第一步事务中加入排它锁未提交

在未提交前,表 test_query 的 tid = 1 行将会锁住,其它查询在这一行数据无法加上排它锁和共享锁,更不能更新改行数据,一直等待直到 commit 或者超时。

  1. BEGIN;
  2. SELECT `test_query`.* FROM `test_query` WHERE `tid` = 1 FOR UPDATE;
  3. -- COMMIT;

提交后 commit,其它会正常执行。

排它锁失败

  1. SELECT `test_query`.* FROM `test_query` WHERE `tid` = 1 FOR UPDATE;

共享锁失败

  1. SELECT `test_query`.* FROM `test_query` WHERE `tid` = 1 LOCK IN SHARE MODE;

更改失败

  1. UPDATE `test_query` SET `name` = 'hello' WHERE `tid` = 1;

普通查询正常

  1. SELECT `test_query`.* FROM `test_query` WHERE `tid` = 1;
  1. public function testForUpdate(): void
  2. {
  3. $connect = $this->createDatabaseConnectMock();
  4. $sql = <<<'eot'
  5. [
  6. "SELECT `test_query`.* FROM `test_query` FOR UPDATE",
  7. [],
  8. false
  9. ]
  10. eot;
  11. $this->assertSame(
  12. $sql,
  13. $this->varJson(
  14. $connect
  15. ->table('test_query')
  16. ->forUpdate()
  17. ->findAll(true)
  18. )
  19. );
  20. }

forUpdate 取消排它锁 FOR UPDATE 查询

  1. public function testCancelForUpdate(): void
  2. {
  3. $connect = $this->createDatabaseConnectMock();
  4. $sql = <<<'eot'
  5. [
  6. "SELECT `test_query`.* FROM `test_query`",
  7. [],
  8. false
  9. ]
  10. eot;
  11. $this->assertSame(
  12. $sql,
  13. $this->varJson(
  14. $connect
  15. ->table('test_query')
  16. ->forUpdate()
  17. ->forUpdate(false)
  18. ->findAll(true),
  19. 1
  20. )
  21. );
  22. }

lockShare 共享锁 LOCK SHARE 查询

第一步事务中加入排它锁未提交

在未提交前,表 test_query 的 tid = 1 行将会锁住,其它查询在这一行数据无法加上排它锁,更不能更新改行数据,但是共享锁是可以的,一直等待直到 commit 或者超时。

  1. BEGIN;
  2. SELECT `test_query`.* FROM `test_query` WHERE `tid` = 1 LOCK IN SHARE MODE;
  3. -- COMMIT;

提交后 commit,其它会正常执行。

排它锁失败

  1. SELECT `test_query`.* FROM `test_query` WHERE `tid` = 1 FOR UPDATE;

共享锁成功

  1. SELECT `test_query`.* FROM `test_query` WHERE `tid` = 1 LOCK IN SHARE MODE;

更改失败

  1. UPDATE `test_query` SET `name` = 'hello' WHERE `tid` = 1;

普通查询正常

  1. SELECT `test_query`.* FROM `test_query` WHERE `tid` = 1;
  1. public function testLockShare(): void
  2. {
  3. $connect = $this->createDatabaseConnectMock();
  4. $sql = <<<'eot'
  5. [
  6. "SELECT `test_query`.* FROM `test_query` LOCK IN SHARE MODE",
  7. [],
  8. false
  9. ]
  10. eot;
  11. $this->assertSame(
  12. $sql,
  13. $this->varJson(
  14. $connect
  15. ->table('test_query')
  16. ->lockShare()
  17. ->findAll(true)
  18. )
  19. );
  20. }

lockShare 取消共享锁 LOCK SHARE 查询

  1. public function testCancelLockShare(): void
  2. {
  3. $connect = $this->createDatabaseConnectMock();
  4. $sql = <<<'eot'
  5. [
  6. "SELECT `test_query`.* FROM `test_query`",
  7. [],
  8. false
  9. ]
  10. eot;
  11. $this->assertSame(
  12. $sql,
  13. $this->varJson(
  14. $connect
  15. ->table('test_query')
  16. ->lockShare()
  17. ->lockShare(false)
  18. ->findAll(true),
  19. 1
  20. )
  21. );
  22. }