回滚机制_【巨杉数据库SequoiaDB】巨杉 Tech | 并发性与锁机制解析与实践

01

概述

数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。

OLTP 场景下通常要求具有很高的并发性。并发事务实际上取决于资源的使用状况,原则上应尽量减少对资源的锁定时间,减少对资源的锁定范围,从而能够尽量增加并发事务的数量,那么影响并发的因素有哪些呢?本文将从巨杉分布式数据库本身的机制以及隔离级别、数据库锁、参数、及实际例子进行详解,读完本文将对巨杉数据库并发性与锁机制有一个初步的了解。

02

隔离级别与并发性

在单用户环境中,每个事务都是顺序执行的,而不会遇到与其他事务的冲突。但是,在多用户环境下,多个事务并发执行。因此每个事务都有可能与其他正在运行的事务发生冲突。有可能与其他事务发生冲突的事务称为交错的或并行的事务,而相互隔离的事务称为串行化事务,这意味着同时运行它们的结果与一个接一个连续地运行它们的结果没有区别。在多用户环境下,在使用并行事务时,会发生四种现象:

  • 丢失更新:这种情况发生在两个事务读取并尝试更新同一数据时,其中一个更新会丢失。例如:事务 1 和事务 2 读取同一行数据,并都根据所读取的数据计算出该行的新值。如果事务 1 用它的新值更新该行以后,事务 2 又更新了同一行,则事务 1 所执行的更新操作就丢失了。
  • 脏读:当事务读取尚未提交的数据时,就会发生这种情况。例如:事务 1 更改了一行数据,而事务 2 在事务1 提交更改之前读取了已更改的行。如果事务 1 回滚该更改,则事务 2 就会读取被认为是不曾存在的数据。
  • 不可重复的读:当一个事务两次读取同一行数据,但每次获得不同的数据值时,就会发生这种情况。例如:事务 1 读取了一行数据,而事务 2 在更改或删除该行后提交了更改。当事务 1 尝试再次读取该行时,它会检索到不同的数据值(如果该行已经被更新的话),或发现该行不复存在了(如果该行被删除的话)。
  • 幻像:当最初没有看到某个与搜索条件匹配的数据行,而在稍后的读操作中又看到该行时,就会发生这种情况。例如:事务 1 读取满足某个搜索条件的一组数据行,而事务 2 插入了与事务 1 的搜索条件匹配的新行。如果事务 1 再次执行产生原先行集的查询,就会检索到不同的行集。

维护数据库的一致性和数据完整性,同时又允许多个应用程序同时访问同一数据,这样的特性称为并发性。巨杉数据库目前通过事务、隔离级别、锁等机制来对并发性进行控制,它决定在第一个事务访问数据时,如何对其他事务锁定或隔离该事务所使用的数据。目前巨杉数据库支持以下隔离级别来实现并发性:

  • 读未提交(ReadUncommitted):该隔离级别指即使一个事务的更新语句没有提交,但是别的事务可以读到这个改变,几种异常情况都可能出现。会出现读取的数据是不对的。
  • 读已提交(Read Committed):该隔离级别指一个事务只能看到其他事务的已经提交的更新,看不到未提交的更新,消除了脏读和第一类丢失更新,这是大多数数据库的默认隔离级别。保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”,但不能避免“幻读”和“不可重复读取”。该级别适用于大多数系统。
  • 读稳定性(RepeatableStability):该隔离级别指一个事务中进行两次或多次同样的对于数据内容的查询,得到的结果是一样的。假设SQL语句中包括查询条件, 则会对全部符合条件的纪录加对应的锁。假设没有条件语句。也就是对表中的全部记录进行处理。则会对全部的纪录加锁。
  • 可重复读(Repeatable Read):REPEATABLE READ隔离级解决了READUNCOMMITTED隔离级导致的问题。它确保同一事务的多个实例在并发读取数据时,会“看到同样的”数据行。不过理论上,这会导致另一个棘手问题:幻读(Phantom Read)。简单来说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影”行。数据库存储引擎可以通过多版本并发控制 (Multiversion Concurrency Control)机制解决了幻读问题,如MySQL的InnoDB和Falcon。巨杉数据库对于多版本控制(MVCC)技术是通过采用事务锁、内存老版本以及磁盘回滚段重建老版本的设计来实现。此架构设计的理论基础是通过对内存结构的合理利用,存储数据和索引的老版本信息,从而实现数据的快速的并发访问。

03

数据库锁参数与并发性实践

1. SequoiaDB的事务配置

事务作为一个完整的工作单元执行,事务中的操作要么全部执行成功要么全部执行失败。SequoiaDB事务中的操作只能是插入数据、修改数据以及删除数据,在事务过程中执行的其它操作不会纳入事务范畴,也就是说事务回滚时非事务操作不会被执行回滚。如果一个表或表空间中有数据涉及事务操作,则该表或表空间不允许被删除。

  • 事务开启、提交与回滚

在SDB中,关于事务启停的配置项如下:

f70589d25a6a77934c0e286298a24ac9.png

默认情况下,SequoiaDB 所有节点的事务功能都是开启的。若用户不需要使用事务功能,可参考以下方法,关闭事务功能。

步骤1:通过sdb shell设置集群所有节点都关闭事务。

db.updateConf( { transactionon: false }, { Global: true } )
72b9b98c40249d6e98163899c8fcf40c.gif

步骤2:在集群每台服务器上都重启 SequoiaDB 的所有节点。​​​​​​​

[sdbadmin@ubuntu-dev1 ~]$ /opt/sequoiadb/bin/sdbstop -t all[sdbadmin@ubuntu-dev1 ~]$ /opt/sequoiadb/bin/sdbstart -t all

注意:

1. 开启及关闭节点的事务功能都要求重启该节点。

2. 在开启节点事务功能的情况下,节点的配置项logfilenum(该配置项默认值为20)的值不能小于 5。

SequoiaDB 事务支持的操作如下:

  • 写事务操作:INSERT、UPDATE、DELETE。
  • 读事务操作:QUERY。

SequoiaDB的其它操作(如:创建表、创建索引、创建并读写LOB等其它非 CRUD 操作)不在事务功能的考虑范围。

支持隔离级别配置参数及取值如下:

96ca8d88239864b5594f88bca7b2b0d4.png

可以通过以下方式修改:

db.updateConf( { transisolation: 1 }, { Global: true } )
72b9b98c40249d6e98163899c8fcf40c.gif

注意:该参数在线生效,会在下一次事务中生效

通过 "transBegin"、"transCommit" 及"transRollback" 方法,用户可以在一个事务中,对若干个操作进行事务控制。其使用方式如下:

> db.transBegin()> 操作1> 操作2> 操作3> ...> db.transCommit() or db.transRollback()

在上述使用模式中,用户必须显式调用"transCommit" 及 "transRollback" 方法来结束当前事务。然而,对于写事务操作,若在操作过程发生错误,数据库配置中的 transautorollback 配置项可以决定当前会话所有未提交的写操作是否自动回滚。transautorollback 的描述如下:

注意:该配置项只有在事务功能开启(即 transactionon 为 true )的情况下才生效。

默认情况下,transautorollback 配置项的值为 true。所以,当写事务操作过程出现失败时,当前事务所有未提交的写操作都将被自动回滚。

  • 事务自动提交

数据库配置中,关于事务自动提交的配置项如下:

6e28e5af6ee55d161afae7cc9f6d68de.png
72b9b98c40249d6e98163899c8fcf40c.gif

​​

事务自动提交功能默认情况下是关闭的。当transautocommit 设置为 true 时,事务自动提交功能将开启。此时,使用事务存在以下两点不同:

  • 用户不需要显式调用 "transBegin" 和"transCommit" 或者 "transRollback" 方法来控制事务的开启、提交或者回滚。
  • 事务提交或者回滚的范围仅仅局限于单个操作。当单个操作成功时,该操作将被自动提交;当单个操作失败时,该操作将被自动回滚。

例如,如下操作中:

> /* transautocommit 设置为 true */> db.foo.bar.update({$inc:{"salary": 1000}}, {"department": "A"}) // 更新 1> db.foo.bar.update({$inc:{"salary": 2000}}, {"department": "B"}) // 更新 2> db.foo.bar.update({$inc:{"salary": 3000}}, {"department": "C"}) // 更新 3> ...

更新 1、更新 2、更新 3 分别为独立的操作。假设更新 1 和 更新 2 操作成功,而更新 3失败。那么更新 1 和 更新 2 修改的记录将全部被自动提交。而更新 3 修改的记录将全部被自动回滚。

  • 其它配置

数据库配置中,关于事务的其它主要配置项如下:

1c5fde1962fed76e657990b95fd06961.png

  • 调整设置

当用户希望调整事务的设置时(如:是否开启事务、调整事务配置项等),有如下 3 种方式供用户选择使用:

  1. 用户可以将数据库配置描述的事务配置项,配置到集群所有(或者部分)节点的配置文件中。若修改的配置项要求重启节点才能生效,用户需重启相应的节点。
  2. 使用 updateConf()命令在 sdb shell 中修改集群的事务配置项。若修改的配置项要求重启节点才能生效,用户需重启相应的节点。
  3. 使用 setSessionAttr()命令在会话中修改当前会话的事务配置项。该设置只在当前会话生效,并不影响其它会话的设置情况。

2. SequoiaDB并发与锁操作实践

示例:

建立数据库以及表

mysql> use company;Database changedmysql>  create table t1 (a int,b int);Query OK, 0 rows affected (0.03 sec)

1)事务提交与回滚

例子1:

使用事务回滚插入操作。事务回滚后,插入的记录将被回滚,集合中无记录:

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> insert into t1 values(1,1);Query OK, 1 row affected (0.08 sec)mysql> select * from t1;+------+------+| a    | b    |+------+------+|    1 |    1 |+------+------+1 row in set (0.00 sec)mysql> rollback;Query OK, 0 rows affected (0.01 sec)mysql> select * from t1;Empty set (0.00 sec)

例子2:

使用事务提交插入操作。提交事务后,插入的记录将被持久化到数据库:

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> insert into t1 values(1,1);Query OK, 1 row affected (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.01 sec)mysql> select * from t1;+------+------+| a    | b    |+------+------+|    1 |    1 |+------+------+1 row in set (0.01 sec)

2)隔离级别为RU并发与锁

例子3:

在隔离级别为RU(transisolation 设置为0)的情况下,设置当前会话级(会话1及会话2同时设置)隔离级别为read uncommitted :

​​​​​​​

mysql> SELECT @@tx_isolation;+-----------------+| @@tx_isolation  |+-----------------+| REPEATABLE-READ |+-----------------+1 row in set, 1 warning (0.00 sec)mysql> set session transaction isolation level read uncommitted;Query OK, 0 rows affected (0.00 sec)mysql> SELECT @@tx_isolation;+------------------+| @@tx_isolation   |+------------------+| READ-UNCOMMITTED |+------------------+1 row in set, 1 warning (0.00 sec)

在窗口1:会话1对该表写入数据,并不提交。

​​​​​​​

mysql> create table t3(a int,b int);Query OK, 0 rows affected (0.02 sec)mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> insert into t3 values(1,1);Query OK, 1 row affected (0.03 sec)

在窗口2:会话2对该表进行查询,查到的是未提交的数据。

mysql>  select * from t3;+------+------+| a    | b    |+------+------+|   1 |    1 |+------+------+1 row in set (0.01 sec)

小结:由于采用了隔离级别是RU,允许脏读,在第二个会话中不会产生锁等待,而直接会读到未提交的数据。该隔离级别建议设置在以读为主的历史数据平台应用中,在真实的OLTP环境中,不能满足业务需求。这样业务查询会读取到未提交事务的修改,如果事务发生回滚,那么读取的数据是错误的。不能满足一致性的要求。

3)隔离级别为RC并发与锁

RR隔离级别的实现概述:

巨杉数据库在RC隔离级别上除了支持传统关系型数据库的读已提交以外,通过MVCC多版本访问的方式支持读取最后一次提交的版本而不会产生锁等待,从而提高业务的并行处理能力。

例子4:在隔离级别为RC(transisolation 设置为1,translockwait为true)的情况下,看看并发情况:

66c648d681e7dac009727f93c18aefd2.png

首先,修改隔离级别为1,translockwait为true该修改将在下一次连接的时候生效。

> db.updateConf({transisolation:1},{Global:true});Takes 0.051656s.> db.updateConf({translockwait:true},{Global:true});Takes 0.041699s.> db.updateConf({transactiontimeout:30},{Global:true});Takes 0.099934s.> db.updateConf({transautocommit:true},{Global:true});Takes 0.040183s.

备注:也可以通过mysql端进行当前session隔离级别参数的修改。

设置当前会话级(会话1及会话2同时设置)隔离级别为read committed :

​​​​​​​

mysql> set session transaction isolation level read committed;  Query OK, 0 rows affected (0.00 sec)

在窗口1:事务1对该表写入数据,并不提交。

​​​​​​​

mysql> create table t4 (a int,b int);Query OK, 0 rows affected (0.09 sec)mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> insert into t4 values(1,1);Query OK, 1 row affected (0.03 sec)

在窗口2:事务2对该表进行查询,可以看到一直会处于等待锁的状态,直到锁超时(transactiontimeout设置为30秒)退出。

​​​​​​​

mysql> select * from t4;ERROR 1030 (HY000): Got eror 40013 from storage engine

通过捉取锁的快照,可以看到第一个事务持有锁的信息,持有该表上的IX,IS锁以及记录上的X锁。如下图所示:

c59dfcf73d6c659c36b7a3e701b1c8a6.png
72b9b98c40249d6e98163899c8fcf40c.gif

而第二个事务等待锁的情况,在等锁该表记录上的S锁。如下图所示:

d64c51a2792d3ae20a9b979c7007661e.png
72b9b98c40249d6e98163899c8fcf40c.gif

小结:由于采用了隔离级别是RC 并且translockwait设置为true的情况下,在第二个事务中会产生锁等待,直到第一个事务释放该表上的行锁,第二个事务才能执行,否则会一直等待到锁超时退出为止。这也是大多数传统关系型数据库的默认隔离级别。

例子5:

在隔离级别为RC(transisolation 设置为1,translockwait为false)的情况下,看看并发情况:

我们先来看看translockwait设置为false的说明: 不等待记录锁,直接从系统读取最后一次提交的版本。

设置SDB参数配置:

​​​​​​​

> db.updateConf({translockwait:false},{Global:true});Takes 0.041699s.

备注:可以通过mysql端进行当前session隔离级别参数的修改。

设置当前会话级(会话1及会话2同时设置)隔离级别为read committed :

​​​​​​​

mysql> set session transaction isolation level read committed;  Query OK, 0 rows affected (0.00 sec)

在窗口1:事务1对该表写入数据,并不提交。

​​​​​​​

mysql> create table t5 (a int,b int);Query OK, 0 rows affected (0.09 sec)mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> insert into t5 values(1,1);Query OK, 1 row affected (0.03 sec)

在窗口2:事务2对该表进行查询,可以看到马上返回,并没有发生锁等待的情况。这时候查到的数据是最后一次提交的版本

mysql> select * from t5;Empty set (0.01 sec)

小结:由于采用了隔离级别是RC 并且translockwait设置为false的情况下,在第二个事务不会产生锁等待,而是会读到最后一次版本已提交的数据。通过锁快照也可以看到没有任何锁等待的情况出现。该隔离级别设置适用于绝大多数的OLTP场景。

4)隔离级别为RS并发与锁

例子6:

在隔离级别为RS(transisolation 设置为2)的情况下,看看并发情况:

> db.updateConf({transisolation:1},{Global:true});Takes 0.051656s.

在窗口1:事务1对该表进行查询数据,不提交。

​​​​​​​

mysql> create table t6 (a int,b int,primary key(a));Query OK, 0 rows affected (0.09 sec)mysql> insert into t6 values(1,1);Query OK, 1 row affected (0.03 sec)mysql> insert into t6 values(2,1);Query OK, 1 row affected (0.03 sec)mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> select * from t6;+------+------+| a    | b    |+------+------+|    1 |    1 ||    2 |    1 |+------+------+1 row in set (0.01 sec)

在窗口2:事务2对该表进行更新,可以看到处于锁等待的状态。最终锁超时事务进行回滚:

​​​​​​​

mysql> egin;Query OK, 0 rows affected (0.00 sec)mysql> update t6 set b=11 where b=1;ERROR 1030 (HY000): Got error 40013 from storage engine

通过捉取锁的快照,可以看到第一个事务持有锁的情况,查询拿到了该表上的S锁。如下图所示:

4e82d0480ab5ce7ac04d3af8a9857424.png
72b9b98c40249d6e98163899c8fcf40c.gif

而事务2需要取到该表上的X锁而产生了等待,如下图所示:

d5c1af8ea2bf72dd96b733ef874a2308.png
72b9b98c40249d6e98163899c8fcf40c.gif

小结:由于采用了隔离级别是RS ,在第二个事务更新的事务会产生锁等待,任何事务查找的记录都不允许更新,直到该读取的表的锁被释放。通过锁快照也可以看到有锁等待的情况出现。RS场景并发性较差,一般适应于总帐计算系统系统。查到的数据该事务不提交,侧不允许被修改。

5)隔离级别为RR并发与锁

RR隔离级别的实现概述:

在多版本控制技术的事务锁实现中,RR(可重复读)配置下的读操作可以在使用完记录之后立即释放锁,不需要一直持有,直到事务提交或者回滚。但是写事务操作则需要一直持有插入、更改和删除的锁,直到事务完成提交或者回滚。巨杉数据库锁的实现是采用悲观锁机制,与传统关系型数据库的采用的主流锁机制类似。

在多版本控制技术的实现中,除了引入悲观锁的机制以外,巨杉数据库还采用了内存老版本机制提升数据库并发访问及操作的能力。内存老版本是通过在记录锁上附加有一个存储原版本数据和索引相关的结构,于内存中存储了老版本的数据。

以下通过实例操作进行详解:

例子7:

在隔离级别为RR(transisolation 设置为3)的情况下,看看并发情况:

> db.updateConf({transisolation:3},{Global:true});Takes 0.051656s.> db.updateConf({mvccon:true},{Global:true})Takes 0.156197s.> db.updateConf({globtranson:true},{Global:true})Takes 0.051241s.

备注:打开RR隔离,除了transisolation 设置为3以外,需要修改以上多二个参数。mvccon及globtranson这二个参数为true。通过mysql端也可以直接进行设置。

通过mysql直接设置当前会话级(会话1及会话2同时设置)隔离级别为REPEATABLEREAD;

​​​​​​​

mysql> set session transaction isolation level REPEATABLE READ;  Query OK, 0 rows affected (0.00 sec)

在窗口1:事务1对该表rr进行查询数据,不提交

mysql> create table rr (a int);Query OK, 0 rows affected (0.06 sec)mysql> insert into rr values(1);Query OK, 1 row affected (0.19 sec)mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> select * from rr;+------+| a    |+------+|    1 |+------+1 row in set (0.00 sec)

在窗口2:事务2对该表rr(事务1第一次查询后)进行数据更新后提交。

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> update rr set a=2 where a=1;Query OK, 1 row affected (0.01 sec)Rows matched: 1  Changed: 1  Warnings: 0mysql> commit;Query OK, 0 rows affected (0.01 sec)

在窗口1:事务1对该表rr进行再次查询数据,查询到的数据可以看到不会由于事务2的更新提交而改变,而是读到事务开始前的版本数据。

mysql> select * from rr;+------+| a    |+------+|    1 |+------+1 row in set (0.00 sec)

通过捉取锁的快照,可以看到第一个查询的事务1在整个事务的查询中没有持任何锁,而事务2更新的操作持用该表的行锁。如下所示:

事务1持有锁的情况(未持有锁):

72b9b98c40249d6e98163899c8fcf40c.gif

事务2持有锁的情况,持有该表的X锁,如下图所示:

3418d39a0ea4dbc605a4a9d88f16f8bd.png
72b9b98c40249d6e98163899c8fcf40c.gif

aad8f8e1bdb8121e2df5684c21d4b396.png
72b9b98c40249d6e98163899c8fcf40c.gif

小结:由于采用了隔离级别是RR ,任何查询都不会持用锁,也不会等锁,可以看到在第二个事务更新的操作不会影响事务1,任何更新的操作不会影响查询,由于事务1是在事务2之前执行查询,当前事务1始终查到的是rr表的事务2的更新前版本。该隔离级别适应于大并发查询的交易场景,能有效提高整个应用的并发性。

05

总结

巨杉数据库完整支持传统关系型数据库的几种常用隔离级别,可满足所有核心生产场景(OLTP及OLAP等场景)需求。创新性采用事务锁、内存老版本以及磁盘回滚段重建老版本的设计来实现了多版本并发控制技术。通过对内存结构的合理利用,存储数据和索引的老版本信息,从而实现多版本数据的快速的并发访问。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/396076.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android系统源码学习——源码目录结构介绍

2019独角兽企业重金招聘Python工程师标准>>> Android 4.0源码目录结构: 本文介绍Android源码目录结构,以便读者理清Android编译系统核心代码在Android源代码的位置。 Android源码体积非常庞大,由Dalvik虚拟机、Linux内核、编译系统、框架代码…

简答题c语言文件操作顺序,计算机基础与程序设计2012年4月真题试题(02275)

计算机基础与程序设计2012年4月真题试题与答案解析(02275)计算机基础与程序设计2012年4月真题试题与答案解析(02275),本试卷总共100分。一、单项选择题(本大题共20小题.每小题1分,共20分)在每小题列出的四个备选项中只有一个是符合题目要求的&#xff0c…

汇编实验3

1.运行如下代码: assume cs:codecode segment mov ah,2 mov dl,3 add dl,30h int 21h mov ah,2 mov dl,6 add dl,30h int 21h mov ah,4ch int 21hcode endsend 进行汇编运行之后结果为: 将第四行和第九行的寄存器dl的值修改之后代码如下: a…

听了一堂《**学院》的课,我也是醉了

这还是首席讲师的ppt,这说话咋感觉,不像是技术出身,反倒是MongoDB的销售人员呢。 这说话,不大讲相对,净他妈的 绝对,这水平,我真醉了。 这牛逼吹得,啧啧啧。 我还是看书吧。 转载于:…

appium 环境搭建(不推荐安装此版本appium,推荐安装appium desktop)

一:安装node.js 1、双击这个软件 2、一键安装,全都下一步,不要私自更改安装路径 3、打开cmd,输入npm,出现如下截图表示成功 二:安装appium 1、双击appium-installer.exe 2、一键安装,全都下一步…

二级c语言上机题库及解析,2013年计算机二级C语言上机题库及答案解析(3)

填空题给定程序中,函数fun的功能是:在形参ss所指字符串数组中,查找含有形参substr所指子串的所有字符串并输出,若没找到则输出相应信息。ss所指字符串数组中共有N个字符串,且串长小于M。程序中库函数strstr(s1, s2)的功能是在 s1串…

js 数组遍历符合条件跳出循环体_C++模拟面试:从数组“紧凑”操作说开来

面试官自来也去掉一个字符串中的空格。假设用C语言来解答,字符串是char数组。O(n)时间复杂度实现不难,比如额外申请一个新数组,然后遍历一遍字符串,将符合条件的字符存储到新数组中,实现起来很简单。但这显然不能让面试…

基本入门程序编写格式和注意事项

在安装好JDK后联系程序的基本写法。1、先创建记事本,如果有超级记事本如:notepad、ultraedit、editplus等更好。重命名把记事本后面的后缀名改为.java 但是值得注意的是要看看自己创建的记事本文档是否是隐藏后缀名的。要是有设置隐藏的就取消隐藏,以免混…

.dll文件存在但是不显示_一招巧妙解决U盘内文件明明存在,打开U盘而内容却不显示的问题...

大家可能都遇到过这种情况,就是说U盘中明明有文件,但是插在电脑上就是什么文件都没有,一片空白,这样的问题对于那些对文件很重要且仅保存了1份的人来说是很.kongbu.,因为U盘中的内容都是命根子。给大家介绍绝对有用的解…

Vue 框架-05-动态绑定 css 样式

Vue 框架-05-动态绑定 css 样式 今天的小实例是关于 Vue 框架动态绑定 css 样式,这也是非常常用的一个部分 首先说一下 动态绑定,相对的大家都知道静态绑定,静态绑定的话,直接加 class“”就可以了,使用 Vue 呢之前也介…

bool查询原理 es_ES系列之原理copy_to用好了这么香

写在前面Elasticsearch(以下简称ES)有个copy_to的功能,之前在一个项目中用到,感觉像是发现了一个神器。这个东西并不是像有些人说的是个语法糖。它用好了不但能提高检索的效率,还可以简化查询语句。基本用法介绍直接上示例。先看看mapping&am…

vnr光学识别怎么打开_干货|指纹锁的指纹识别模块的前世今生,智能锁的指纹识别到底有多智能?...

智能锁现在也有很多叫法:指纹锁、电子锁。可见指纹识别是智能锁的核心功能了,那我们今天来聊聊智能锁的指纹识别模块。指纹识别的历史指纹识别认证的流程指纹识别技术的种类指纹识别的历史早在2000多年前我国古代的人就将指纹用于签订合同和破案了&#…

hide show vue 动画_(Vue动效)7.Vue中动画封装

关键词&#xff1a;动画封装——进行可复用一、如何封装&#xff1f;1、使用&#xff1a;局部组件传递数据局部组件中使用JS动画2、原理&#xff1a;将动画效果完全第封装在一个名为<fade>的组件中&#xff0c;今后如要复用&#xff0c;只需要复制有其组件名的部分&#…

《Python地理数据处理》——导读

前言本书可以帮助你学习使用地理空间数据的基础知识&#xff0c;主要是使用GDAL / OGR。当然&#xff0c;还有其他选择&#xff0c;但其中一些都是建立在GDAL的基础之上&#xff0c;所以如果你理解了本书中的内容&#xff0c;就可以很轻松地学习其他知识。这不是一本关于地理信…

记一次Java AES 加解密 对应C# AES加解密 的一波三折

最近在跟三方对接 对方采用AES加解密 作为一个资深neter Ctrl CV 是我最大的优点 所以我义正言辞的问他们要了demo java demo代码&#xff1a; public class EncryptDecryptTool {private static final String defaultCharset "UTF-8";private static final String …

zemax评价函数编辑器_ZEMAX与光学设计案例:激光扩束系统详细设计与公差分析(二)...

目前超过两千人的光学与光学设计方面的微信公众号&#xff0c;欢迎您的到来&#xff01;激光扩束系统公差分析ZEMAX与光学设计案例&#xff1a;激光扩束系统详细设计与公差分析(二)作者&#xff1a;墨子川上10倍扩束系统在上篇已经设计好了&#xff0c;接下来就是进行系统的公差…

UiPath: Selectors repair 选择器的修复,即被选择的按钮发生改变如何选择第二按钮...

实现批量注册用户功能时&#xff0c;出现第一个用户注册完时&#xff0c;弹出确认按钮&#xff0c;点击即可&#xff0c;但是第二个用户注册完成时&#xff0c;弹出的按钮与第一个有差异&#xff0c;图形用户界面元素及其父元素的属性都发生改变。所以就点不了按钮&#xff0c;…

《C专家编程》一1.6 它很棒,但它符合标准吗

本节书摘来自异步社区《C专家编程》一书中的第1章&#xff0c;第1.6节&#xff0c;作者 【美】Perter Van Der Linde&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看 1.6 它很棒&#xff0c;但它符合标准吗 不要添乱——立即解散ISO工作小组。 ——匿名人士 …

abap al设置单元格可编辑 oo_excel表格操作: 图形和图表编辑技巧汇总(二)

1. 快速选取图表元素图表创建好以后&#xff0c;我们还需要对某些图表元素进行编辑和格式化。图表区包括整个图表和它的全部元素&#xff0c;当你选取图表区后&#xff0c;你就可以看到8个黑色小方块。要想调整单个的图表对象&#xff0c;首先必须选取该对象&#xff0c;然后更…

我的北航故事

我的北航故事 致 沙航的我 既然是故事&#xff0c;那就一定少不了我们耳熟能详的时间&#xff0c;地点&#xff0c;人物&#xff0c;事件&#xff0c;发展&#xff0c;高潮&#xff0c;结局。经过反复的琢磨&#xff0c;我觉得还是写成日记形式比较适合&#xff0c;一是为了掩盖…