SQL create table if not exists spring_ch21_rows(label text primary key)
SQL truncate spring_ch21_rows
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.
ENV Spring=6.2.11 Java=21.0.11
TX required/outer thread=blog.spring.Chapter21.main() pid=76648 xid=770 active=true
INSERT required-outer thread=blog.spring.Chapter21.main()
TX required/inner thread=blog.spring.Chapter21.main() pid=76648 xid=770 active=true
CHECK PASS REQUIRED shares physical connection and transaction
INSERT required-inner thread=blog.spring.Chapter21.main()
CAUGHT inner REQUIRED
CHECK PASS inner REQUIRED failure marks outer rollback-only
CHECK PASS normal outer callback return still causes UnexpectedRollbackException -> UnexpectedRollbackException
OBSERVER thread=blog.spring.Chapter21.main() spring_ch21_rows=[]
CHECK PASS REQUIRED rolls back both rows
TX new/outer thread=blog.spring.Chapter21.main() pid=76648 xid=771 active=true
INSERT new-outer thread=blog.spring.Chapter21.main()
TX new/inner thread=blog.spring.Chapter21.main() pid=76656 xid=772 active=true
CHECK PASS REQUIRES_NEW uses independent connection and transaction
INSERT new-inner thread=blog.spring.Chapter21.main()
TX new/resumed thread=blog.spring.Chapter21.main() pid=76648 xid=771 active=true
CHECK PASS outer physical transaction resumes unchanged
OBSERVER thread=blog.spring.Chapter21.main() spring_ch21_rows=[new-inner]
CHECK PASS independent observer sees inner commit before outer finishes
CHECK PASS outer failure after independent inner commit -> Abort
OBSERVER thread=blog.spring.Chapter21.main() spring_ch21_rows=[new-inner]
CHECK PASS REQUIRES_NEW inner commit survives outer rollback
SQL truncate spring_ch21_rows
TX nested/outer thread=blog.spring.Chapter21.main() pid=76648 xid=774 active=true
INSERT nested-outer thread=blog.spring.Chapter21.main()
CHECK PASS NESTED status owns a savepoint
TX nested/inner thread=blog.spring.Chapter21.main() pid=76648 xid=774 active=true
CHECK PASS NESTED shares outer physical transaction
INSERT nested-inner thread=blog.spring.Chapter21.main()
CAUGHT inner NESTED
CHECK PASS savepoint rollback does not mark outer rollback-only
OBSERVER thread=blog.spring.Chapter21.main() spring_ch21_rows=[]
CHECK PASS observer sees no uncommitted outer data
INSERT nested-after thread=blog.spring.Chapter21.main()
OBSERVER thread=blog.spring.Chapter21.main() spring_ch21_rows=[nested-after, nested-outer]
CHECK PASS NESTED removes inner row and commits outer rows
SQL truncate spring_ch21_rows
INSERT nested-success thread=blog.spring.Chapter21.main()
CHECK PASS outer abort after successful nested scope -> Abort
OBSERVER thread=blog.spring.Chapter21.main() spring_ch21_rows=[]
CHECK PASS successful NESTED is not an independent durable commit
CHECK PASS propagation pool returned all connections
CHECK PASS propagation thread state cleared
SQL truncate spring_ch21_rows
TX pool/outer-1 thread=pool-1-thread-2 pid=76692 xid=780 active=true
INSERT pool-outer-1 thread=pool-1-thread-2
TX pool/outer-0 thread=pool-1-thread-1 pid=76700 xid=781 active=true
INSERT pool-outer-0 thread=pool-1-thread-1
CHECK PASS two outer transactions hold connections at barrier
POOL capacity=2 active=2 waiting=2
CHECK PASS both inner transactions wait while outer connections remain borrowed
ACQUIRE TIMEOUT worker=1 elapsedMs=1509 cause=java.sql.SQLTransientConnectionException: ch21-capacity-2 - Connection is not available, request timed out after 1507ms.
ACQUIRE TIMEOUT worker=0 elapsedMs=1509 cause=java.sql.SQLTransientConnectionException: ch21-capacity-2 - Connection is not available, request timed out after 1507ms.
CHECK PASS expected acquisition timeout count capacity=2
CHECK PASS expected inner commit count capacity=2
OUTER ROLLBACK worker=1
OUTER ROLLBACK worker=0
CHECK PASS worker transaction state cleared 0
CHECK PASS worker transaction state cleared 1
CHECK PASS pool active connections return to zero capacity=2
CHECK PASS pool waiters return to zero capacity=2
OBSERVER thread=blog.spring.Chapter21.main() spring_ch21_rows=[]
CHECK PASS database terminal state capacity=2
INSERT recovery thread=blog.spring.Chapter21.main()
OBSERVER thread=blog.spring.Chapter21.main() spring_ch21_rows=[recovery]
CHECK PASS pool serves a fresh transaction after scenario capacity=2
CHECK PASS worker executor terminated
SQL truncate spring_ch21_rows
TX pool/outer-1 thread=pool-2-thread-2 pid=76805 xid=784 active=true
INSERT pool-outer-1 thread=pool-2-thread-2
TX pool/outer-0 thread=pool-2-thread-1 pid=76806 xid=785 active=true
INSERT pool-outer-0 thread=pool-2-thread-1
CHECK PASS two outer transactions hold connections at barrier
TX pool/inner-0 thread=pool-2-thread-1 pid=76807 xid=786 active=true
INSERT pool-inner-0 thread=pool-2-thread-1
TX pool/inner-1 thread=pool-2-thread-2 pid=76807 xid=787 active=true
INSERT pool-inner-1 thread=pool-2-thread-2
CHECK PASS expected acquisition timeout count capacity=3
CHECK PASS expected inner commit count capacity=3
OUTER ROLLBACK worker=1
OUTER ROLLBACK worker=0
CHECK PASS worker transaction state cleared 1
CHECK PASS worker transaction state cleared 0
CHECK PASS pool active connections return to zero capacity=3
CHECK PASS pool waiters return to zero capacity=3
OBSERVER thread=blog.spring.Chapter21.main() spring_ch21_rows=[pool-inner-0, pool-inner-1]
CHECK PASS database terminal state capacity=3
INSERT recovery thread=blog.spring.Chapter21.main()
OBSERVER thread=blog.spring.Chapter21.main() spring_ch21_rows=[pool-inner-0, pool-inner-1, recovery]
CHECK PASS pool serves a fresh transaction after scenario capacity=3
CHECK PASS worker executor terminated
SQL drop table if exists spring_ch21_rows
