事务的概念:
事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功。
数据库开启事务的命令为:
start transaction 开启事务。
rollback 回滚事务。
commit 提交事务。
数据库中默认的事务开启状态:
MySQL中事务默认自动提交的,每当执行一条SQL,就会提交一个事务 (一条SQL 就是一个事务);Oracle 中事务默认不自动提交,需要在执行SQL 语句后 通过commint 手动提交事务。
数据库中存在一个设置自动提交的变量 ,通过 show variables like '%commit%';
得到结果:autocommint = on,说明自动提交被开启。
关闭自动提交: set autocommit = off 或 set autocommit = 0
如果设置autocommit = off,则之后每条SQL 都会处于一个事务中,相当于每条SQL执行前 都执行 start transaction,必须执行commit才会对数据库执行修改。(Oracle中 autocommit 默认值为 off。)
在jdbc中使用事务:
Connection.setAutoCommit(false);
Connection.rollback();
Connection.commit();
事务的特性:4个(ACID)
原子性(Atomicity):事务是一个不可分割的工作单位,事务中的操作要么都成功,要么都不成功。
一致性(Consistency):事务完成前后,必须使所有的数据都保持一致状态,而且在相关数据中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如B树索引和双向链表)都应该是正确的。
隔离性(Isolation):由并发事务所作的修改必须与其它任何并发事务所作的修改隔离,即一个用户的事务不能被其他用户的事务所干扰。事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。
持久性(Durability):事务完成之后,它对系统的影响是永久的,即使出现致命的系统故障也一直保持。
数据库定义的4个事务隔离级别:
Read uncommitted:安全性最差。
Read committed:不会读到中间状态的数据,但是如果其他的事务对数据修改并提交,则该事务读到的数据会变化。
Repeatable read:可重复读,无论其他的事务是否提交,该事务前后读到的数据是一致的。
Serializable:安全性最高,串行化操作,必须等待其他事务操作完成并提交后才能对数据库进行操作。
事务并发处理时,常出现的问题为丢失更新:即,并发执行的两个事务,后提交的事务将先提交的事务所做的修改覆盖掉了。
解决方法(2种):
悲观锁:(利用数据库内部的锁机制)
1.共享锁:对同一个数据表的操作可以添加多个共享锁。select * from table lock in share mode(读锁,共享锁)
2.排它锁:对一个数据表的操作只能添加一个排它锁,且添加排它锁的前后都不能添加其它锁。select * from table for update(写锁,排它锁)
乐观锁:(在数据表中添加版本字段)
如:一个int型的版本号字段,每次修改操作后版本字段的值自动加1;或,设置时间戳,每次数据修改操作之后,都对时间戳进行更新。后提交的事务提交时判断此时的版本号或者时间戳是否与此事务开启时一致,若一致,则提交此事务的修改;若不一致,则此事务提交失败。
连接池:
1.为什么要使用数据库连接池?
答:数据库连接是一种关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。
2.什么是数据库连接池?
答:连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等。也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。
思考:可以使用LinkedList集合来实现一个自定义连接池。(选用LinkedList是因为:在使用连接池时,最常用的操作是取出和放回,即可理解为添加和删除,因此,二叉树结构较为合适。)