假设我们有事务 t1,他在 SERIABLIZABLE 级别向表中插入一行。现在有另一个事务 t2 不在 SERIABLIZABLE 级别,它通过 select * from table_foo 从同一个表中选择所有行
我的问题是在 t1 提交/释放锁之前,t2 会看到 t1 插入的行吗?
假设我们有事务 t1,他在 SERIABLIZABLE 级别向表中插入一行。现在有另一个事务 t2 不在 SERIABLIZABLE 级别,它通过 select * from table_foo 从同一个表中选择所有行
我的问题是在 t1 提交/释放锁之前,t2 会看到 t1 插入的行吗?
我的问题是在 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 之外的任何隔离级别。
假设 T1 在 T2 之前执行;T2 将看不到这些行,因为 T2 等待 T1。
当 T1 开始执行时,它会锁定表以确保最大隔离级别,这意味着在 T1 完成之前不会在此表上执行任何其他事务。
如果任何其他事务尝试使用该表(在本例中为 T2),它将不得不等待。
因此,T1 和 T2 永远不会同时(并发)执行。例如:
T2 等待 T1
当 T1 完成时 T2 执行
T2 将看到 T1 插入的行
(评论区太长了)是的,如果您真的需要以安全的方式执行每个事务,则替代方法可能是将 SERIALIZABLE 设置为数据库的隔离级别。
从理论上讲,每个事务都应该单独执行(以实现 ACID 属性的 I),但实际上这没有多大意义。这都是关于性能问题。高并发应用程序的数据库无法以这种方式正确执行。
这个想法是在隔离和性能之间实现平衡。当隔离级别降低时(例如,通常是默认隔离级别的 COMMITTED READ)可能会出现一些问题:丢失更新、不可重复读取、幻读。通常这种风险是可以接受的,也可以控制它只在必须处理这些情况的某些事务上提高隔离级别。