これは私の最初の質問でした:
SQL Server で EXCLUSIVE テーブル ロックを強制する方法を見つけようとしています。ISOLATION LEVEL を READ UNCOMMITTED に明示的に設定する非協力的なリーダー (私の制御の及ばない、クローズド ソースのもの) を回避する必要があります。その結果、挿入/更新中に指定したロックの数と分離の種類に関係なく、クライアントは適切な分離を設定するだけで、進行中のガベージの読み取りに戻ります。
答えは非常に単純であることが判明しました-
明示的なロックをトリガーする方法はありませんが、DDL を変更すると、探していたロックがトリガーされます。
この状況は理想的ではありませんが (反復可能な読み取りを監視する代わりにクライアントがブロックします)、クライアントに分離をオーバーライドさせてダーティ データを読み取らせるよりははるかに優れています。ダミー トリガー ロック メカニズムを使用した完全なコード例を次に示します。
勝った!
#!/usr/bin/env perl
Test::More を使用します。
警告を使用します。
厳密に使用します。
DBI を使用します。
my ($dsn, $user, $pass) = @ENV{ map { "DBICTEST_MSSQL_ODBC_$_" } qw/DSN USER PASS/ };
私の @coninf = ($dsn, $user, $pass, {
自動コミット => 1、
LongReadLen => 1048576、
印刷エラー => 0、
RaiseError => 1、
});
if (! フォーク) {
私の $reader = DBI->connect(@coninf);
$reader->do('SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED');
"READER $$: テーブルの作成を待っています" と警告します。
睡眠 1;
(1..5) {
is_deeply (
$reader->selectall_arrayref ('SELECT COUNT(*) FROM artist'),
[ [ 0 ] ],
"READER $$: db に何も表示されません。しばらくスリープ状態です" . 時間、
);
睡眠 1;
}
出口;
}
私の $writer = DBI->connect(@coninf);
eval { $writer->do('DROP TABLE アーティスト') };
$writer->do('CREATE TABLE artist ( name VARCHAR(20) NOT NULL PRIMARY KEY )');
$writer->do(do('DISABLE TRIGGER _lock_artist ON artist');
睡眠 1;
is_deeply (
$writer->selectall_arrayref ('SELECT COUNT(*) FROM アーティスト'),
[ [ 0 ] ],
'開始する行がありません',
);
$writer->begin_work;
$writer->prepare("INSERT INTO artist VALUES ('bupkus') ")->execute;
# これがロック方法です
$writer->do('ENABLE TRIGGER _lock_artist ON artist');
$writer->do('DISABLE TRIGGER _lock_artist ON artist');
is_deeply (
$writer->selectall_arrayref ('SELECT COUNT(*) FROM アーティスト'),
[ [ 1 ] ]、
'ライターは挿入された行を見る',
);
# 遅延リーダー
睡眠 2;
$writer->ロールバック;
# リーダーに影響を与えるべきではありません
睡眠 2;
is_deeply (
$writer->selectall_arrayref ('SELECT COUNT(*) FROM アーティスト'),
[ [ 0 ] ],
'何もコミットされていません (ライター)',
);
待つ;
done_testing;
結果:
READER 27311: mssql_isolation.t 行 27 でテーブルの作成を待機しています。 ok 1 - READER 27311: db に何も表示されず、1 秒間スリープします 1310555569 ok 1 - 開始する行がありません ok 2 - Writer は挿入された行を認識します わかりました 2 - リーダー 27311: db に何も表示されず、1 秒間スリープします 1310555571 ok 3 - READER 27311: db に何も表示されず、1 秒間スリープします 1310555572 ok 3 - 何もコミットされていません (ライター) ok 4 - READER 27311: db に何も表示されず、1 秒間スリープします 1310555573 OK 5 - READER 27311: db に何も表示されず、1 秒間スリープします 1310555574