加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

sql-server – 如何在Microsoft SQL Server中显式锁定表(寻找黑

发布时间:2020-12-12 06:28:35 所属栏目:MsSql教程 来源:网络整理
导读:这是我最初的问题: 我试图弄清楚如何在SQL Server中强制执行EXCLUSIVE表锁.我需要解决不合作的读者(我无法控制,闭源的东西),这些读者明确地将他们的ISOLATION LEVEL设置为READ UNCOMMITTED.结果是,无论我在执行插入/更新时指定了多少锁和什么样的隔离,客户端
这是我最初的问题:

我试图弄清楚如何在SQL Server中强制执行EXCLUSIVE表锁.我需要解决不合作的读者(我无法控制,闭源的东西),这些读者明确地将他们的ISOLATION LEVEL设置为READ UNCOMMITTED.结果是,无论我在执行插入/更新时指定了多少锁和什么样的隔离,客户端只需要设置正确的隔离并返回读取我正在进行的垃圾.

答案结果很简单 –

while there is no way to trigger an explicit lock,any DDL change triggers the lock I was looking for.

虽然这种情况并不理想(客户端阻塞而不是目击可重复读取),但它比让客户端覆盖隔离和读取脏数据要好得多.这是带有虚拟触发器锁定机制的完整示例代码

赢了!

#!/usr/bin/env perl

use Test::More;

use warnings;
use strict;

use DBI;

my ($dsn,$user,$pass) = @ENV{ map { "DBICTEST_MSSQL_ODBC_$_" } qw/DSN USER PASS/ };

my @coninf = ($dsn,$pass,{
  AutoCommit => 1,LongReadLen => 1048576,PrintError => 0,RaiseError => 1,});

if (! fork) {
  my $reader = DBI->connect(@coninf);
  $reader->do('SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED');

  warn "READER $$: waiting for table creation";
  sleep 1;

  for (1..5) {
    is_deeply (
      $reader->selectall_arrayref ('SELECT COUNT(*) FROM artist'),[ [ 0 ] ],"READER $$: does not see anything in db,sleeping for a sec " . time,);
    sleep 1;
  }

  exit;
}

my $writer = DBI->connect(@coninf);

eval { $writer->do('DROP TABLE artist') };
$writer->do('CREATE TABLE artist ( name VARCHAR(20) NOT NULL PRIMARY KEY )');
$writer->do(do('DISABLE TRIGGER _lock_artist ON artist');

sleep 1;

is_deeply (
  $writer->selectall_arrayref ('SELECT COUNT(*) FROM artist'),'No rows to start with',);

$writer->begin_work;

$writer->prepare("INSERT INTO artist VALUES ('bupkus') ")->execute;
# this is how we lock
$writer->do('ENABLE TRIGGER _lock_artist ON artist');
$writer->do('DISABLE TRIGGER _lock_artist ON artist');

is_deeply (
  $writer->selectall_arrayref ('SELECT COUNT(*) FROM artist'),[ [ 1 ] ],'Writer sees inserted row',);

# delay reader
sleep 2;

$writer->rollback;

# should not affect reader
sleep 2;

is_deeply (
  $writer->selectall_arrayref ('SELECT COUNT(*) FROM artist'),'Nothing committed (writer)',);

wait;

done_testing;



结果:

READER 27311: waiting for table creation at mssql_isolation.t line 27.
ok 1 - READER 27311: does not see anything in db,sleeping for a sec 1310555569
ok 1 - No rows to start with
ok 2 - Writer sees inserted row
ok 2 - READER 27311: does not see anything in db,sleeping for a sec 1310555571
ok 3 - READER 27311: does not see anything in db,sleeping for a sec 1310555572
ok 3 - Nothing committed (writer)
ok 4 - READER 27311: does not see anything in db,sleeping for a sec 1310555573
ok 5 - READER 27311: does not see anything in db,sleeping for a sec 1310555574

解决方法

一个hack hack hack方法是在表上强制执行一个SCH-M锁在表上的操作,即使在READ UNCOMMITTED隔离级别也会阻止对表的读取.例如,作为操作的一部分,执行类似ALTER TABLE REBUILD的操作(可能在特定的空分区上以降低性能影响)将阻止对表的所有并发访问,直到您提交为止.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读