知识大全 如何保证并发下资料库操作的原子性
Posted 操作
篇首语:仓廪实则知礼节,衣食足则知荣辱。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 如何保证并发下资料库操作的原子性相关的知识,希望对你有一定的参考价值。
如何保证并发下资料库操作的原子性
不并发控制的话会带来一系列问题:资料冗余、更新异常、插入异常、删除异常等
并发控制保证事务4个特性,acid:A:原子性(Atomicity) 事务是资料库的逻辑工作单位,事务中包括的诸操作要么全做,要么全不做。C:一致性(Consistency) 事务执行的结果必须是使资料库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。I:隔离性 (Isolation) 一个事务的执行不能被其他事务干扰。 D:持续性/永久性(Durability) 一个事务一旦提交,它对资料库中资料的改变就应该是永久性的。
如何确保memcache资料读写操作的原子性
memcache不是就是记忆体资料库么 = = memcache内容很简单的,直接网路发包set进去就行了,memcache本身是个hash结构,这货是开源的,有兴趣直接看看原始码就知道了,程式码量很小就是了。 至于与神马连线,其实都是外部做的
如何保证资料库操作与档案系统操作一致性
如果需求是将资料储存到资料中,那程式设计师是不需要担心事务问题的。但如,如果资料非得储存在档案系统中,或者联合资料使用,那么,资料的一致和隔离如何保证呢? 如果不关注一致性,程式可能程式码如下: public void register(User user,byte[] images) throws Exception UserDao dao = new UserDao(); dao,addUser(user); FileSystem fs = FileSystemFactory.getFileSystem(); 储存图片到指定路径,有可能丢掷异常 fs.saveFile(user.getImagePath(),images)上述程式码的潜在问题就是如果档案系统储存失败,那么,资料就会不一致,页面显示使用者资讯的时候,图片确没有找到。后果稍微严重的列子还有些,譬如上传金钥档案失败但相关资料确已经储存到资料库。 所谓工程思路,其实就是对操作纪录日志,然后有后台系统监控错误并提供管理模组供事后纠正这些错误,这就是所谓的“冲正”,比如上面一个例子,可以写成下面的程式码public void register(User user,byte[] images) throws Exception Logger log = LoggerFactrory,getLogger(); log.addTaskDescription("insert user "+user).addTaskDescription("save file"+user.getImagePath()) UserDao dao = new UserDao();
hive中怎么在当下资料库操作另一个数据库资料
可以使用Sqoop、DataX、或者Hive储存过程来完成。搜寻"lxw的大资料田地",里面有很多关于Hive的文章,肯定能找到你想要的。
sql 资料库操作
SELECT * FROM XXX WHERE GETDATE() beeen begindate and enddate
或者
SELECT * FROM XXX WHERE GETDATE() < enddate and GETDATE() > begindate
MFC中,如何连线sqlite3的资料库,并对此资料库操作?
这个比较容易。按照网上提供的方法把sqlite编译成dll和lib
将dll和lib在专案的输入中新增好
在要操作的档案中#include “sqlite3.h”就可以了。我做过这方面的专案,虽然是嵌入式wince使用,但是基本和windows相同。
下面是详细的用法:
一. 编译动态连结库库档案
1). 开启VC新建一个“Win32 Dynamic-Link Library”工程,命名为:sqlite3(也可以是其他的,注意这个就是编译后的dll和lib的名字)
2). 在接下来的对话方块中选择"An empty DLL project",点 FINISH->OK
3). 将原始码中所有的 *.c *.h *.def 复制到工程资料夹下
4). 在工程的Source File中新增你下载到的SQLite原始档中所有*.c档案,
注意这里不要新增shell.c和tclsqlite.c这两个档案。*注意需要将tclsqlite.c和shell.c、icu.c去掉。其中tclsqlite.c用于生成基于tcl的api,如果要编译,这需要另外下载tcl.h;shell.c用于生成命令列模式的sqlite.exe,如果是静态库形式则可以选择; icu是internationalponents forunicode,如果需要则需另外下载相关标头档案。
5). 将 SQLite 原始档中的 sqlite3.def 档案新增到在工程的Source File中
6). 在Header File中新增你下载到的SQLite原始档中所有*.h档案,
7). 开始编译,Build(F7)一下
也许到这里会遇到一个错误:
e:\\zieckey\\sqlite\\sqlite3\\sqlite3ext.h(22) : fatal error C1083: Cannot open include file: \'sqlite3.h\': No such file or directory
经检查发现,原始码中包含sqlite3.h都是以 #include <sqlite3.h> 方式包含的,
这就是说编译器在系统预设路径中搜索,这样当然搜寻不到 sqlite3.h 这个标头档案啦,
这时可以改为 #include "sqlite3.h" ,让编译器在工程路径中搜索,
但是如果还有其他地方也是以 #include <sqlite3.h> 方式包含的,那么改原始码就显得有点麻烦,
好了,我们可以这样,在选单栏依次选择:Tools->Options...->Directeries
在下面的Directeries选项中输入你的 sqlite3.h 的路径,这里也就是你的工程目录.
新增好后,我们在编译一下就好了,
最后我们在工程目录的 Debug 目录生成了下面两个重要档案:
动态连结库档案 sqlite3.dll 和引入库档案 sqlite3.lib
二. 使用动态连结库
下面我们来编写个程式来测试下我们的动态连结库.
在VC下新建一个空的"Win32 Console Application" Win32控制台程式,工程命名为:TestSqliteOnWindows
再新建一个 test.cpp 的C++语言源程式,原始码如下:
name: test.cpp
This prog is used to test C/C++ API for sqlite3 .It is very simple,ha !
Author : zieckey
data : 2006/11/28
#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"
#define _DEBUG_
int main( void )
sqlite3 *db=NULL;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("zieckey.db", &db); 开启指定的资料库档案,如果不存在将建立一个同名的资料库档案
if( rc )
fprintf(stderr, "Can\'t open database: %s\\n", sqlite3_errmsg(db));
sqlite3_close(db);
return (1);
else printf("You have opened a sqlite3 database named zieckey.db suessfully!\\nCongratulations! Have fun ! ^-^ \\n");
建立一个表,如果该表存在,则不建立,并给出提示资讯,储存在 zErrMsg 中
char *sql = " CREATE TABLE SensorData(ID INTEGER PRIMARY KEY,SensorID INTEGER,SiteNum INTEGER,Time VARCHAR(12),SensorParameter REAL);" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
#ifdef _DEBUG_
printf("zErrMsg = %s \\n", zErrMsg);
#endif
插入资料
sql = "INSERT INTO \\"SensorData\\" VALUES(NULL , 1 , 1 , \'200605011206\', 18.9 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \\"SensorData\\" VALUES(NULL , 23 , 45 , \'200605011306\', 16.4 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
sql = "INSERT INTO \\"SensorData\\" VALUES(NULL , 34 , 45 , \'200605011306\', 15.4 );" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
int nrow = 0, ncolumn = 0;
char **azResult; 二维阵列存放结果
查询资料
sql = "SELECT * FROM SensorData ";
sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
int i = 0 ;
printf( "row:%d column=%d \\n" , nrow , ncolumn );
printf( "\\nThe result of querying is : \\n" );
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s\\n", i , azResult[i] );
删除资料
sql = "DELETE FROM SensorData WHERE SensorID = 1 ;" ;
sqlite3_exec( db , sql , 0 , 0 , &zErrMsg );
#ifdef _DEBUG_
printf("zErrMsg = %s \\n", zErrMsg);
#endif
sql = "SELECT * FROM SensorData ";
sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg );
printf( "\\n\\n\\n\\nrow:%d column=%d " , nrow , ncolumn );
printf( "\\nAfter deleting , the result of querying is : \\n" );
for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ )
printf( "azResult[%d] = %s\\n", i , azResult[i] );
释放掉 azResult 的记忆体空间
sqlite3_free_table( azResult );
#ifdef _DEBUG_
printf("zErrMsg = %s \\n", zErrMsg);
#endif
sqlite3_close(db); 关闭资料库
return 0;
另外,将sqlite3.h sqlite3.lib sqlite3.dll档案复制到我们的工程目录.
最后 Project->Settings 在Link选项卡找到Object/library modules : 在最后填入sqlite3.lib 。
如果原来就有连结,请使用空格分隔。
现在可以编译了.
执行结果如下:
You have opened a sqlite3 database named zieckey.db suessfully!
Congratulations! Have fun ! ^-^
zErrMsg = (null)
row:3 column=5
The result of querying is :
azResult[0] = ID
azResult[1] = SensorID
azResult[2] = SiteNum
azResult[3] = Time
azResult[4] = SensorParameter
azResult[5] = 1
azResult[6] = 1
azResult[7] = 1
azResult[8] = 200605011206
azResult[9] = 18.9
azResult[10] = 2
azResult[11] = 23
azResult[12] = 45
azResult[13] = 200605011306
azResult[14] = 16.4
azResult[15] = 3
azResult[16] = 34
azResult[17] = 45
azResult[18] = 200605011306
azResult[19] = 15.4
zErrMsg = (null)
row:2 column=5
After deleting , the result of querying is :
azResult[0] = ID
azResult[1] = SensorID
azResult[2] = SiteNum
azResult[3] = Time
azResult[4] = SensorParameter
azResult[5] = 2
azResult[6] = 23
azResult[7] = 45
azResult[8] = 200605011306
azResult[9] = 16.4
azResult[10] = 3
azResult[11] = 34
azResult[12] = 45
azResult[13] = 200605011306
azResult[14] = 15.4
zErrMsg = (null)
Press any key to continue
在上面的第五步
5). 将 SQLite 原始档中的 sqlite3.def 档案新增到在工程的Source File中
是必须的, sqlite3.def 这个档案的加入会生成 *.lib引入库档案,这个对于*.dll档案是很重要的.否则你光有*.dll档案在程式呼叫的时候就不是那么方便了,因为这样你只能通过动态载入dll的方式呼叫dll库中函式
这个程式,我们先建立一个数据库,然后新建一个表,然后插入一些资料,
再查询看看插入的资料是否正确,然后又删除一些资料,删除后我们再查询了一下,
发现我们的删除操作也是成功的.
这个程式简单的呼叫 sqlite 的函式介面来实现对资料库的管理,
包括建立资料库、建立表格、插入资料、查询资料、删除资料等。
oracle 资料库操作
这样?
select B.*, A.*from B left A on B.c = A.c and B.d = A.d
如何保证资料库的完整性、安全性、并发性
从解发器,防注入,锁机制。这三个方面来弄。
如何在高并发环境下设计出无锁的资料库操作
一个线上2k的游戏,每秒钟并发都吓死人。传统的hibernate直接插库基本上是不可行的。我就一步步推汇出一个无锁的资料库操作。
1. 并发中如何无锁。
一个很简单的思路,把并发转化成为单执行绪。Java的Disruptor就是一个很好的例子。如果用java的concurrentCollection类去做,原理就是启动一个执行绪,跑一个Queue,并发的时候,任务压入Queue,执行绪轮训读取这个Queue,然后一个个顺序执行。
在这个设计模式下,任何并发都会变成了单执行绪操作,而且速度非常快。现在的node.js, 或者比较普通的ARPG服务端都是这个设计,“大回圈”架构。
这样,我们原来的系统就有了2个环境:并发环境 + ”大回圈“环境
并发环境就是我们传统的有锁环境,效能低下。
”大回圈“环境是我们使用Disruptor开辟出来的单执行绪无锁环境,效能强大。
2. ”大回圈“环境 中如何提升处理效能。
一旦并发转成单执行绪,那么其中一个执行绪一旦出现效能问题,必然整个处理都会放慢。所以在单执行绪中的任何操作绝对不能涉及到IO处理。那资料库操作怎么办?
增加快取。这个思路很简单,直接从记忆体读取,必然会快。至于写、更新操作,采用类似的思路,把操作提交给一个Queue,然后单独跑一个Thread去一个个获取插库。这样保证了“大回圈”中不涉及到IO操作。
问题再次出现:
如果我们的游戏只有个大回圈还容易解决,因为里面提供了完美的同步无锁。
但是实际上的游戏环境是并发和“大回圈”并存的,即上文的2种环境。那么无论我们怎么设计,必然会发现在快取这块上要出现锁。
3. 并发与“大回圈”如何共处,消除锁?
我们知道如果在“大回圈”中要避免锁操作,那么就用“非同步”,把操作交给执行绪处理。结合这2个特点,我稍微改下资料库架构。
原本的快取层,必然会存在着锁,例如:
public TableCache
private HashMap<String, Object> caches = new ConcurrentHashMap<String, Object>();
这个结构是必然的了,保证了在并发的环境下能够准确的操作快取。但是”大回圈“却不能直接操作这个快取进行修改,所以必须启动一个执行绪去更新快取,例如:
private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();
EXECUTOR.execute(new LatencyProcessor(logs));
class LatencyProcessor implements Runnable
public void run()
这里可以任意的去修改记忆体资料。采用了非同步。
OK,看起来很漂亮。但是又有个问题出现了。在高速存取的过程中,非常有可能快取还没有被更新,就被其他请求再次获取,得到了旧的资料。
4. 如何保证并发环境下快取资料的唯一正确?
我们知道,如果只有读操作,没有写操作,那么这个行为是不需要加锁的。
我使用这个技巧,在快取的上层,再加一层快取,成为”一级快取“,原来的就自然成为”二级快取“。有点像CPU了对不?
一级快取只能被”大回圈“修改,但是可以被并发、”大回圈“同时获取,所以是不需要锁的。
当发生资料库变动,分2种情况:
1)并发环境下的资料库变动,我们是允许有锁的存在,所以直接操作二级快取,没有问题。
2)”大回圈“环境下资料库变动,首先我们把变动资料储存在一级快取,然后交给非同步修正二级快取,修正后删除一级快取。
这样,无论在哪个环境下读取资料,首先判断一级快取,没有再判断二级快取。
这个架构就保证了记忆体资料的绝对准确。
而且重要的是:我们有了一个高效的无锁空间,去实现我们任意的业务逻辑。
最后,还有一些小技巧提升效能。
1. 既然我们的资料库操作已经被非同步处理,那么某个时间,需要插库的资料可能很多,通过对表、主键、操作型别的排序,我们可以删除一些无效操作。例如:
a)同一个表同一个主键的多次UPdate,取最后一次。
b)同一个表同一个主键,只要出现Delete,前面所有操作无效。
2. 既然我们要对操作排序,必然会存在一个根据时间排序,如何保证无锁呢?使用
private final static AtomicLong _seq = new AtomicLong(0);
即可保证无锁又全域性唯一自增,作为时间序列。
如何获取资料库操作的错误资讯
用e.getMessage()
就可以得到你所想要的oracle具体提示资讯,
比如:ORA-000234,XXXXXXX
然后你就可以分析这些字串,对照ORACLE的相关错误号文件,自己做处理。
相关参考
事务概述 事务就是指作为单个逻辑工作单元执行的一组数据操作这些操作要么必须全部成功要么必须全部失败以保证数据的一致性和完整性事务具有ACID属性 原子性自然界最小的事务的内容要么都做要么都不做
java中原子操作是线程安全的论调经常被提到根据定义原子操作是不会被打断地的操作因此被认为是线程安全的实际上有一些原子操作不一定是线程安全的 这个问题出现的原因是尽量减少在代码中同步关键字同
Java开发下的设计模式简单说明 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 设计模式一个设计
患者多在精神因素的促发下急性起病,并迅速发展到严重阶段。临床表现复杂多样,变化多端,但可归纳起来可有以下三大类。 (1)癔症性精神障碍。①意识障碍:癔症患者的意识障碍包括周围环境意识和自我意识障碍。
患者多在精神因素的促发下急性起病,并迅速发展到严重阶段。临床表现复杂多样,变化多端,但可归纳起来可有以下三大类。 (1)癔症性精神障碍。①意识障碍:癔症患者的意识障碍包括周围环境意识和自我意识障碍。
浅谈ASP.NET开发下的MVC设计模式的实现 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nb
——个半世纪以来,化学元素都使用标准单一值的原子量。随着技术的进步,研究人员发现化学元素周期表中有些元素的原子量并不像学
——个半世纪以来,化学元素都使用标准单一值的原子量。随着技术的进步,研究人员发现化学元素周期表中有些元素的原子量并不像学生上化学课时学到的那样一成不变。这意味着未来化学元素周斯表要进行全面改动,十大化
知识大全 能发下白虎(白色虎式)高清蓝光720P版BD-RMVB[2013最新电影的种子或下载链接么
能发下【白虎(白色虎式)】【高清蓝光720P版BD-RMVB】[2013最新电影的种子或下载链接么? 以下文字资料是由(本站网www.cha138.com)小编为大家搜
知识大全 在企业单位上班,领导不给批辞职,自离后没有发下的工资是应该发下还是扣住不发
在企业单位上班,领导不给批辞职,自离后没有发下的工资是应该发下还是扣住不发?只要你是按照正常来办理辞职手续的,安照劳务工和遵守《劳动劳务法则条例》来讲;厂方是无任何权力的扣压员工的工资的。如是处离的话
知识大全 能发下[知电影OMG Oh My God!高清蓝光720P版BD-RMVB.中字的种子或下载链接么
能发下[知电影【OMGOhMyGod!】【高清蓝光720P版BD-RMVB.中字】的种子或下载链接么? 以下文字资料是由(本站网www.cha138.com)小编为大家