есть момент, что транзакции начинаются вот так
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
START TRANSACTION
szQocks, у вас же вложенные транзакции, конечно они обе получат один снапшот и будут работать с одними и теми же данными. Не знаю, зачем вам это понадобилось, но просто вытащите вложенную транзакцию наружу и все будет отлично, тем более, что если это происходит в одном участке кода, то конкуренцию запросы друг другу не составят при любом развитии событий, это же один поток, он выполнится последовательно. Т.е. в данном случае даже просто предложенное выше UPDATE users SET balance = balance + 100 WHERE id = 1, выполненное одно за другим сколько угодно раз без транзакций сработает так, как нужно. При отсутствии параллельных обращений, конечно. Транзакции и нужны только чтоб работающие параллельно потоки/процессы не ломились наперегонки в БД, а чинно ждали тех, кто пришел раньше.