线程安全(锁)

撰写时间:2019年0604

 

Mysql的引擎

mysql-5.5.5开始,InnoDB 作为默认存储引擎,以前是MyISAM引擎

MyISAM引擎和InnoDB引擎的比较:

MyISAM 是非事务安全型的,而 InnoDB 是事务安全型的。

MyISAM 锁的粒度是表级,而 InnoDB 支持行级锁定。

MyISAM 支持全文类型索引,而 InnoDB 不支持全文索引。

MyISAM 相对简单,所以在效率上要优于 InnoDB,小型应用可以考虑使用 MyISAM。

MyISAM 表是保存成文件的形式,在跨平台的数据转移中使用 MyISAM 存储会省去    不少的麻烦。

InnoDB 表比 MyISAM 表更安全,可以在保证数据不会丢失的情况下,切换非事务    表到事务表(alter table tablename type=innodb)。

default-storage-engine=InnoDB

default-storage-engine=MYISAM

事务(回滚):当事务正常提交上去的时候,下一个事务失败的时候

事务要回滚到上一条数据。旧引擎MyISAM 就是不支持回滚,所以不支持事务

悲观锁:即很悲观 ,每次拿数据的时候都觉得数据会被人更改,所以拿数据的时

候就把这条记录锁掉,这样别人就没办法改这条数据了,一直到你的锁释放。

 * 悲观锁的实现采用的是数据库内部的锁机制 for update

 * 在查询数据的时候先用for update把这条数据锁住,然后更改完这条数据再

提交。这样别的线程没法更新这条数据,也就保证了不会丢失更新

行级锁

锁一条数据 改其他数据没影响的

需要数据库支持

旧的那个引擎是不支持行级锁的

public class DemoLock1 {

public static void main(String[] args) {

Connection conn = null;

PreparedStatement ps = null;

ResultSet rs = null;

try {

conn = DBUtil.getConnection();

conn.setAutoCommit(false);

String sql = "Select * From user where id=5 for update";

ps = conn.prepareStatement(sql);

// 执行返回结果

rs = ps.executeQuery();

while (rs.next()) {

System.out.println("id:" + rs.getInt(1)

+ " name:"+ rs.getString(2)

+ " passwpord:" + rs.getString(3));

sql = "UPDATE USER SET  NAME ='cbd' WHERE id =5";

ps = conn.prepareStatement(sql);

ps.executeUpdate();

}

conn.commit();

} catch (SQLException e) {

e.printStackTrace();

} finally {

DBUtil.close(conn, ps, rs);

}

}

}

 

悲观锁在 高并发的时候会出现严重问题

悲观锁给人的感觉就是 一直在等待 然后给人返回一个超时

不如直接给出一个操作不成功

这就是出现了乐观锁

 

*查询数据的时候总觉得不会有人更改数据,等到更新的时候在判断这个数据有没

有被人更改,有人更改了则本次更新失败

*通过在表里面加一个版本号的形式

 

乐观锁是通过代码逻辑来实现的 而不是通过数据库内部的锁机制

当操作某条数据的时候 先查询出来获取某个值,然后已该值为修改的where 条件,

当这条数据先被修改过,那么那个值就发生改变,然后修改的where条件获取的是

进来时查询到的值,是修改前的,然后跟当前最新值不对应,然后就返回一个修改

不成功。

public class DemoLock2 {

public static void main(String[] args) {

Connection conn=null;

PreparedStatement ps=null;

ResultSet rs=null;

int r=0;

try {

conn=DBUtil.getConnection();

conn.setAutoCommit(false);

String sql="Select * From user where id=5";

ps=conn.prepareStatement(sql);

rs=ps.executeQuery();

while (rs.next()) {

int version=rs.getInt("version");

sql="update user set name='蔡一0',version=version+1

where id=5 and version=?";

ps=conn.prepareStatement(sql);

ps.setInt(1, version);

r=ps.executeUpdate();

}

conn.commit();

if (r>0) {

System.out.println("修改成功");

}

} catch (SQLException e) {

e.printStackTrace();

}

finally{

DBUtil.close(conn, ps, rs);

}

}

}

测试看效果:断点执行,在提交之前一定要断点,在断点那停的时候去数据库手动修改

加锁的那条数据,看看实际效果是不是跟说的一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值