我的数据库包含名为的表,该表sample_table由名为的一列组成,user_first_name并且该表为空
sample_table
user_first_name
假设我有2笔这样的交易
START TRANSACTION; INSERT INTO sample_table VALUES("TEJA"); INSERT INTO sample_table VALUES("TEJA"); INSERT INTO sample_table VALUES("TEJA"); INSERT INTO sample_table VALUES("TEJA"); INSERT INTO sample_table VALUES("TEJA"); INSERT INTO sample_table VALUES("TEJA"); INSERT INTO sample_table VALUES("TEJA"); //......... till 10000 times COMMIT START TRANSACTION; SELECT * FROM sample_table; SELECT * FROM sample_table; SELECT * FROM sample_table; SELECT * FROM sample_table; SELECT * FROM sample_table; SELECT * FROM sample_table; //........ till 10000 times COMMIT
我以这种方式并行运行这两个事务,首先运行transaction1,然后在运行transaction1时运行transaction2。我希望结果将包含一些名称为TEJA的行。但是我得到了一个空洞的结果。请帮助我解释为什么结果为空?
这完全取决于ISOLATION LEVEL您设置的。
ISOLATION LEVEL
您可以看到使用此查询设置了哪一个:
select @@global.tx_isolation, @@session.tx_isolation;
在解释不同的隔离级别之前,让我解释一下他们试图避免哪些问题:
该 脏读 :一个尚未完成交易的数据被另一个事务读取。
在 丢失更新 :两个事务修改表中的并行条目。当两个事务完成时,仅应用一个修改。
在 不可重复读 :读Reoccuring导致不同的结果。
该 幻读 :一个事务其他事务添加,删除或修改表条目在。
现在针对不同的隔离级别。
读未提交 : 使用此隔离级别,读操作将忽略任何类型的锁,因此可能发生上述任何问题。
已提交读 : 此隔离级别为应修改的对象的整个事务设置了写锁定。读取锁仅在读取数据时设置。因此,可能发生不可重复的读取和幻像读取。
重复读取 : 通过这种隔离级别,可以确保当参数相同时,重复发生的读取操作始终会产生相同的结果。在事务的总持续时间内,为读写操作设置了锁定。因此,只能进行幻像读取。
可序列化 : 最高的隔离级别确保并行运行的事务的结果与事务将一个接一个地运行的结果相同。大多数数据库并没有真正一个接一个地运行这些事务,这会造成性能损失。因此,可能发生一项事务中止的情况。例如,MySQL通过MVCC(多版本并发控制)实现了这一点。如果您想了解更多,请使用Google。这个答案太多了。
此表中的所有内容也对此进行了解释:
| Lost updates | Dirty Read | Non-Repeatable Read | Phantom Read --------------------------------------------------------------------------------- Read Uncommitted | possible | possible | possible | possible Read Committed | impossible | impossible | possible | possible Repeatable Read | impossible | impossible | impossible | possible Serializable | impossible | impossible | impossible | impossible