Java常见面试题汇总-----------数据库(数据库锁、数据库存储过程)

57、数据库的锁

  锁是一种并发控制技术,锁是用来在多个用户同时访问同一个数据的时候保护数据的。

57.1、有 2 种基本的锁类型

  共享(S)锁: 多个事务可封锁一个共享页;任何事务都不能修改该页;通常是该页被读取完毕,S锁立即被释放。在执行 select 语句的时候需要给操作对象(表或者一些记录)加上共享锁,但加锁之前需要检查是否有排他锁,如果没有,则可以加共享锁(一个对象上可以加 n 个共享锁 ),否则不行。共享锁通常在执行完 select 语句之后被释放,当然也有可能是在事务结束(包括正常结束和异常结束)的时候被释放,主要取决于数据库所设置的事务隔离级别。

  排它(X)锁: 仅允许一个事务封锁此页;其他任何事务必须等到 X 锁被释放才能对该页进行访问;X 锁一直到事务结束才能被释放。执行 insert、update、delete 语句的时候需要给操作的对象加排他锁,在加排他锁之前必须确认该对象上没有其他任何锁,一旦加上排他锁之后,就不能再给这个对象加其他任何锁。排他锁的释放通常是在事务结束的时候(当然也有例外,就是在数据库事务隔离级别被设置成 Read Uncommitted(读未提交数据)的时候,这种情况下排他锁会在执行完更新操作之后就释放,而不是在事务结束的时候)。

57.2、mysql 锁的粒度(即锁的级别)

  MySQL 各存储引擎使用了三种类型(级别)的锁定机制:行级锁定,页级锁定和表级锁定。
  1、表级锁, 直接锁定整张表,在你锁定期间,其它进程无法对该表进行写操作。如果你是写锁,则其它进程则读也不允许。特点:开销小,加锁快;不会出现死锁;锁定粒度最大,发生锁冲突的概率最高,并发度最低。
  MyISAM 存储引擎采用的是表级锁。
  有 2 种模式:表共享读锁和表独占写锁。加读锁的命令:lock table 表名 read;去掉锁的命令:unlock tables。
  支持并发插入:支持查询和插入操作并发进行(在表尾并发插入)。
  锁调度机制:写锁优先。一个进程请求某个 MyISAM 表的读锁,同时另一个进程也请求同一表的写锁,MySQL 如何处理呢?答案是写进程先获得锁。

  2、行级锁, 仅对指定的记录进行加锁,这样其它进程还是可以对同一个表中的其它记录进行操作。特点:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
  InnoDB 存储引擎既支持行级锁,也支持表级锁,但默认情况下是采用行级锁。

  3、页级锁,一次锁定相邻的一组记录。开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

  最常用的处理多用户并发访问的方法是加锁。当一个用户锁住数据库中的某个对象时,其他用户就不能再访问该对象。加锁对并发访问的影响体现在锁的粒度上。比如,(表锁)放在一个表上的锁限制对整个表的并发访问;(页锁)放在数据页上的锁限制了对整个数据页的访问;(行锁)放在行上的锁只限制对该行的并发访问。

57.3、按锁的机制分:有悲观锁和乐观锁

  悲观锁 ,锁如其名,他对世界是悲观的,他认为别人访问正在改变的数据的概率是很高的,所以从数据开始更改时就将数据锁住,直到更改完成才释放。
  一个典型的倚赖数据库的悲观锁调用:
  select * from account where name=”Erica” for update
  这条 sql 语句锁定了 account 表中所有符合检索条件(name=”Erica”)的记录。 本次事务提交之前(事务提交时会释放事务过程中的锁),外界无法修改这些记录。该语句用来锁定特定的行(如果有 where 子句,就是满足 where条件的那些行)。当这些行被锁定后,其他会话可以选择这些行,但不能更改或删除这些行,直到该语句的事务被 commit 语句或 rollback 语句结束为止。需要注意的是,select ....for update 要放到 mysql的事务中,即 begin 和commit 中,否则不起作用。
  悲观锁可能会造成加锁的时间很长,并发性不好,特别是长事务,影响系统的整体性能。
  悲观锁的实现方式:
  悲观锁,也是基于数据库的锁机制实现。 传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

  乐观锁 ,他对世界比较乐观,认为别人访问正在改变的数据的概率是很低的,所以直到修改完成,准备提交所做的修改到数据库的时候才会将数据锁住, 当你读取以及改变该对象时并不加锁,完成更改后释放。乐观锁不能解决脏读的问题。
  乐观锁加锁的时间要比悲观锁短,大大提升了大并发量下的系统整体性能表现。
  乐观锁的实现方式:
  1、大多是基于数据版本(Version )记录机制实现, 需要为每一行数据增加一个版本标识(也就是每一行数据多一个字段 version),每次更新数据都要更新对应的版本号+1。
  工作原理:读出数据时,将此版本号一同读出,之后更新时,对此版本号加一。 此时,将提交数据的版本信息与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据,不得不重新读取该对象并作出更改。
  假设数据库中帐户信息表中有一个version 字段,当前值为 1;而当前帐户余额字段(balance)为 $100。
  1)、操作员 A 此时将其读出(version=1),并从其帐户余额中扣除 $50($100-$50)。
  2)、在操作员 A 操作的过程中,操作员 B 也读入此用户信息(version=1),并从其帐户余额中扣除 $20($100-$20)。
  3) 操作员 A 完成了修改工作,将数据版本号加一(version=2),连同帐户扣除后余额(balance=$50),提交至数据库更新,此时由于提交数据版本大于数据库记录当前版本,数据被更新,数据库记录 version 更新为 2。
  4) 操作员 B 完成了操作,也将版本号加一(version=2)试图向数据库提交数据(balance=$80),但此时比对数据库记录版本时发现,操作员 B 提交的数据版本号为2,数据库记录当前版本也为 2 ,不满足“提交版本必须大于记录当前版本才能执行更新“的乐观锁策略,因此,操作员 B 的提交被驳回。
  这样,就避免了操作员 B 用基于 version=1 的旧数据修改的结果覆盖操作员 A 的操作结果的可能。
  从上面的例子可以看出,乐观锁机制避免了长事务中的数据库加锁开销(操作员 A 和操作员 B 操作过程中,都没有对数据库数据加锁),大大提升了大并发量下的系统整体性能表现。

  2、使用时间戳来实现
  同样是在需要乐观锁控制的 table 中增加一个字段,名称无所谓,字段类型使用时间戳(timestamp),和上面的 version 类似,也是在更新提交的时候检查当前数据库中数据的时间戳和自己更新前取到的时间戳进行对比,如果一致则 OK,否则就是版本冲突。
  悲观锁和乐观锁的适用场景:
  如果并发量不大,可以使用悲观锁解决并发问题;但如果系统的并发量非常大的话,悲观锁定会带来非常大的性能问题,所以我们就要选择乐观锁定的方法。



58、数据库存储过程

58.1、存储过程

  存储过程:就是一些编译好了的 sql 语句,这些 SQL 语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。
  优点:
  1、存储过程因为 SQL 语句已经预编译过了,因此运行的速度比较快。
  2、存储过程在服务器端运行,减少客户端的压力。
  3、允许模块化程序设计,就是说只需要创建一次过程,以后在程序中就可以调用该过程任意次,类似方法的复用。
  4、减少网络流量,客户端调用存储过程只需要传存储过程名和相关参数即可,与传输 SQL 语句相比自然数据量少了很多。
  5、增强了使用的安全性,充分利用系统管理员可以对执行的某一个存储过程进行权限限制,从而能够实现对某些数据访问的限制,避免非授权用户对数据的访问,保证数据的安全。程序员直接调用存储过程,根本不知道表结构是什么,有什么字段,没有直接暴露表名以及字段名给程序员。
  缺点:
  调试麻烦(至少没有像开发程序那样容易),可移植性不灵活(因为存储过程是依赖于具体的数据库)。

58.2、定义与调用存储过程

create procedure insert_Student (_name varchar(50), _age int, out _id int)
begin
insert into student value(null,_name,_age);
select max(stuId) into _id from student;
end;

call insert_Student('wfz',23,@id);
select @id;

调用存储过程

public class JdbcTest {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Connection cn = null;
        CallableStatement cstmt = null;
        try {
            //这里最好不要这么干,因为驱动名写死在程序中了
            Class.forName("com.mysql.jdbc.Driver");
            //实际项目中,这里应用DataSource数据,如果用框架,这个数据源不需要我们编码创建
            cn = DriverManager.getConnection("jdbc:mysql:///test","root","root");
            cstmt = cn.prepareCall("{call insert_Student(?,?,?)}");
            cstmt.registerOutParameter(3,Types.INTEGER);
            cstmt.setString(1, "wangwu");
            cstmt.setInt(2, 25);
            cstmt.execute();
            //get第几个,不同的数据库不一样,建议不写
            System.out.println(cstmt.getString(3));

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

        } finally {
            try {
                if(cstmt != null)
                    cstmt.close();
                if(cn != null)
                    cn.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 文章导读: 累兮,累兮,要死兮...... 本文解决问题: 1、表级锁定(读锁、写锁) 2、行级锁定(共享锁、排他...
    创造new_world阅读 637评论 0 1
  • 一、简介 数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种...
    huangxiongbiao阅读 427评论 0 0
  • 一、数据库事务 1、事务是作为单个逻辑工作单元执行的一系列操作。可以是一条SQL语句也可以是多条SQL语句。 2、...
    allwefly阅读 1,554评论 0 4
  • 数据库的锁机制 并发控制 在计算机科学,特别是程序设计、操作系统、多处理机和数据库等领域,并发控制(Concurr...
    梦醒家先生阅读 536评论 0 1
  • 今天上午一位经常来洗车的一个大哥 车过来第一次进店保养聊的特别的好,客户也特别的相信以后这些客户一定要照顾好服务好...
    AAAAA京心达张水尚阅读 91评论 0 0