1、先插入再查询

BEGIN;
INSERT INTO video (CREATE_TIME, UPDATE_TIME, VERSION, VID, VIDEO_NAME, SPEED, RATE, HORIZONTAL, VERTICAL, SIZE, LIB_ID, ALARM_THRESHOLD, ONLINE, STATUS, REMARK) 
VALUES(NOW(),NOW(),0,'vidtest','test.mp4',1,1,1,1,'1',1,0.1,20,20,'');
SELECT * FROM video WHERE VID = 'vidtest';
ROLLBACK;

在事务内部的SELECT语句可以查询到数据,但是回滚后,不能查询到数据

2、先删除再查询

BEGIN;
DELETE FROM video WHERE VID = 'vidtest';
SELECT * FROM video WHERE VID = 'vidtest';
ROLLBACK;

在事务内部的查询不能查询到数据,但是回滚后,可以查询到数据

二、原因说明:

在同一个事务中,数据需要保证一致性,也就是说,在当前的事务中,删除了就是看不到了,插入了就是多了一条数据,但这些操作都是在当前事务内部的。对于外界是隔离的。如果我们开启事务插入一条数据,还没有提交,这时新开一个事务,去查询数据,是发现不了未提交数据的。

三,基于mybatis进行测试

1、先插入再更新

//这两个操作是在同一个方法中 方法是通过Transactional注解实现事务的
@Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
//插入一条数据
int i = videoDao.insert(videoPo);
//更新一条数据
int j = videoDao.updateVid(videoPo.getId(),vid);

控制台打印的sql语句

Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5cfedd40]
JDBC Connection [ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@6624f1eb]]] will be managed by Spring
==>  Preparing: INSERT INTO video (CREATE_TIME, UPDATE_TIME, VERSION, VID, VIDEO_NAME, SPEED, RATE, HORIZONTAL, VERTICAL, SIZE, LIB_ID, ALARM_THRESHOLD, ONLINE, STATUS, REMARK) VALUES (now(), now(), 0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
==> Parameters: vid60c7d86a-111b-45ec-b25e-2100b6f9a588(String), 1.mp4(String), 1(Integer), 1(Integer), 50(Integer), 20(Integer), 30*30(String), 1(Long), 0.1000(BigDecimal), 10(Integer), 20(Integer), null
<==    Updates: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5cfedd40]
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5cfedd40] from current transaction
==>  Preparing: UPDATE video SET VID = ? WHERE ID = ? 
==> Parameters: vid14(String), 14(Long)
<==    Updates: 1

mybatis会将两条执行语句在同一个sqlSession中执行。

2、先删除再查询

//这两个操作是在同一个方法中 方法是通过Transactional注解实现事务的
@Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
//删除一条数据
int i = videoDao.deleteVedioByVid(vid);
//查询被删除的数据
VideoPo videoPo = videoDao.getVideoByVid(vid);

控制台打印的sql语句

Creating a new SqlSession Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3b1ca134] JDBC Connection [ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@6624f1eb]]] will be managed by Spring ==> Preparing: DELETE FROM video WHERE VID = ? ==> Parameters: vidtest(String) <== Updates: 1 Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3b1ca134] Creating a new SqlSession Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@55d43e72] JDBC Connection [ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@1dfa23fe]]] will be managed by Spring ==> Preparing: SELECT * FROM video WHERE VID = ? ==> Parameters: vidtest(String) <== Columns: ID, CREATE_TIME, UPDATE_TIME, VERSION, VID, VIDEO_NAME, SPEED, RATE, HORIZONTAL, VERTICAL, SIZE, LIB_ID, ALARM_THRESHOLD, ONLINE, STATUS, REMARK <== Row: 12, 2018-10-19 15:05:15.0, 2018-10-19 15:05:15.0, 0, vidtest, test.mp4, 1, 1, 1, 1, 1, 1, 0.1000, 20, 20, <== Total: 1

mybatis创建了两个sqlSession。

后来我又测试了先删除再更新的场景,发现更新失败。

结论: mybatis会再插入或删除后,进行更新操作时使用同一个sqlSession,查询时新建sqlSession。

一,现象展示1、先插入再查询BEGIN;INSERT INTO video (CREATE_TIME, UPDATE_TIME, VERSION, VID, VIDEO_NAME, SPEED, RATE, HORIZONTAL, VERTICAL, SIZE, LIB_ID, ALARM_THRESHOLD, ONLINE, STATUS, REMARK) VALUES(NOW()...
数据库和操作系统一样,是一个多用户使用的共享资源。当多个用户并发地存取数据 时,在数据库中就会产生多个 事务 同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。加锁是实现数据库并 发控制的一个非常重要的技术。在实际应用中经常会遇到的与锁相关的异常情况,当两个 事务 需要一组有冲突的锁,而不能将 事务 继续下去的话,就会出现死锁,严 重影响应用的正常执行。 在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。当数据对象被加上排它锁时,其他的 事务 不能对它读取和修改。加了共享锁的数据对象可以被其他
分别创建增加、 删除 、更新的触发器(Trigger)来达到两张表之间数据同步的目的。 1:数据同步增加: 如有两张表——A表和B表,创建触发器使当A表 插入 数据后B表也同步 插入 数据。其中B表 插入 数据的字段需要同A表中的字段相对应。 代码如下: CREATE TRIGGER 触发器名称 ON A表 AFTER INSERT AS BEGIN INSERT INTO B表(B表字段1,B表字段2,B表字段3) SELECT A表字段1,A表字段2,A表字段3 FROM INSERTED END 2.数据同步 删除 : 如有两张表——A表和B表,创建触发器使当A表 删除 数据后B表也同步 删除 数据。其中B表与
Object res = this.selectById(obj.getId()); res: null; 线上的一个坑,做了读写分离以后,有一个场景因为想方法复用,只传入一个ID就好,直接去库里查出一个对象再做后续处理,结果查不出来, 事务 隔离级别各种也都排查了,最后发现是读写分离的问题,所以换个思路去实现吧。 补充知识: MySQL INSERT 插入 条件判断:如果不存在则 插入 我们经常需要进行sql的批量 插入 ,要求:该条记录不存在则 插入 ,存在则不 插入 。如果使用一条IN
def fieldbyname(self, namestr): self.env.cr.execute("SELECT "+namestr+" FROM dzjl_muoban WHERE id=%s", [self.id]) c_id = self.env.cr.fetchone() # print(c_id) # print(namestr) return c_id.
Mysql 事务 操作失败如何解决 事务 的原子性 : 事务 是数据库的逻辑工作单位, 事务 中包含的各操作要么都做,要么都不做 。 要实现 事务 的原子性,单单靠一条commit或是rollback命令还是不行的,因为例如commit命令它只是将一个 事务 中执行成功的DML语句提交给数据库里。如果要实现 事务 的原子性,则就需要commit和rollback命令配合上程序上的一个业务逻辑才能可以,具体业务逻辑代码如下示例代码:      程序中打开了 事务 进行 插入 ,但是没有commit,表中的数据已经存在,就是回滚也不能 删除 插入 的数据     本表的Storage Engine 为myisam
要介绍几个概念: 1.    MVCC(Multi-Vers ion Concurren):多版本并发控制,是 MySQL 事务 型存储引擎如InnoDB。 2.    trx_id与roll_pointer: MySQL 会给每个表加2个字段,trx_id是 事务 字段id,roll_pointer为回滚字段。 3. 事务 会有一个ID,只有更新( 删除 插入 是特性的更新)会生成 事务 ID。 4.    在 事务 中进行更新,会把原记录放到undo回滚日志里面,然后再 插入 一条新记录,这个新记录的roll_pointer指向刚刚放到undo回滚日志里面的那个记录。 5.    在 事务 中使用select不会生
近来稍有时间研究了下 MYSQL 中的 事务 操作,在很多场合下很是适用,譬如在注册的时候需要初始化很多张关联表的时候,问答回复的时候需要至少同时操作两张表,这些都会在某些时候只能成功更新一张表,而另外的SQL语句出现错误,正常的操作会导致初始化了一张表 ,其他的都木有能初始化,这个时候就会导致用户表里的用户信息已经执行 插入 ,导致提示注册失败,但是用户已经注册了部分信息,这个时候需要程序员去数据库 删除 相应的数据是一个比较不好的事情。 因此这边考虑使用 事务 事务 可以进行模拟SQL操作,当所有的SQL都操作成功的时候才进行SQL操作,只要有一个操作失败就回滚当前 事务 的所有SQL操作,避免出现上面描述中出现
因此,正确的原子操作是真正被执行过的。是物理执行。 在当前 事务 中确实能看到 插入 的记录。最后只不过 删除 了。但是AUTO_INCREMENT不会应 删除 而改变值。 1、为什么auto_increament没有回滚? 因为innodb的auto_increament的计数器记录的当前值是保存在存内存中的,并不是存在于磁盘上,当 mysql server处于运行的时候,这个计数值只会随着insert改增长,不会随着delete而减少。而当 mysql server启动时,当我们需要去 查询 auto_increment计数值时, mysql 便会自动执行:SELECT MAX(id) FROM 表名 FOR UPD
# 查询 是否存在记录 mycursor.execute("SELECT * FROM customers WHERE email = %s", ("john@example.com",)) result = mycursor.fetchone() if result: # 更新记录 sql = "UPDATE customers SET firstname = %s, lastname = %s WHERE email = %s" mycursor.execute(sql, ("John", "Doe", "john@example.com")) else: # 插入 新纪录 sql = "REPLACE INTO customers (firstname, lastname, email) VALUES (%s, %s, %s)" mycursor.execute(sql, data) # 提交 事务 mydb.commit() # 输出结果 print(mycursor.rowcount, "record(s) affected") 注意,REPLACE INTO语句只适用于有主键或唯一索引的表,因为它会根据主键或唯一索引来判断记录是否存在。如果表没有主键或唯一索引,可以考虑使用INSERT ... ON DUPLICATE KEY UPDATE语句。