我发出一个单独的SQL查询,包含使用UNION分组的多个SELECT:
SELECT *
FROM employee
LEFT JOIN department
ON employee.DepartmentID = department.DepartmentID
UNION
SELECT *
FROM employee
RIGHT JOIN department
ON employee.DepartmentID = department.DepartmentID;
Run Code Online (Sandbox Code Playgroud)
假设我在READ_COMMITTED事务隔离下执行此查询,两个SELECT语句是否保证以原子方式执行?或者我是否存在各个SELECT语句之间数据更改的风险?SQL规范是否讨论过这种事情?
澄清:当我说"原子"时,我不是指ACID中的"A".我的意思是我希望在查询完成之前对department和employee表进行读锁定.
是的,该语句是原子的,但数据可以在两次读取之间发生变化。
Read Committed
只保证您不会读取脏数据,它对读取的一致性没有任何保证,因为您需要更高的隔离级别。
正如您所说,您会接受 SQL Server 示例...
(假设在悲观的已提交读隔离级别下)
CREATE TABLE employee
(
name VARCHAR(50),
DepartmentID INT
)
CREATE TABLE department
(
DepartmentID INT
)
INSERT INTO department VALUES (1)
INSERT INTO employee VALUES ('bob',1)
declare @employee TABLE
(
name VARCHAR(50),
DepartmentID INT
)
WHILE ((SELECT COUNT(*) FROM @employee) < 2)
BEGIN
DELETE FROM @employee
INSERT INTO @employee
SELECT employee.*
FROM employee
LEFT JOIN department
ON employee.DepartmentID = department.DepartmentID
UNION
SELECT employee.*
FROM employee
RIGHT JOIN department
ON employee.DepartmentID = department.DepartmentID
END;
SELECT * FROM @employee
Run Code Online (Sandbox Code Playgroud)
while (1=1)
UPDATE employee SET name = CASE WHEN name = 'bob' THEN 'bill' else 'bob' END
Run Code Online (Sandbox Code Playgroud)
现在返回连接 1
name DepartmentID
-------------------------------------------------- ------------
bill 1
bob 1
Run Code Online (Sandbox Code Playgroud)
(记得切换回连接 2 来杀死它!)
READ COMMITED
涵盖此行为的具体文档在这里
共享锁的类型决定了何时释放它。在处理下一行之前释放行锁。当读取下一页时,页锁被释放,当语句完成时,表锁被释放。