最近在处理事务和多线程时,比较困扰数据库事务,数据库连接以及java线程之间的关系。
问题1:事务和连接的关系?
回答:对于数据库事务来说先有一个连接,才能有事务,一个连接里可以有一次或多次事务的提交(自动提交或者手动提交)。对于java中的被transactional注解方法来说,这个被事务管理的方法中可能会使用多个连接。例如一个事务方法里嵌套一个propagation=required的事务方法时,外方法用一个连接,嵌套的方法用一个连接,并且是两个不同的事务。
问题2:连接和线程的关系?
回答:从debug代码看来,一个线程中有去操作数据库,就会去CP获取一个数据库连接,如果此时CP中没有连接可用,就会等待,直到有连接为止。
问题3:一个事务中(transactional注解的方法内)如果开启了多个线程去执行其他的插入操作,那么每个线程执行的插入操作,和线程的caller方法中的插入操作是同一个事务吗?
回答:不是同一个事务
解析:
1.如下图,一个transactional 注解的方法内,先做一次插入操作,接着开了3个线程去分别处理插入任务
2.执行结果通过看debug日志可看出,在执行testTransAndConnection方法时获取了一个数据库连接,并开启了一个事务,并把事务设置为手动提交,然后进行插入操作,插入操作完成,就call起三个线程并且准备着手提交主方法里的事务了。
3.每个线程是创建了不同的sqlsession 去处理的,这里用的连接却都还是主方法释放的那个连接(这里都是同一个连接的原因是由于服务起来后,第一次去请求应用,此时数据库连接池还没有初始化完毕,池子里只有刚刚初始化好的一个连接,其他的连接还没来的及初始化出来,所以这里几个线程的操作其实是大家都在等待并争用那唯一的一个数据库连接。等CP初始化完毕,如果再次触发一次请求就会发现:每个线程的sqlsession都是不同的连接)