begintransaction(mysql更新如果失败怎么处理)

精英怪
广告

begintransaction,mysql更新如果失败怎么处理?

仔细点哦

begintransaction(mysql更新如果失败怎么处理)

Release r = dao.findRelease(releaseId); Book b = dao.findBook(bookId); if(r != null && b != null){ Session session = HibernateUtils.getSession(); Transaction tx = session.beginTransaction(); try{ dao.cancelBook(r, b); dao.updateReleaseCounts(r, b); }catch(Exception e){ tx.rollback(); } tx.commit(); }

caffe多标签学习有没有方法显示整体的精确度?

拷贝convert_imageset,生成新工程convert_imageset_multi_label

修改源码

std::ifstream infile(argv[2]); std::vector<std::pair<std::string, std::vector<float>> > lines; std::string filename; std::string label_count_string = argv[5]; int label_count = std::atoi(label_count_string.c_str()); std::vector<float> label(label_count); while (infile >> filename) { for (int i = 0; i < label_count; i++) infile >> label[i]; lines.push_back(std::make_pair(filename, label)); } if (FLAGS_shuffle) { // randomly shuffle data LOG(INFO) << "Shuffling data"; shuffle(lines.begin(), lines.end()); } LOG(INFO) << "A total of " << lines.size() << " images."; if (encode_type.size() && !encoded) LOG(INFO) << "encode_type specified, assuming encoded=true."; int resize_height = std::max<int>(0, FLAGS_resize_height); int resize_width = std::max<int>(0, FLAGS_resize_width); // Create new DB scoped_ptr<db::DB> db_image(db::GetDB(FLAGS_backend)); scoped_ptr<db::DB> db_label(db::GetDB(FLAGS_backend)); db_image->Open(argv[3], db::NEW); db_label->Open(argv[4], db::NEW); scoped_ptr<db::Transaction> txn_image(db_image->NewTransaction()); scoped_ptr<db::Transaction> txn_label(db_label->NewTransaction());// // Create new DB// scoped_ptr<db::DB> db(db::GetDB(FLAGS_backend));// db->Open(argv[3], db::NEW);// scoped_ptr<db::Transaction> txn(db->NewTransaction()); // Storing to db std::string root_folder(argv[1]); Datum datum_image; Datum datum_label; int count = 0; int data_size = 0; bool data_size_initialized = false; for (int line_id = 0; line_id < lines.size(); ++line_id) { bool status; std::string enc = encode_type; if (encoded && !enc.size()) { // Guess the encoding type from the file name string fn = lines[line_id].first; size_t p = fn.rfind('.'); if ( p == fn.npos ) LOG(WARNING) << "Failed to guess the encoding of '" << fn << "'"; enc = fn.substr(p); std::transform(enc.begin(), enc.end(), enc.begin(), ::tolower); } status = ReadImageToDatum(root_folder + lines[line_id].first, lines[line_id].second[0], resize_height, resize_width, is_color, enc, &datum_image); if (status == false) continue; if (check_size) { if (!data_size_initialized) { data_size = datum_image.channels() * datum_image.height() * datum_image.width(); data_size_initialized = true; } else { const std::string& data = datum_image.data(); CHECK_EQ(data.size(), data_size) << "Incorrect data field size " << data.size(); } } // sequential string key_str = caffe::format_int(line_id, 8) + "_" + lines[line_id].first; // Put in db string out; CHECK(datum_image.SerializeToString(&out)); txn_image->Put(key_str, out); ////////////////////////////////////////////////////////////////////////// datum_label.set_channels(label_count); datum_label.set_height(1); datum_label.set_width(1); datum_label.clear_data(); datum_label.clear_float_data(); datum_label.set_encoded(false); std::vector<float> label_vec = lines[line_id].second; for (int i = 0; i < label_vec.size();i++) { datum_label.add_float_data(label_vec[i]); } string out_label; CHECK(datum_label.SerializeToString(&out_label)); txn_label->Put(key_str, out_label); ////////////////////////////////////////////////////////////////////////// if (++count % 1000 == 0) { // Commit db txn_image->Commit(); txn_image.reset(db_image->NewTransaction()); txn_label->Commit(); txn_label.reset(db_label->NewTransaction()); LOG(INFO) << "Processed " << count << " files."; } } // write the last batch if (count % 1000 != 0) { txn_image->Commit(); txn_label->Commit(); LOG(INFO) << "Processed " << count << " files."; }

上述方式使用了二个data层,编译之后,使用如下方式生成:

Build\x64\Release>convert_imageset_multi_label.exe ./ train.txt data/train_image_lmdb data/train_label_lmdb 4

train.txt文件格式如下:

data/00A03AF5-41C7-4966-8EF3-8B2C90DCF75C_cgfn.jpg 1 2 3 6data/00A15FBD-9637-44C5-B2E7-81611263C88C_tmph.jpg 2 5 6 4

网络配置文件需要加入slice层将标签分割开来

layer { name: "slice" type: "Slice" bottom: "label" top: "label_1" top: "label_2" top: "label_3" top: "label_4" slice_param { axis: 1 slice_point: 1 slice_point: 2 slice_point: 3 }}

也可以通过python直接生成lmdb格式,其方式如下:

# -*- coding: utf-8 -*-"""Created on Sat Dec 24 20:57:28 2016 @author: zhouly"""import lmdbfrom skimage import ioimport numpy as np import syscaffe_root = '../../'sys.path.insert(0, caffe_root + '/python')import caffeimport cv2root = '../../'file_input=open(root+'data/train.txt','r') in_image_db=lmdb.open(root+'examples/99/train_image_lmdb', map_size=int(1e12)) in_label_db=lmdb.open(root+'examples/99/train_label_lmdb', map_size=int(1e12)) in_image_txn = in_image_db.begin(write=True) in_label_txn = in_label_db.begin(write=True)for in_idx, in_ in enumerate(file_input): content = in_.strip() content = content.split(' ') im_file = root + 'data/verification/' + content[0] try: im = io.imread(im_file) except: print '-------------------------', im_file continue im = im[:,:, 3] im = cv2.resize(im, (224, 224), interpolation=cv2.INTER_LINEAR) data = np.zeros((3, 224, 224), np.uint8) data[0, :, :] = im[:, :] data[1, :, :] = im[:, :] data[2, :, :] = im[:, :] im_dat = caffe.io.array_to_datum(data) in_image_txn.put('{:0>10d}'.format(in_idx), im_dat.SerializeToString()) print 'data train: {} [{}]'.format(content[0], in_idx + 1) del im_file, im, im_dat, data target_label = np.zeros((4, 1, 1)) target_label[0, 0, 0] = int(content[1]) target_label[1, 0, 0] = int(content[2]) target_label[2, 0, 0] = int(content[3]) target_label[3, 0, 0] = int(content[4]) label_data = caffe.io.array_to_datum(target_label) in_label_txn.put('{:0>10d}'.format(in_idx), label_data.SerializeToString()) del target_label, label_data in_image_txn.commit() in_label_txn.commit() in_image_db.close() in_label_db.close() file_input.close()

如何使用消息队列解决分布式事务?

消息事务是指一系列的生产、消费操作可以要么都完成,要么都失败,类似数据库的事务。在此用Kafka 为例做进一步解说吧!

一、基本概念

为了支持事务,Kafka 0.11.0版本引入以下概念:

1.事务协调者:类似于消费组负载均衡的协调者,每一个实现事务的生产端都被分配到一个事务协调者(Transaction Coordinator)。

2.引入一个内部Kafka Topic作为事务Log:类似于消费管理Offset的Topic,事务Topic本身也是持久化的,日志信息记录事务状态信息,由事务协调者写入。

3.引入控制消息(Control Messages):这些消息是客户端产生的并写入到主题的特殊消息,但对于使用者来说不可见。它们是用来让broker告知消费者之前拉取的消息是否被原子性提交。

4.引入TransactionId:不同生产实例使用同一个TransactionId表示是同一个事务,可以跨Session的数据幂等发送。当具有相同Transaction ID的新的Producer实例被创建且工作时,旧的且拥有相同Transaction ID的Producer将不再工作,避免事务僵死。

5.Producer ID:每个新的Producer在初始化的时候会被分配一个唯一的PID,这个PID对用户是不可见的。主要是为提供幂等性时引入的。

6.Sequence Numbler。(对于每个PID,该Producer发送数据的每个<Topic, Partition>都对应一个从0开始单调递增的Sequence Number。

7.每个生产者增加一个epoch:用于标识同一个事务Id在一次事务中的epoch,每次初始化事务时会递增,从而让服务端可以知道生产者请求是否旧的请求。

8.幂等性:保证发送单个分区的消息只会发送一次,不会出现重复消息。增加一个幂等性的开关enable.idempotence,可以独立与事务使用,即可以只开启幂等但不开启事务

二、事务流程

1、查找事务协调者

生产者会首先发起一个查找事务协调者的请求(FindCoordinatorRequest)。协调者会负责分配一个PID给生产者。类似于消费组的协调者。

2、获取produce ID

在知道事务协调者后,生产者需要往协调者发送初始化pid请求(initPidRequest)。这个请求分两种情况:

●不带transactionID

这种情况下直接生成一个新的produce ID即可,返回给客户端

●带transactionID

这种情况下,kafka根据transactionalId获取对应的PID,这个对应关系是保存在事务日志中(上图2a)。这样可以确保相同的TransactionId返回相同的PID,用于恢复或者终止之前未完成的事务。

3、启动事务

生产者通过调用beginTransaction接口启动事务,此时只是内部的状态记录为事务开始,但是事务协调者认为事务开始只有当生产者开始发送第一条消息才开始。

4、消费和生产配合过程

这一步是消费和生成互相配合完成事务的过程,其中涉及多个请求:

●增加分区到事务请求

当生产者有新分区要写入数据,则会发送AddPartitionToTxnRequest到事务协调者。协调者会处理请求,主要做的事情是更新事务元数据信息,并把信息写入到事务日志中(事务Topic)。

●生产请求

生产者通过调用send接口发送数据到分区,这些请求新增pid,epoch和sequence number字段。

●增加消费offset到事务

生产者通过新增的snedOffsets ToTransaction接口,会发送某个分区的Offset信息到事务协调者。协调者会把分区信息增加到事务中。

●事务提交offset请求

当生产者调用事务提交offset接口后,会发送一个TxnOffsetCommitRequest请求到消费组协调者,消费组协调者会把offset存储在__consumer-offsets Topic中。协调者会根据请求的PID和epoch验证生产者是否允许发起这个请求。 消费offset只有当事务提交后才对外可见。

5、提交或回滚事务

用户通过调用commitTransaction或abortTranssaction方法提交或回滚事务。

●EndTxnRequest

当生产者完成事务后,客户端需要显式调用结束事务或者回滚事务。前者会使得消息对消费者可见,后者会对生产数据标记为Abort状态,使得消息对消费者不可见。无论是提交或者回滚,都是发送一个EndTnxRequest请求到事务协调者,写入PREPARE_COMMIT或者PREPARE_ABORT信息到事务记录日志中(5.1a)。

●WriteTxnMarkerRequest

这个请求是事务协调者向事务中每个TopicPartition的Leader发送的。每个Broker收到请求后会写入COMMIT(PID)或者ABORT(PID)控制信息到数据日志中(5.2a)。

这个信息用于告知消费者当前消息是哪个事务,消息是否应该接受或者丢弃。而对于未提交消息,消费者会缓存该事务的消息直到提交或者回滚。

这里要注意,如果事务也涉及到__consumer_offsets,即该事务中有消费数据的操作且将该消费的Offset存于__consumer_offsets中,Transaction Coordinator也需要向该内部Topic的各Partition的Leader发送WriteTxnMarkerRequest从而写入COMMIT(PID)或COMMIT(PID)控制信息(5.2a 左边)。

●写入最终提交或回滚信息

当提交和回滚信息写入数据日子后,事务协调者会往事务日志中写入最终的提交或者终止信息以表示事务已经完成(图5.3),此时大部分于事务有关系的消息都可以被删除(通过标记后面在日志压缩时会被移除),我们只需要保留事务ID以及其时间戳即可。

发表评论

快捷回复: 表情:
AddoilApplauseBadlaughBombCoffeeFabulousFacepalmFecesFrownHeyhaInsidiousKeepFightingNoProbPigHeadShockedSinistersmileSlapSocialSweatTolaughWatermelonWittyWowYeahYellowdog
评论列表 (暂无评论,159人围观)

还没有评论,来说两句吧...