0

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

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

4

2 回答 2

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 之外的任何隔离级别。

于 2013-07-27T00:46:54.927 回答
0

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

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

如果任何其他事务尝试使用该表(在本例中为 T2),它将不得不等待。

因此,T1 和 T2 永远不会同时(并发)执行。例如:

T2 等待 T1

当 T1 完成时 T2 执行

T2 将看到 T1 插入的行


(评论区太长了)是的,如果您真的需要以安全的方式执行每个事务,则替代方法可能是将 SERIALIZABLE 设置为数据库的隔离级别。

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

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

于 2013-07-25T14:47:39.110 回答