SQL:将SERIALIZABLE插入其他非可序列化事务可见

时间:2013-07-25 07:43:01

标签: mysql database transactions

假设我们有事务t1,它在SERIABLIZABLE级别的表中插入一行。现在有另一个事务t2不在SERIABLIZABLE级别,它通过select * from table_foo

从同一个表中选择所有行

我的问题是在t1提交/释放锁之前,t2会看到t1行插入吗?

2 个答案:

答案 0 :(得分:1)

  

我的问题是在t1提交/释放锁之前,将t2看到该行   按t1插入?

t2看到的内容完全取决于t2的隔离级别。它与t1的隔离级别无关。

要查看其工作原理,请打开两个终端窗口,并建立两个与MySQL数据库的连接。假设表“test”存在,并且有两行。

Term 1                                         Term 2
set transaction isolation level serializable;  
                                               set transaction isolation level read uncommitted;
                                               select count(*) as num_rows from test;
                                               +----------+
                                               | num_rows |
                                               +----------+
                                               |        2 |
                                               +----------+
                                               1 row in set (0.00 sec)

start transaction;
insert into test values 
('2013-01-02 08:00', '2013-01-02 08');
                                               select count(*) as num_rows from test;
                                               +----------+
                                               | num_rows |
                                               +----------+
                                               |        3 |
                                               +----------+
                                               1 row in set (0.00 sec)

rollback;
                                               select count(*) as num_rows from test;
                                               +----------+
                                               | num_rows |
                                               +----------+
                                               |        2 |
                                               +----------+
                                               1 row in set (0.00 sec)

为了确保术语2 不会看到术语1的INSERT语句中的未提交行,直到它们被提交,除了在术语2中使用READ UNCOMMITTED之外,还要使用任何隔离级别。

答案 1 :(得分:0)

假设T1在T2之前执行; T2不会看到行,因为T2等待T1。

当T1开始执行时,它会锁定表以确保最大隔离级别,这意味着在T1完成之前,该表上不会执行任何其他事务。

如果任何其他事务尝试使用该表(在本例中为T2),则必须等待。

因此,T1和T2永远不会同时执行(同时)。 e.g:

T2等待T1

当T1完成T2执行

T2将看到T1插入的行


(评论区太长了) 是的,如果你真的需要以一种有效的方式执行每个事务,那么可以选择将SERIALIZABLE设置为数据库的隔离级别。

理论上,每个事务应该独立执行(为了实现ACID属性的I),但实际上这没有多大意义。这完全取决于性能问题。高并发应用程序的数据库无法以这种方式正确执行。

这个想法是在隔离和性能之间实现平衡。当隔离级别降低时(例如,通常是默认隔离级别的COMMITTED READ),可能会出现一些问题:丢失更新,不可重复读取,幻读。通常这种风险是可以接受的,并且只有在某些必须处理这些情况的交易中才能控制隔离水平。