如何在代码中开启乐观锁

【 TiDB 使用环境】生产环境
【 TiDB 版本】v7.1.1
【复现路径】做过哪些操作出现的问题
【遇到的问题:问题现象及影响】
【资源配置】
【附件:截图/日志/监控】

想向大家请教一下,默认全局是悲观锁的情况下,如何在用Java 代码实现session 级别的乐观锁。
背景是我有个批量插入的操作,其实写入冲突几乎没有,只是先保证原子性,我应该如何做呢?

https://docs.pingcap.com/zh/tidb/stable/sql-statement-begin#mysql-兼容性

如果是框架包了一层,你需要看看框架的实现。
对于Tidb来说,你begin的时候就可以指定这个事务是乐观的还是悲观的。

https://docs.pingcap.com/zh/tidb/stable/dev-guide-optimistic-and-pessimistic-transaction
这个你可以看看

或者修改tidb 参数,改成乐观的,默认是悲观,这样代码就可以不动了
pessimistic-auto-commit

  • 用来控制开启全局悲观事务模式下 (tidb_txn_mode='pessimistic') 时,自动提交的事务使用的事务模式。默认情况下,即使开启全局悲观事务模式,自动提交事务依然使用乐观事务模式来执行。当开启该配置项后(设置为 true),在全局悲观事务模式下,自动提交事务将也使用悲观事务模式执行。行为与其他显式提交的悲观事务相同。
  • 对于存在冲突的场景,开启本开关可以将自动提交事务纳入全局等锁管理中,从而避免死锁,改善冲突造成死锁带来的时延尖刺。
  • 对于不存在冲突的场景,如果有大量自动提交事务(例如自动提交事务数量占业务数量的比例超过一半甚至更多,需要根据实际情况分析)且单个事务操作数据量较大的情况下,开启该配置项会造成性能回退。例如,自动提交的 INSERT INTO SELECT 语句。
  • 默认值:false
1 个赞

谢谢您的回答,但是我发现一个现象,想再请教:
我写了一段批量插入的代码,并没有去写类似这种代码:
connection.createStatement().executeUpdate(txnComment + "begin optimistic");
就是单纯一个batch insert , 也没有设置auto commit = false。
连接串是:
characterEncoding=utf8&useSSL=false&useServerPrepStmts=true&prepStmtCacheSqlLimit=10000000000&useConfigs=maxPerformance&rewriteBatchedStatements=true&defaultfetchsize=-2147483648

但是我发现Grafana 的metrics 里面竟然都是乐观锁的数据

那就是自动提交了,默认自动提交是乐观的,pessimistic-auto-commit=true 时(默认false),自动提交才是悲观呢。

2 个赞

那么再问您下,batch insert auto commit =false 还能算一次事务吗?能保证原子性吗?或者换句话,batch insert 需要显示开启事务吗?

你好,这个不影响呢,开显式还是隐式,这个要看业务代码与数据库呢,一般都是开自动提交,想用显式的话,那就在代码里加begin ,commit 这些就好。相比mysql的话,tidb 多了乐观锁,所以,参数也需要注意下

1 个赞

乐观事务模型就是直接提交,遇到冲突就回滚。比较适合冲突率不高的场景,因为直接提交大概率会成功,冲突是小概率事件,但是一旦遇到事务冲突,回滚的代价会比较大。
悲观事务模型就是在真正提交事务前,先尝试对需要修改的资源上锁,只有在确保事务一定能够执行成功后,才开始提交。好处是对于冲突率高的场景,提前上锁的代价小于事后回滚的代价,而且还能以比较低的代价解决多个并发事务互相冲突导致谁也成功不了的场景。
冲突率不高的场景下,悲观事务没有乐观事务处理高效。

1 个赞

此话题已在最后回复的 60 天后被自动关闭。不再允许新回复。