SQLite中隐式事务的形态及多语句事务边界疑问
SQLite中隐式事务的形态及多语句事务边界疑问
嘿,这个问题问到点子上了!咱们来把SQLite的隐式事务逻辑讲明白~
首先得明确SQLite的默认行为:它默认处于自动提交(autocommit)模式。在这个模式下,规则是这样的:
- 所有的写操作语句(比如INSERT、UPDATE、DELETE、CREATE TABLE这类)会自动被包裹在一个隐式事务里:执行语句前自动
BEGIN TRANSACTION,语句执行成功后立刻自动COMMIT。 - 而只读的SELECT语句,在自动提交模式下不会触发任何隐式事务——它就是直接执行查询,不需要事务的包裹。
那回到你的代码:
INSERT INTO artists(Name) VALUE("Artist1"); -- 这里小提醒:SQLite里应该用VALUES,不是VALUE哦,不然会报错 SELECT * FROM artists;
咱们来对应你的两种猜测分析:
第一种猜测(两个独立事务):
BEGIN TRANSACTION; INSERT INTO artists(Name) VALUE("Artist1"); COMMIT; BEGIN TRANSACTION; SELECT * FROM artists; COMMIT;这个是不准确的——因为SELECT语句不会触发隐式事务,所以第二个
BEGIN TRANSACTION和COMMIT根本不会出现,SELECT就是直接执行的。第二种猜测(一个事务包裹两个语句):
BEGIN TRANSACTION; INSERT INTO artists(Name) VALUE("Artist1"); SELECT * FROM artists; COMMIT;这个也不对,因为在默认自动提交模式下,INSERT执行完成后会立刻自动COMMIT,不会等后面的SELECT语句。所以两个语句不会被放在同一个隐式事务里。
如果想要让INSERT和SELECT处于同一个事务中,你需要显式开启事务,比如这样写:
BEGIN TRANSACTION; INSERT INTO artists(Name) VALUES("Artist1"); SELECT * FROM artists; COMMIT;
这时候两个语句会在同一个事务里执行,SELECT能读到INSERT刚插入的数据(事务内的一致性读取)。
总结一下:默认自动提交模式下,你的INSERT会单独触发一个隐式事务(执行后自动提交),SELECT直接执行无事务包裹;只有显式用BEGIN/COMMIT包裹多个语句时,它们才会属于同一个事务。
备注:内容来源于stack exchange,提问作者VanechikSpace
相关产品推荐
相关产品推荐

