我正在开发一个应用程序,它需要处理数据访问并发问题,但我不太清楚如何正确使用事务隔离级别。
我有一个名为“Folders”的表,其中包含类似树形结构的文件夹:
为什么会发生这种情况?如何防止其他人读取/写入
我有一个名为“Folders”的表,其中包含类似树形结构的文件夹:
+-----------------------------------------------------------------+
| Id (int) | Name (varchar) | FullPath (varchar) | ParentId (int) |
|----------+----------------+--------------------+----------------|
| 1 | 'root1' | '/root1/' | NULL |
| 2 | 'c1' | '/root1/c1/' | 1 |
| 3 | 'c2' | '/root1/c1/c2/' | 2 |
| 4 | 'root2' | '/root2/' | NULL |
+----------+----------------+--------------------+----------------+
我正在尝试实现“移动文件夹”工作流程,如下所示(例如,我想将ID为2的文件夹移动到新父文件夹ID为4):
- 开始事务
- 读取ID为2的文件夹(称其为folder2):
SELECT * FROM Folders WHERE Id=2
- 读取ID为4的文件夹(称其为folder4):
SELECT * FROM Folders WHERE Id=4
- 更新folder2的ParentId和FullPath:
UPDATE Folders SET ParentId=folder4.Id, FullPath=folder4.FullPath+folder2.Name+'/' WHERE Id = folder2.Id
- 读取folder2的所有子文件夹(称之为subfoldersOfFolder2):
SELECT * FROM Folders WHERE FullPath LIKE folder2.FullPath + '%'
- 对于subfoldersOfFolder2中的每个子文件夹,更新FullPath列(省略查询)
- 提交事务
folder2
和subfoldersOfFolder2
。阅读这篇关于SQL Server事务的文章后,我认为在步骤#1将隔离级别设置为Serializable会有所帮助。但出于某种原因,似乎并没有发生这种情况。我尝试保持事务打开状态(在第7步之前停止),打开SSMS的另一个实例,并执行SELECT * FROM Folders
,查询成功完成,我仍然可以看到第1个事务读取的数据。为什么会发生这种情况?如何防止其他人读取/写入
folder2
和subfoldersOfFolder2
?我觉得我错过了关于事务实际上如何锁定数据的重要内容。
updlock, holdlock
选择所有相关的父节点来修改代码。然而,这只会让修改代码正确,但不能防止人们读取您将要修改但尚未修改的子文件夹的路径。考虑到在锁定和读取父文件夹之后才能知道这些子文件夹的 ID(竞争条件),似乎您希望每次编辑路径时对整个表格进行tablock, xlock, holdlock
。 - GSerg