在InnoDB存储引擎中,事务id是用来标识事务的唯一数字标识,每个事务都有一个唯一的事务id。在mvcc、锁等很多场景中,我们都能看到事务id的影子。
那么,事务id是什么时候被分配的呢?其实是在执行第一条语句的时候分配的,准确的说,是执行第一条写语句或锁定读语(SELECT ... FOR UPDATE)句时执行的。
下面来做一些小测验,验证一下事务id的分配时机。
设有一张t2表:
CREATE TABLE `t2` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`c` int DEFAULT NULL,
`d` int DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `c` (`c`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
表中有一条记录:
insert into t2 (id,c,d) values (1,11,3);
现在开启一个事务:
begin; -- time0
select * from t2 where id=1; -- time1
select * from t2 where id=1 for share; -- time2
select * from t2 where id=1 for update; -- time3
我们可以通过查询information_schema.innodb_trx表来查看当前事务的信息:
select trx_id, trx_state, trx_started, trx_mysql_thread_id from information_schema.innodb_trx\G
在各个不同的时间点查询,结果如下:
- time0:
- time1:
- time2:
- time3:
我们可以看到,在执行begin语句的时候,查询结果为空,这个时候并没有真正开启事务。而在执行第一条select语句的时候(time0),分配了一个
事务id 281479752323760,在time3,事务id变成了1036864。其实,事务id是一个递增值,在time1的时候,分配的是一个虚拟的事务id,真正
的事务id是在time3的时候分配的。
其实,关于这个话题,在mysql官方手册中,是这样描述的(见8.5.3):
A transaction ID is only needed for a transaction that might perform write operations or locking reads such as SELECT ... FOR UPDATE.
大意是:
只有在执行写操作或锁定读(SELECT ... FOR UPDATE)语句时,才需要事务id。
本文由mdnice多平台发布
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。