3、原生jdbc链接数据库之锁与事务
一。锁的概念
1.作用:是保证数据的一致性,只能一个人修改数据,不能同时多用户修改
2.分类:行级锁和表级锁
乐观锁和悲观锁
二.事务
1.为了保证数据的一致性和完整性,让数据库的多项操作合并为一个整体,要不全部成功,要不有一个失败全部失败
2.步骤:
a.将jdbc的自动提交事务改为手动提交
b.在业务最后提交事务
c.在异常处理中回滚事务
3.事务的边界:
事务的开始:jdbc的自动提交事务改为手动提交
事务的结束:commit和rollback。如果事务没有正常结束,事务中的锁是不会释放的
4.事务隔离级别:
TRANSACTION_NONE:没有事务
TRANSACTION_READ_UNCOMMITTED:允许脏读
TRANSACTION_READ_COMMITTED:避免脏读
TRANSACTION_REPEATABLE_READ:避免不可重复读
TRANSACTION_SERIALIZABLE:可重复读
5.事务隔离级别的设定:
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);//设置事务级别,默认为该级别
实例:
package com.demo1212; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException; public class TanstactionDemo {
//模拟转账流程
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
try{
conn = JDBCFactory.getConn();
//打开事务边界,就是取消自动提交,改为手动
conn.setAutoCommit(false);
//把一号账户减去500余额
String sql1 = "update user_info set balance=balance-500 where user_id=1";
ps = conn.prepareStatement(sql1);
ps.executeUpdate(); // int num = 1/0;//模拟异常情况 //把二号账户加上500余额
String sql2 = "update user_info set balance=balance+500 where user_id=2";
ps = conn.prepareStatement(sql2);
ps.executeUpdate(); conn.commit();//提交事务,正常结束
}catch (Exception e) {
try {
conn.rollback();//有异常发生就回滚事务,是为了保证释放锁
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
JDBCFactory.closeAll(conn, ps, null);
}
}
}
锁的概念,摘自其他博客...
一、悲观锁和乐观锁 我们经常在开发中遇到数据库并发处理时,处理不一致的问题。需要对程序做并发控制。
典型的并发时出现的冲突有两种:
1、丢失更新:一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失。
例如X=0 A1把X=X+1 A2也设置X=X+1 如果A1和A2同时执行,可能出现最终X=1的情况。而我们需要得到的是X=2 。 这就需要update处理为串行化的。
2、脏读:读到的数据可能是旧的。 初使X=0 A1把X设置为1,A2读取时X是1,但A1后面又修改成了2,或回滚到了0,那么A2读取的数据就是脏数据。
A2读取的是未提交的数据。一般数据库不会设为读未提交,所以一般不会出现脏读。 那什么是乐观锁,什么是悲观锁。 悲观锁:需要使用数据库的锁机制,如数据库有表级排它锁,有行级排它锁。
假定一切操作都可能发现并发冲突,所以采取悲观态度。通过加锁,屏蔽一切可能违反数据完整性的操作
比方select * from table for update; 就是表锁,
select * from table where x = 1 for update; 就是行锁。
当使用for update后,其它会话还是可以执行select操作,但无法执行select xx for update操作,只有当前会话commit后,其它for update操作才会被执行。
典型例子可以参考quartz集群的锁机制:
http://blog.itpub.net/11627468/viewspace-1764753/
当然,此时也不可以update,update需要等select xx for update 所在会话commit后才能执行。
注:mysql需要设置autocommit=0 乐观锁:其实不是真实的去锁住记录不让访问,或者不让更新。
假定操作很少发生冲突,一般对于读多写少的情况。只在提交操作时检查是否违反数据完整性。[1] 乐观锁不能解决脏读的问题。
可以通过版本号是否比上个版本号或者时间戳来实现。
对于冲突检测后的处理,需要业务逻辑去处理。 二、排它锁和共享锁
在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。
当数据对象被加上排它锁时,其他的事务不能对它读取和修改。
加了共享锁的数据对象可以被其他事务读取,但不能修改。
数据库利用这两种基本的锁类型来对数据库的事务进行并发控制。
三、表级锁和行级锁 DML锁的目的在于保证并发情况下的数据完整性,主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。
当Oracle执行DML语句时,系统自动在所要操作的表上申请TM类型的锁。当TM锁获得后,系统再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志,而只需检查TM锁模式的相容性即可,大大提高了系统的效率。TM锁包括了SS、SX、S、X等多种模式,在数据库中用0-6来表示。不同的SQL操作产生不同类型的TM锁。 值 锁模式 锁描述 SQL
0 NONE 1 NULL 空 SELECT
2 SS(ROW-S) 行级共享锁
其他对象只能查询这些数据行 SELECT FOR UPDATE、LOCK FOR UPDATE、
LOCK ROW SHARE
3 SX(ROW-X) 行级排它锁
在提交前不允许做DML操作 INSERT、UPDATE、DELETE、
LOCK ROW SHARE
4 S(SHARE) 共享锁 CREATE INDEX、LOCK SHARE
5 SSX(S/ROW-X) 共享行级排它锁 LOCK SHARE ROW EXCLUSIVE
6 X(eXclusive) 排它锁 ALTER TABLE、DROP TABLE、DROP INDEX、
TRUNCATE TABLE、LOCK EXCLUSIVE 四、几个问题
1.UPDATE/DELETE操作会将RS锁定,直至操作被COMMIT或者ROLLBACK;
若操作未COMMIT之前其他session对同样的RS做变更操作,则操作会被hold,直至前session的UPDATE/DELETE操作被COMMIT; 2.session内外SELECT的RS范围
前提:INSERT、UPDATE操作未COMMIT之前进行SELECT;
若在同一session内,SELECT出来的RS会包括之前INSERT、UPDATE影响的记录;
若不在同一session内,SELECT出来的RS不会包括未被COMMIT的记录; 3.SELECT.... FOR UPDATE [OF cols] [NOWAIT/WAIT] [SKIP LOCKED]
OF cols:只锁定指定字段所在表的RS,而没有指定的表则不会锁定,只会在多表联合查询时出现;
NOWAIT:语句不会hold,而是直接返回错误ORA-00054: resource busy and acquire with NOWAIT specified;
WAIT N:语句被hold N秒,之后返回错误ORA-30006: resource busy; acquire with WAIT timeout expired;
SKIP LOCKED:不提示错误,而是直接返回no rows selected;
以上几个选项可以联合使用的,比较推荐的有:
SELECT.... FOR UPDATE NOWAIT:对同一RS执行该SQL时,直接返回错误;
SELECT.... FOR UPDATE NOWAIT SKIP LOCKED:对同一RS执行该SQL时,直接返回空行;
PS:当RS被LOCK住之后,只对同样请求LOCK的语句有效,对无需LOCK的SELECT语句并没有任何影响; 以上悲观锁和乐内容参考:
http://www.cnblogs.com/guyufei/archive/2011/01/10/1931632.html
spring锁实现参数:
http://blog.itpub.net/12158104/viewspace-374745
关于隔离级别可以参考:
http://blog.itpub.net/11627468/viewspace-1793036/
关于数据库的锁可以参考:
http://zhidao.baidu.com/link?url=zRnaslJ8INtEviT--BzrT2bMOqf4LJQzL-NQg2ECu6l-s-xPHi11bBlNjN2_zyNrwd9M0ZnbelQntmfYPB0ifq
3、原生jdbc链接数据库之锁与事务的更多相关文章
- 4、原生jdbc链接数据库常用资源名
原生jdbc链接数据库要素:#MySql:String url="jdbc:mysql://localhost:3306/数据库名";String name="root& ...
- 5、原生jdbc链接数据库实例-自动取款机
ATM自动取款机需求 一.登陆 1.界面要求:服务选择 1.老用户登陆:进入后输入卡号密码登陆 2.新用户开户:开户需要输入身份证号,记录姓名,开户时间.然后机器给出卡号,原始密码:111111. 卡 ...
- jdbc链接数据库,获取表名,字段名和数据
import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import ...
- Java基础之原生JDBC操作数据库
前言 日常开发中,我们都习惯了使用ORM框架来帮我们操作数据库,本文复习.记录Java如何使用原生JDBC操作数据库 代码编写 封装几个简单方法 find查询方法 findOne查询方法 update ...
- JDBC链接数据库步骤
java中定义链接数据库的标准:JDBC 1.导包:不同数据库有不同的jdbc驱动包,而且jdbc驱动包和数据库版本必须对应 2.测试 3.写代码 try { 1.//加载JDBC驱动 Clas ...
- jdbc链接数据库的三种方式
/** * jdbc连接数据库 * @author APPle * */ public class Demo1 { //连接数据库的URL private String url = "jdb ...
- 1019 JDBC链接数据库进行修删改查
package com.liu.test01; import java.sql.Statement; import java.sql.Connection; import java.sql.Drive ...
- jdbc链接数据库
JDBC简介 JDBC全称为:Java Data Base Connectivity (java数据库连接),可以为多种数据库提供填统一的访问.JDBC是sun开发的一套数据库访问编程接口,是一种SQ ...
- JDBC链接数据库。
第一步,创建一个空包: 给包起个名字: 新建Modules: 给Modules起名: 创建libs文件: 点击file---->new---->project---->Directo ...
随机推荐
- 协程与Epoll的配合
想快速了解协程与网络调用的原来么,那么请赶紧关闭本页,因为下面都是在扯淡. 这几天是端午假期,第一天大算照着网上一大堆基于ucontext来写协程的文章自己也写一个简单的协程实现.于是第一天我就开始动 ...
- vuejs通过filterBy,orderBy实现搜索筛选,降序排序数据实例
直接贴代码了: 先上输入前的样子: <style> #example{margin:100px auto;width:600px;} .show{margin:10px;} #search ...
- HTML5中的input type为file控件限制上传文件类型及扩展
简单介绍 input file控件限制上传文件类型如下:1.文件类型中间用,分开:2.html和htm这样的要写成两个: 3实例: <input type="file" na ...
- 洛谷P4492 [HAOI2018]苹果树(组合数)
题意 题目链接 Sol 有点自闭,.我好像对组合数一窍不通(~~~~) Orz shadowice // luogu-judger-enable-o2 #include<bits/stdc++. ...
- 深圳共创力“研发管理&知识管理”高端研讨交流会在深圳举办!
2017/4/8,由深圳市共创力企业管理咨询公司举办的“研发管理&知识管理”高端研讨会在深圳市南山区圣淘沙国际酒店(翡翠店)隆重召开.此次研讨会由共创力总经理.首席顾问杨学明先生主持.研讨会先 ...
- Keras实现VGG16
一.代码实现 # -*- coding: utf-8 -*- """ Created on Sat Feb 9 15:33:39 2019 @author: zhen & ...
- shell编程-函数(九)
每种语言都有自己的函数,shell也不例外.支持函数,它可以将脚本程序划分成一个个相对独立的代码块,使代码的模块化,结构更加清晰,并有效地减少程序的代码量,提高代码的复用率. 函数格式 functio ...
- 前后端分离djangorestframework——解析渲染组件
解析器 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己想要的数据类型的过程,本质就是对请求体中的数据进行解析 Accept是告诉对方我能解析什么样的数据,通常也可以表示我想要什么样的数 ...
- Proxysql读写分离配置
ProxySQL是Percona主推的读写分离中间件,下载地址为: https://www.percona.com/downloads/proxysql/ 一.安装 1:下载 wget https:/ ...
- c/c++ 函数模板初探
函数模板初探 1,由来:有时候,函数的逻辑是一样的,只是参数的类型不同,比如下面 int Max(int a, int b){ return a > b ? a : b; } double Ma ...