最近使用阿里云的rds mysql数据库遇到一个问题,读写分离情景下插入的数据马上去查查不出来,想知道在主键自增的情况下,jdbc的Statment::getGeneratedKeys会不会有类似问题。
更直接点,SELECT LAST_INSERT_ID()这个语句会被分到写库还是读库?
在读写分离的情景下,插入数据后立即查询可能会出现读取不到数据的情况,这是因为在读写分离架构中,写操作会发送到主库,而读操作会发送到从库。由于数据同步需要一定的时间,所以在插入数据后立即查询可能会导致从库还没有完全同步数据,从而查询不到插入的数据。
关于jdbc的Statment::getGeneratedKeys方法,它会返回插入数据时生成的自增主键。在读写分离场景下,如果插入操作发送到主库,则getGeneratedKeys方法会返回主库生成的自增主键值。如果插入操作发送到从库,则getGeneratedKeys方法可能返回null或者抛出异常,因为从库不生成自增主键。
至于SELECT LAST_INSERT_ID()这个语句,默认情况下会被发送到主库执行。LAST_INSERT_ID()函数是MySQL提供的用于获取最后插入的自增主键值的函数,它返回的是在当前连接中最后一次插入的自增主键值。由于写操作发送到主库,所以主库中的最后一次插入的自增主键值可以通过这个函数获取到。
在读写分离的场景下,SELECT LAST_INSERT_ID()这个语句会被分到写库。因为在执行插入操作后,LAST_INSERT_ID()函数会返回最后一个插入记录的自增主键值,这个值是在写库中生成的。所以在使用jdbc的Statement::getGeneratedKeys方法时,不会出现类似问题。
在MySQL读写分离的场景下,LAST_INSERT_ID()
函数或JDBC Statement::getGeneratedKeys
方法用于获取自增主键的最新值时,通常不会有问题。
LAST_INSERT_ID()
是一个会话级别的函数,它返回的是当前连接最后一次执行INSERT操作后生成的自动增长ID。当你在一个写库上执行插入操作时,该函数会在同一数据库连接中正确地返回新插入记录的自增主键值。
对于JDBC中的getGeneratedKeys
方法,在执行包含自增主键字段的INSERT语句之后调用,也会返回新插入行的自增主键值,这个行为同样与数据库的读写分离设置无关,因为它发生在写入事务过程中,并且是在同一个数据库连接中完成的。
总结来说,由于主键自增是写操作,所以在主库上执行插入并获取自增ID的过程不受读写分离的影响,因此不论是使用LAST_INSERT_ID()
还是getGeneratedKeys
,只要保证插入操作是在写库上执行的,就不会有查不到新插入数据的问题。
在读写分离场景下,对于MySQL数据库,LAST_INSERT_ID()
或通过JDBC的 Statement::getGeneratedKeys
方法获取自动生成的主键值(比如针对自增主键的情况),这类操作应当始终指向写入数据的主库,而不是从库。
原因在于LAST_INSERT_ID()
获取的是当前会话最后一次执行的INSERT操作产生的自动增长ID,这个值仅在执行插入操作的数据库实例中有效。在主从架构中,写入操作发生在主库上,因此要获取最新的自增ID,查询请求必须发送到主库。
当应用程序通过JDBC执行带有自增主键且需要获取生成主键值的INSERT语句时,可以配置Statement或PreparedStatement来检索这些生成的键,此时驱动程序会确保这个请求被导向到正确的数据库节点(即主库)。
总结来说,在阿里云RDS MySQL的读写分离环境下,为了获取最新插入记录的自增主键值,不论是通过LAST_INSERT_ID()
函数还是使用JDBC的getGeneratedKeys
方法,都会指向主库,不会存在查不到新插入数据的问题。同时,合理的数据库连接池配置应该能保证这一点,即执行写入操作后立即执行的获取自增ID的操作会保持在同一数据库连接上,从而避免由于读写分离带来的数据不一致情况。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
阿里云关系型数据库主要有以下几种:RDS MySQL版、RDS PostgreSQL 版、RDS SQL Server 版、PolarDB MySQL版、PolarDB PostgreSQL 版、PolarDB分布式版 。