2017-08-30 68 views
0

我现在正在学习InnoDB的MVCC和我有尝试测试表明:关于MySQL的InnoDB的MVCC测试

MySQL版本:

[[email protected] ~]# mysql --version 
mysql Ver 15.1 Distrib 5.5.52-MariaDB, for Linux (x86_64) using readline 5.1 

表模式:

MariaDB [liruifeng]> show create table test_a; 
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| Table | Create Table                                   | 
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| test_a | CREATE TABLE `test_a` (
    `id` int(11) NOT NULL DEFAULT '0', 
    `a` char(10) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 | 
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ 
1 row in set (0.00 sec) 

然后初始化与这样的数据:

MariaDB [liruifeng]> select * from test_a; 
+----+------+ 
| id | a | 
+----+------+ 
| 1 | 1 | 
| 2 | 2 | 
| 3 | 3 | 
+----+------+ 
3 rows in set (0.00 sec) 

和在第i个具有不同的终端打开两个会话,测试步骤显示为波纹管:

T1:

MariaDB [liruifeng]> start transaction; 
Query OK, 0 rows affected (0.00 sec) 

MariaDB [liruifeng]> select * from test_a; 
+----+------+ 
| id | a | 
+----+------+ 
| 1 | 1 | 
| 2 | 2 | 
| 3 | 3 | 
+----+------+ 
3 rows in set (0.00 sec) 

T2:

MariaDB [liruifeng]> insert into test_a values (4,4); 
Query OK, 1 row affected (0.01 sec) 

MariaDB [liruifeng]> select * from test_a; 
+----+------+ 
| id | a | 
+----+------+ 
| 1 | 1 | 
| 2 | 2 | 
| 3 | 3 | 
| 4 | 4 | 
+----+------+ 
4 rows in set (0.00 sec) 

T1:

MariaDB [liruifeng]> select * from test_a; 
+----+------+ 
| id | a | 
+----+------+ 
| 1 | 1 | 
| 2 | 2 | 
| 3 | 3 | 
+----+------+ 
3 rows in set (0.00 sec) 

MariaDB [liruifeng]> update test_a set a = 444 where id = 4; 
Query OK, 1 row affected (0.00 sec) 
Rows matched: 1 Changed: 1 Warnings: 0 

MariaDB [liruifeng]> select * from test_a; 
+----+------+ 
| id | a | 
+----+------+ 
| 1 | 1 | 
| 2 | 2 | 
| 3 | 3 | 
| 4 | 444 | 
+----+------+ 
4 rows in set (0.00 sec) 

它让我感到困惑,为什么t1可以在t1提交之前通过t2更新行插入?我的tx_isolation级别是可重复读取的,为什么这个更新sql有效?

我的隔离显示为波纹管:

MariaDB [liruifeng]> show variables like 'tx_isolation'; 
+---------------+-----------------+ 
| Variable_name | Value   | 
+---------------+-----------------+ 
| tx_isolation | REPEATABLE-READ | 
+---------------+-----------------+ 
1 row in set (0.00 sec) 

感谢进步:)

+0

我在一个终端上看到一个'START',那另一个终端呢? 'autocommit'的价值是什么? –

+0

@RickJames是,autocommit :) –

回答

0

REPEATABLE-READ说,select * from test_a;会说同样的事情,直到T1 COMMITs。事实上,UPDATE可以看到第4行,但相同SELECT不能是奇怪的,但是有效的。

+0

因此,如果程序尝试使用where子句更新数据,比如“a <5”在其他事务执行插入或更新操作时可能很危险?为什么mysql中的mvcc设计得如此呢? :( –

+0

'UPDATE ... WHERE一个<5'会锁定(某种程度上)所有这些行,WHERE a = 5'只锁定一行。不是一个问题,生产系统需要几毫秒,而不是像t1和t2这样的语句之间的秒。 –